Введение в скриптинг: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
 
(23 intermediate revisions by 12 users not shown)
Line 1: Line 1:
Ресурсы - ключевая часть MTA. Ресурс - папка или zip архив, который содержит набор файлов, также мета файл, который рассказывает серверу как нужно загружать ресурс и из каких файлов он состоит. Это как программа в операционной системе - может быть запущен и остановлен, а также могут работать несколько ресурсов одновременно. Всё содержымое скрипта находится в ресурсе
Ресурсы являются ключевой частью MTA. Ресурс - это папка или zip-архив, содержащий набор файлов, а также meta-файл, который описывает серверу как нужно загружать ресурс и из каких файлов он состоит. Ресурс играет практически ту же роль, что и программа в операционной системе - он может быть запущен и остановлен, при этом несколько ресурсов могут быть запущены одновременно.  


==Создаем простейший скрипт==
Все, связанное со скриптингом, находится в ресурсах. Назначение ресурса и определяет, является ли он модом, картой или чем-либо еще. MTA поставляется с ресурсами, которые вы можете выборочно использовать в своих модах, например, maplimits, позволяющий удерживать игроков в рамках указанных границ карты, или deathpickups, создающий пикапы с оружием.
Для начала давайте сделаем команду "createvehicle" которая будет создавать машину рядом с игроком.
{{tip|Первым шагом в изучении Lua-скриптинга должен быть выбор Lua-редактора. Это намного упрощает скриптинг. Мы рекомендуем [http://notepad-plus.sourceforge.net/uk/site.htm Notepad++] или [http://luaedit.sourceforge.net/ LuaEdit]. Также имеется неофициальный [[RU/MTASE|MTA Script Editor]] (на стадии разработки), который вы можете испытать.}}
===Подготовка===
Как написано выше, скрипт содержится в папке или архиву, делаем папку с названием "createvehicle". Имя папки должно соответствовать имени скрипта, это используется для запуска или остановки скрипта.


Каждому скрипту нужен "meta.xml" файл. В этом файле хранятся данные о авторе скрипта, описание и путь к скрипту. В нашем случае мы будем делать скрипт который будет делать машину возле игрока.
==Создание работающего скрипта==
Для начала мы узнаем, как пошагово сделать простой скрипт, который позволит игроку прогуливаться по городу.
===Где находятся все скрипты?===
Давайте взглянем на файловую структуру скрипта. Зайдите в папку сервера MTA и пройдите по следующему пути:


/server/mods/deathmatch/resources/
Вы увидите множество .zip-архивов, являющихся упакованными пробными скриптами, поставляемыми с MTA DM. Каждый файл - это "ресурс", все они будут распакованы и загружены сервером при его старте. Чтобы создать свой собственный ресурс, просто создайте папку и назовите ее так, как хотите. В нашем случае мы назовем ее "myserver".
Теперь вам нужно зайти в эту папку:
/server/mods/deathmatch/resources/myserver/
===Идентификация вашего ресурса===
Чтобы сервер мог узнать о содержимом того или иного ресурса, в нем должен быть создан файл ''meta.xml'', перечисляющий его содержимое. Этот файл должен быть расположен в корневой директории ресурса, в нашем случае - это папка "myserver". Просто создайте текстовый файл, назовите его "meta.xml" и откройте с помощью Блокнота (notepad).
В файл ''meta.xml'' введите следующий код:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<meta>
<meta>
  <info author="YourName" description="A few simple commands" />
    <info author="YourName" type="gamemode" name="Kontol memek" description="My Mta Sa" />
  <script src="script.lua" />
    <script src="script.lua" type="server"/>
</meta>
</meta>
</syntaxhighlight>
</syntaxhighlight>
В теге ''<info />'' есть поле "type", которое говорит о том, что данный ресурс - ''gamemode'' ("мод", игровой режим), а не обычный include или ''map'' (карта), о которых мы поговорим чуть позже. Gamemode - то, что вам нужно, чтобы создать независимый сервер.


"script.lua" - это имя файла самого скрипта в той же самой директории что и "meta.xml" (ОБЯЗАТЕЛЬНО!)
Тег ''<script />'' оговаривает сценарии (скрипты), которые содержит ресурс, о них мы сейчас и поговорим.
Сейчас нам надо создать "script.lua" файл, после чего у нас в папке будут два файла:
Поле "type" говорит о том, что данный скрипт "script.lua" будет выполняться на стороне сервера.


<syntaxhighlight lang="xml">
===Создание простого скрипта===
/createvehicle/meta.xml
Заметьте, что в теге ''<script /> 'script.lua' - файл не находится в какой-либо вложенной директории. Следовательно, мы создадим файл в той же папке, что и meta.xml. Теперь можно скопировать и вставить в script.lua следующий код:
/createvehicle/script.lua
<syntaxhighlight lang="lua">
local spawnX, spawnY, spawnZ = 1959.55, -1714.46, 10
function joinHandler()
spawnPlayer(source, spawnX, spawnY, spawnZ)
fadeCamera(source, true)
setCameraTarget(source, source)
outputChatBox("Welcome to My Server", source)
end
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)
</syntaxhighlight>
</syntaxhighlight>
Этот скрипт заспавнит вас по координатам (x, y, z), указанным выше, когда вы зайдете на сервер. Обратите внимание, что функция ''fadeCamera'' обязательно должна быть, иначе экран будет черным. К тому же, в релизах новее DP2 вам нужно установить цель для камеры (иначе все, что увидит игрок - синее небо).


===Writing the script===
Переменная '''source''' указывает на того, кто вызвал срабатывание события. Так как данный код срабатывает при заходе какого-либо игрока, эта переменная используется для установления того, кто зашел. Так что спавнить будет именно этого игрока, а не всех сразу или кого-нибудь случайно.
Let's start with the contents of the ''script.lua'' file. As mentioned above, we want to provide a command to create a vehicle beside your current position in the game. Firstly we need to create a function we want to call and a command handler that creates the command the player will be able to enter in the console.
 
Если присмотреться к [[addEventHandler]], вы заметите три вещи: 'onPlayerJoin', указывающий на то, когда (почему) произойдет срабатывание; getRootElement(), который показывет благодаря кому/чему может произойти срабатывание (getRootElement() - это все/всё) и joinHandler, который отвечает за функцию, на которую произойдет переключение при срабывании события. Остальные подробности будут изложены позже и на отдельном примере, а теперь давайте просто запустим сервер и попрактикуемся!
 
===Запуск скрипта===
Чтобы запустить сервер, просто запустите исполняемый файл (на Windows - .exe) по адресу ''MTA San Andreas x.x/server'', где x.x - номер версии MTA. Сначала будут показаны данные сервера; запомните номер порта (server port), который понадобится вам при подключении. Затем сервер загрузит все ресурсы в папку mods/deathmatch/resources/ и позже будет "ready to accept connections!", то есть готов принимать игроков.
 
Перед тем, как вы подключитесь к серверу, нужно обязательно запустить мод (gamemode). Введите "start myserver" и нажмите Enter. Сервер запустит мод, который вы только что создали, а также начнет отображать различные ошибки и предупреждения, если таковые будут. Теперь можно запустить клиент MTA DM и подключиться через "Quick Connect", воспользовавшись IP-адресом вашего сервера и номером порта, на который мы ранее обратили ваше внимание. Если все пройдет по плану, через несколько секунд ваш персонаж сможет пройтись по улицам Los Santos'а.
 
Затем мы добавим в скрипт команду, которую игроки смогут использовать для того, чтобы спавнить рядом с собой транспортное средство. Вы можете это пропустить и взглянуть на статью про более продвинутый скриптинг с использованием [[RU/Map manager|Map Manager]], которая продолжит это руководство. Еще одним ответвлением данного руководства является [[Введение в скриптинг GUI]]: прочитав его, вы узнаете, как рисуется и программируется Graphical User Interface в MTA:DM.
 
==Создание простой команды==
Давайте вернемся к содержимому файла ''script.lua''. Как уже было сказано, мы хотим предоставить команду для создания трансортного средства рядом с вашей текущей позицией в игре. Во-первых, нам понадобится создать функцию, которую мы будем вызывать, и обработчик команды, который сделает команду доступной для выбора игроком посредством ввода ее в консоли.


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- create the function the command handler calls, with the arguments: thePlayer, command, vehicle
-- создаем функцию, вызываемую обработчиком команды, с аргументами: thePlayer, command, vehicleModel
function createVehicleForPlayer(thePlayer, command, vehicle)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
   -- create a vehicle and stuff
   -- создаем транспортное средство и другое
end
end


-- create a command handler
-- создаем обработчик команды
addCommandHandler("createvehicle", createVehicleForPlayer)
addCommandHandler("createvehicle", createVehicleForPlayer)
</syntaxhighlight>
</syntaxhighlight>
''Note: Function names are clickable in code examples on the wiki and linked to the functions' documentation.''
''Заметка: Клик по названию функции в образце кода перенаправит на соответствующую страницу с ее описанием.''


====About command handlers====
====Про обработчики команд====
The first argument of [[addCommandHandler]] is the name of the command the player will be able to enter, the second argument is the function this will call, in this case ''createVehicleForPlayer''.
Первый аргумент [[addCommandHandler]] - имя команды, которая будет доступна игроку, второй аргумент - функция, на которую произойдет переключение, в данном случае - это ''createVehicleForPlayer''.


If you have already experience in scripting, you will know that you call a function like this:
Если у вас уже есть опыт в скриптинге, вы знаете, что функции вызываются примерно следующим образом:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
functionName(argument1, argument2, argument3, ..)
functionName(argument1, argument2, argument3, ..)
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="lua">
functionName(thePlayer, commandName, argument3, ..)
</syntaxhighlight>
Присмотревшись ко второму образцу (выше), мы увидим, что argument1 - thePlayer, а argument2 - commandName. thePlayer - тот, кто набрал команду, так что как бы вы ее не вводили, переменная будет содержать игрока, который ее активировал. commandName - команда, которую ввели. Так что при вводе "/greet", этот аргумент будет содержать "greet". Argument 3 - еще что-то, введенное игроком после, об этом вы узнаете чуть позже из данного руководства. Никогда не забывайте, что первые 2 аргумента являются стандартными, но назвать вы их можете по своему усмотрению. То есть важен порядок, а не название.


We called the [[addCommandHandler]] function this way already and since ''createVehicleForPlayer'' is a function too, it can be called that way as well. But we are using a command handler for that, which calls it in a similiar manner, internally.
Мы уже вызывали таким образом функцию [[addCommandHandler]], и так как ''createVehicleForPlayer'' - также функция, ее тоже можно так вызвать. Но мы для этого используем обработчик команд, который вызывает ее схожим образом, только внутренне.


For example: Someone types "createvehicle 468" ingame in the console to spawn a Sanchez, the command handler calls the createVehicleForPlayer function, as '''if''' we would have this line of code in the script:
Например: Кто-то вводит "createvehicle 468" в игровой консоли, чтобы заспавнить Sanchez, обработчик команд вызывает функцию createVehicleForPlayer, как '''если бы''' мы имели в скрипте следующую строку кода:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
createVehiceForPlayer(thePlayer,"createvehicle","468") -- thePlayer is the player element of the player who entered the command
createVehicleForPlayer(thePlayer,"createvehicle","468") -- thePlayer - элемент типа player игрока, который ввел команду
</syntaxhighlight>
</syntaxhighlight>
As we can see, it provides several parameters: the player who called the command, the command he entered and whatever text he had after that, in this case "468" as vehicle id for the Sanchez. The first two parameters are the same with all command handlers, which you can read on the [[addEventHandler]] page. For this fact, you always have to define at least those two parameters to use any after that (for example to process text that was entered after the command, like in our example the vehicle model id).
Как можно заметить, предоставляются несколько параметров: игрок, который вызвал команду, сама команда, которую он ввел, и какой-нибудь текст, который он после нее ввел, в данном случае - "468" в качестве id трансопртного средства, отвчечающего за Sanchez. Первые два параметра одинаковы для всех обработчиков команд, о них вы можете почитать на странице [[addCommandHandler]]. Фактически, вам всегда придется определять как минимум эти два параметра, чтобы смочь использовать какие-нибудь другие, идущие после них (например, для обработки текста, введенного после команды, как id модели транспортного средства в нашем случае).


''Note: You have to add the command handler AFTER you defined the handler function, else it can't find it. The order of execution matters.''
''Заметка: Обработчик команды надо добавлять именно ПОСЛЕ функции, на которую он сошлется, иначе она не будет найдена. Порядок имеет значение!''


====Writing the function====
====Написание функции====
In order to fill the function we created, we need to think about what we have to do:
Чтобы заполнить созданную нами функцию, нам следует подумать, что нам предстоит сделать:
* Get the players position, so we know where to spawn the vehicle (we want it to appear right beside the player)
* Получить позицию игрока, чтобы знать, где спавнить ТС (мы хотим, чтобы оно появлялось прямо рядом с игроком)
* Calculate the position we want to spawn the vehicle at (we don't want it to appear in the player)
* Вычислить позицию, на которой мы хотим заспавнить ТС (мы же не хотим его появления на голове у игрока)
* Spawn the vehicle
* Собственно, заспавнить ТС
* Check if it has been spawned successfully, or output a message
* Проверить, заспавнилось ли оно успешно, в противном случае - вывести сообщение в чат


In order to achieve our goals, we have to use several functions. To find function we need to use, we should visit the [[Scripting Functions|Server Functions List]]. First we need a function to get the players position. Since players are Elements, we first jump to the '''Element functions''' where we find the [[getElementPosition]] function. By clicking on the function name in the list, you get to the function description. There we can see the syntax, what it returns and usually an example. The syntax shows us what arguments we can or have to submit.
Чтобы разрешить все поставленные задчаи, нам понадобится задействовать несколько функций. А чтобы найти нужные нам функции, нужно перейти ко [[RU/Server_Scripting_Functions|списку серверных функций]]. Для начала нам понадобится функция, которая получит координаты игрока. Так как все игроки являются элементами, мы сразу выбираем '''Element functions''', где и находим функцию [[getElementPosition]]. Кликнув по имени функции из списка, вы получите ее описание. Там можно увидеть синтаксис, что она возвращает и, как правило, пример использования. Синтаксис сообщает какие аргументы мы можем или должны ей передать.


For [[getElementPosition]], the syntax is:
Для [[getElementPosition]] синтаксис таков:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
float, float, float getElementPosition ( element theElement )
float, float, float getElementPosition ( element theElement )
</syntaxhighlight>
</syntaxhighlight>


The three ''float'' in front of the function name are the return type. In this case it means the function returns three floating point numbers. Within the parentheses, you can see what arguments you have to submit. In this case only the element whose position you want to get, which is the player in our example.
Три ''float'' перед именем функции и есть типы значений, которые она возвращает. В данном случае это значит, что функция возвращает три числа с плавающей точкой (x, y и z). Внутри круглых скобок указаны аргументы, которые ей необходимо передать. В данном случае это только элемент, чью позицию вы хотите получить, у нас он представлен игроком.


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
-- get the position and put it in the x,y,z variables
-- get the position and put it in the x,y,z variables
-- (local means, the variables only exist in the current scope, in this case, the function)
-- (local означает, что переменные существуют только здесь, в этой области, внутри этой функции)
local x,y,z = getElementPosition(thePlayer)
local x,y,z = getElementPosition(thePlayer)
end
end
</syntaxhighlight>
</syntaxhighlight>


Next we want to ensure that the vehicle won't spawn directly in the player, so we add a few units to the ''x'' variable, which will make it spawn east from the player.
Затем нам надо сделать так, чтобы ТС не спавнилось прямо внутри игрока, поэтому мы прибавим небольшое число к переменной ''x'', что повлечет за собой спавн ТС чуть восточнее самого игрока.


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
local x,y,z = getElementPosition(thePlayer) -- get the position of the player
local x,y,z = getElementPosition(thePlayer) -- получаем позицию игрока
x = x + 5 -- add 5 units to the x position
x = x + 5 -- прибавляем число 5 к позиции по оси x
end
end
</syntaxhighlight>
</syntaxhighlight>


Now we need another function, one to spawn a vehicle. We once again search for it on the [[Scripting Functions|Server Functions List]], this time - since we are talking about vehicles - in the '''Vehicle functions''' section, where we will choose [[createVehicle]]. In this functions' syntax, we only have one return type (which is more common), a vehicle element that points to the vehicle we just created. Also, we see that some arguments are enclosed within [ ] which means that those are optional.
Теперь нам понадобится другая функция, чтобы непосредственно заспавнить транспортное средство. Мы снова ищем ее в [[RU/Server Scripting Functions|списке серверных функций]], на этот раз, так как мы говорим о транспорте - в разделе '''Vehicle functions''', где выберем [[createVehicle]]. В синтаксисе этой функции указано только одно возвращаемое значение (что встречается наиболее часто) - элемент типа vehicle, представляющий только что созданное ТС. Также мы видим, что часть аргументов заключена в [ ], следовательно, они необязательны.


We already have all arguments we need for [[createVehicle]] in our function: The position we just calculated in the ''x,y,z'' variables and the model id that we provided through the command ("createvehicle 468") and can access in the function as ''vehicleModel'' variable.
Внутри нашей функции у нас уже есть все аргументы, которые нужны функции [[createVehicle]]: Только что вычисленная позиция в переменных ''x,y,z'' и id модели, который мы получили через команду ("createvehicle 468"), он доступен внутри функции в качестве переменной ''vehicleModel''.


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
local x,y,z = getElementPosition(thePlayer) -- get the position of the player
local x,y,z = getElementPosition(thePlayer) -- получаем позицию игрока
x = x + 5 -- add 5 units to the x position
x = x + 5 -- прибавляем число 5 к позиции по оси x
-- create the vehicle and store the returned vehicle element in the ''createdVehicle'' variable
-- создаем ТС и сохраняем возвращенный элемент типа vehicle в переменной ''createdVehicle''
local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
end
end
</syntaxhighlight>
</syntaxhighlight>


Of course this code can be improved in many ways, but at least we want to add a check whether the vehicle was created successfully or not. As we can read on the [[createVehicle]] page under '''Returns''', the function returns ''false'' when it was unable to create the vehicle. Thus, we check the value of the ''createVehicle'' variable.
Этот код, конечно же, можно усовершенствовать различными путями, но как минимум мы добавим проверку на то, было ли ТС успешно создано. Как можно прочитать на странице [[createVehicle]] под '''Returns''', функция возвращает ''false'', если ТС создать не получилось. Стало быть, мы проверяем значение переменной ''createVehicle''.


Now we have our complete script:
Теперь у нас есть готовый скрипт:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function createVehicleForPlayer(thePlayer, command, vehicleModel)
function createVehicleForPlayer(thePlayer, command, vehicleModel)
local x,y,z = getElementPosition(thePlayer) -- get the position of the player
local x,y,z = getElementPosition(thePlayer) -- получаем позицию игрока
x = x + 5 -- add 5 units to the x position
x = x + 5 -- прибавляем число 5 к позиции по оси x
local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
-- check if the return value was ''false''
-- проверяем, является ли возвращаемое значение ''false''
if (createdVehicle == false) then
if (createdVehicle == false) then
-- if so, output a message to the chatbox, but only to this player.
-- если да, то выводим сообщение в чат, но только для игрока, который спавнил ТС.
outputChatBox("Failed to create vehicle.",thePlayer)
outputChatBox("Failed to create vehicle.",thePlayer)
end
end
Line 118: Line 156:
</syntaxhighlight>
</syntaxhighlight>


As you can see, we introduced another function with [[outputChatBox]]. By now, you should be able to explore the function's documentation page yourself.
Как вы уже, наверное, заметили, вашему взору предстала новая функция - [[outputChatBox]]. Теперь вы самостоятельно можете изучить содержимое ее страницы-документации. Чтобы узнать больше о продвинутом скриптинге, почитайте про [[RU/Map manager|Map Manager]].


==What you need to know==
==Что вам следует знать==
You already read some things about resources, command handlers and finding functions in the documentation in the first paragraph, but there is much more to learn. This section will give you a rather short overview over some of these things, while linking to related pages if possible.
Вы уже кое-что прочитали о ресурсах, обработчиках команд и поиске функций в документации в первом разделе, но многое еще предстоит узнать. Этот раздел проведет довольно краткий обзор о некоторых из этих вещей, по возможности ссылаясь на соответствующие страницы.
===Clientside and Serverside scripts===
===Клиентские и серверные скрипты===
You may have already noticed these or similiar terms (Server/Client) somwhere on this wiki, mostly in conjunction with functions. MTA not only supports scripts that run on the server and provide commands (like the one we wrote above) or other features, but also scripts that run on the MTA client the players use to connect to the server. The reason for this is, that some features MTA provides have to be clientside (like a GUI - Graphical User Interface), others should be because they work better and still others are better off to be serverside or just don't work clientside.
Может быть, вы уже заметили эти или схожие термины (сервер/клиент) где-либо на данной вики, наиболее вероятно, вкупе с функциями. MTA не только поддерживает работающие на сервере скрипты, предоставляет команды (типа как мы писали выше) и другие возможности, но также и скрипты, выполняющиеся на клиенте MTA, который игроки используют для подключения к серверу. Причиной этому служит то, что некоторые предоставляемые MTA функции не могут быть серверными (например, GUI - Graphical User Interface, т.е. графический интерфейс пользователя), другие там просто работают лучше, но другим все же лучше быть серверными или попросту не работать на клиентской стороне.


Most scripts you will make (gamemodes, maps) will probably be serverside, like the one we wrote in the first section. If you run into something that can't be solved serverside, you will probably have to make it clientside. For a clientside script for example, you would create a ordinary script file (for example called ''client.lua'') and specify it in the meta.xml, like this:
Большинство сделанных вами скриптов (модов, карт), вероятно, будут серверными, как и та, которую мы написали в первом разделе. Если вы столкнетесь с чем-то, что не может быть реализовано на серверной стороне, возможно, вы сможете реализовать это на клиентской. Для написания клиентского скрипта, создайте обычный файл-скрипт (например, названный ''client.lua'') и укажите его в meta.xml так:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<script src="client.lua" type="client" />
<script src="client.lua" type="client" />
</syntaxhighlight>
</syntaxhighlight>
The ''type'' attribute defaults to 'server', so you only need to specify it for clientside scripts. When you do this, the clientside script will be downloaded to the player's computer once he connects to the server. Read more about [[Client side scripts]].
Атрибут ''type'' по умолчанию установлен на 'server', так что надобность указывать его существует только для клиентских скриптов. После этого, клиентский скрипт будет загружаться на компьютеры игроков при заходе. Подробнее о [[RU/Client side scripts|клиентских скриптах]].


===More complex resources===
===Более сложные ресурсы===
The previous section showed briefly how to add clientside scripts to the resource, but there is also much more possible. As mentioned at the very top of this page, resources can be pretty much everything. Their purpose is defined by what they do. Let's have some theoratical resources, by looking at the files it contains, the ''meta.xml'' and what they might do:
Предыдущий раздел вкратце изложил, как добавлять в ресурс клиентские скрипты, но возможностей на самом деле намного больше. Как написано в самом начале статьи, ресурсы могут быть чем угодно. Их назначение определяется тем, что они делают. Давайте теоретически вообразим некоторые ресурсы, глядя на их файлы-содержимое, ''meta.xml'' и подумаем, что они могут делать:


====First example - A utility script====
====Первый пример - Вспомогательный скрипт====
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
/admin_commands
/admin_commands
Line 149: Line 187:
</syntaxhighlight>
</syntaxhighlight>


* The ''commands.lua'' provides some admin commands, like banning a player, muting or something else that can be used to admin the server
* ''commands.lua'' предоставляет некоторые администраторские команды, такие как бан и заглушение игроков или еще что-нибудь, что может быть доступно для администраторов сервера
* The ''client.lua'' provides a GUI to be able to perform the mentioned actions easily
* ''client.lua'' предоставляет GUI, чтобы возможно было с легкостью выполнять вышеуказанные действия


This example might be running all the time (maybe even auto-started when the server starts) as it's useful during the whole gaming experience and also wont interfere with the gameplay, unless an admin decides to take some action of course.
Этот пример может выполняться все время (даже автозапускаться со стартом сервера), так как является полезным на протяжении всего игрового процесса и не конфликтует с ним, если администратор, конечно, сам этого не захочет.


====Second example - A gamemode====
====Второй пример - Мод====
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
/counterstrike
/counterstrike
Line 169: Line 207:
</syntaxhighlight>
</syntaxhighlight>


* The ''counterstrike.lua'' contains similiar to the following features:
* ''counterstrike.lua'' содержит схожие с нижеперечисленными функции:
** Let players choose their team and spawn them
** Позволить игрокам выбирать свою команду и спавниться
** Provide them with weapons, targets and instructions (maybe read from a Map, see below)
** Обеспечить их оружием, целями и инструкциями (возможно, взятыми из игровой карты, см. ниже)
** Define the game's rules, e.g. when does the round end, what happens when a player dies
** Определить правила игры, напр., когда кончается раунд, что происходит при смерти игрока
** .. and maybe some more
** .. и, может быть, что-то еще
* The ''buymenu.lua'' is a clientside script and creates a menu to buy weapons
* ''buymenu.lua'' - клиентский скрипт, создающий меню для покупки оружия


This example can be called a gamemode, since it not only intereferes with the gameplay, but actually defines the rules of it. The ''type'' attribute indicates that this example works with the [[Map manager]], yet another resource that was written by the QA Team to manage gamemodes and map loading. It is highly recommended that you base your gamemodes on the techniques it provides.
Этот образец может быть назван модом, так как не только влияет на игровой процесс, но, по сути, и задает его рамки. Атрибут ''type'' говорит о том, что этот пример работает с [[RU/Map manager|Map Manager]], уже другим ресурсом, написанным QA Team для управлениями модами и подгрузки карт. Очень рекомендуется основывать свои моды на предоставляемом им функционале.


This also means that the gamemode probably won't run without a map. Gamemodes should always be as generic as possible. An example for a map is stated in the next example.
Это также означает, что мод, возможно, не запустится без карты. Моды всегда должны пользоваться общим функционалом настолько широко, насколько это возможно. Образец карты - в следующем примере.


====Third example - A Map====
====Третий пример - Карта====
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
/cs-airport
/cs-airport
Line 195: Line 233:
</syntaxhighlight>
</syntaxhighlight>


* The ''airport.map'' in a XML file that provides information about the map to the gamemode, these may include:
* ''airport.map'' - XML-файл, предоставляющий моду информацию о карте, что включает в себя:
** Where the players should spawn, with what weapons, what teams there are
** Где игроки должны спавниться, с каким оружием, какие имеются команды
** What the targets are
** Какие имеются цели
** Weather, World Time, Timelimit
** Погода, время, ограничение по времени
** Provide vehicles
** Предоставляемый транспорт
* The ''airport.lua'' might contain map-specific features, that may include:
* ''airport.lua'' может содержать присущий данной карте функционал, что включает в себя:
** Opening some door/make something explode when something specific happens
** Открытие каких-либо дверей, подрыв чего-нибудь при определенных условиях
** Create or move some custom objects, or manipulate objects that are created through the .map file
** Создание или передвижение определенных игровых объектов, или управление теми, что были созданы через .map-файл
** .. anything else map-specific you can think of
** .. все что еще угодно, связанное с картами


As you can see, the ''type'' attribute changed to 'map', telling the [[Map manager]] that this resource is a map, while the ''gamemodes'' attribute tells it for which gamemodes this map is valid, in this case the gamemode from the above example.
Как вы уже заметили, атрибут ''type'' поменялся на 'map', сообщая [[RU/Map manager|Map Manager]], что этот ресурс - карта, в то время как атрибут ''gamemodes'' говорит, с какими модами эта карта совместима, в данном случае - это мод из примера выше.
What may come as a surprise is that there is also a script in the Map resource. Of course this is not necessarily needed in a map, but opens a wide range of possibilities for map makers to create their own world within the rules of the gamemode they create it for.
Сюрпризом может показаться то, что в ресурс-карту также входит и скрипт. Конечно, это совсем не обязательно для карты, но открывает широкий спектр возможностей для их создателей, позволяя создавать собственный мир с правилами мода, на котором он основывается.


The ''airport.map'' file might look similiar to this:
Файл ''airport.map'' может выглядеть примерно так:
<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">
<map mode="deathmatch" version="1.0">
<map mode="deathmatch" version="1.0">
Line 225: Line 263:
</syntaxhighlight>
</syntaxhighlight>


When a gamemode is started with a map, the map resources is automatically started by the mapmanager and the information it contains can be read by the gamemode resource. When the map changes, the current map resource is stopped and the next map resource is started.
Когда мод запускается с картой, ресурс-карта автоматически запускается mapmanager'ом, и информация, которую он содержит, может быть прочитана ресурсом-модом. При смене карты, текущий ресурс-карта останавливается, а следующий - запускается. Для более детального разъяснения и образцов того, как ресурсы-карты используются основным скриптом, посетите страницу [[RU/Writing Gamemodes]].


===Events===
===События===
Events are the way MTA tells scripts about things that happen. For example when a player dies, the [[onPlayerWasted]] event is triggered. In order to perform any actions when a player dies, you have to prepare yourself similiar to adding a command handler, as shown in [[#Writing_the_script|the first chapter]].
События - способ MTA сообщать скриптам о происходящем. Например, при смерти игрока, срабатывает событие [[onPlayerWasted]]. Чтобы при смерти игрока что-то происходило, вам придется проделать действия, схожие с добавлением обработчика команд, как об этом рассказано в [[#Создание простого скрипта|первом разделе]].


This example will output a message with the name of the player who died:
Этот пример будет выводить сообщение с именем игрока, который умер:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function playerDied(totalAmmo, killer, killerWeapon, bodypart)
function playerDied(totalAmmo, killer, killerWeapon, bodypart)
outputChatBox(getClientName(source).." died!")
outputChatBox(getPlayerName(source).." умер!")
end
end
addEventHandler("onPlayerWasted",getRootElement(),playerDied)
addEventHandler("onPlayerWasted",getRootElement(),playerDied)
</syntaxhighlight>
</syntaxhighlight>


Instead of showing what arguments are needed, the documentation page for Events shows what parameters are passed to the handler function, similiar to the way a [[#About_command_handlers|command handler]] does, just that it is different from event to event. Another important point is the ''source'' variable, that exists in handler functions. It doesn't have to be added to the parameter list of the function, but it still exists. It has a different value from event to event, for player events (as in the example above) it is the player element.
Вместо того, чтобы сначала вывести список требуемых аргументов, страница документации для событий отображает, какие параметры передаются функции-обработчику, так же, как делает [[#Про обработчики команд|обработчик команд]], просто это разнится от события к событию. Другим важным моментом является существующая в функциях-обработчиках переменная ''source''. Ее необязательно добавлять в список параметров функции, но она, тем не менее, существует. Ее значение меняется от события к событию, для событий, связанных с игроком (как в образце выше), это - элемент типа player. В качестве другого образца служит базовый скрипт для респавна игрока в первом разделе, на его примере можно понять, как используется ''source''.


==Where to go from here==
==Что делать теперь==
You should now be familiar with the most basic aspects of MTA scripting and also a bit with the documentation. The [[Main Page]] provides you with links to more information, Tutorials and References that allow a deeper look into the topics you desire to learn about.
Теперь вы знакомы с наиболее базовыми аспектами скриптинга в MTA, а также чуть-чуть с документацией. [[Главная страница]] обеспечит вас ссылками на множество различной информации, руководства и указания, которые позволят глубже взглянуть на интересующие вас темы.
{{note|Теперь мы рекомендуем вам прочитать руководство по [[RU/Debugging|отладке]]. Умение хорошо отлаживать - абсолютная необходимость при написании скриптов. Мы также рекомендуем вам пользоваться [[RU/Predefined variables list|списком предписанных переменных]], который поможет вам в выполнении определенных задач, а писать скрипты станет намного легче и быстрее.}}
'''Также смотрите:'''
* [[Advanced Topics|Продвинутый функционал]]
[[en:Scripting Introduction]]
[[es:Introducción a la Programación]]
[[it:Introduzione allo scripting]]
[[pt-br:Introdução ao Scripting]]
[[nl:Scripting_introductie]]

Latest revision as of 17:12, 19 May 2019

Ресурсы являются ключевой частью MTA. Ресурс - это папка или zip-архив, содержащий набор файлов, а также meta-файл, который описывает серверу как нужно загружать ресурс и из каких файлов он состоит. Ресурс играет практически ту же роль, что и программа в операционной системе - он может быть запущен и остановлен, при этом несколько ресурсов могут быть запущены одновременно.

Все, связанное со скриптингом, находится в ресурсах. Назначение ресурса и определяет, является ли он модом, картой или чем-либо еще. MTA поставляется с ресурсами, которые вы можете выборочно использовать в своих модах, например, maplimits, позволяющий удерживать игроков в рамках указанных границ карты, или deathpickups, создающий пикапы с оружием.

[[{{{image}}}|link=|]] Tip: Первым шагом в изучении Lua-скриптинга должен быть выбор Lua-редактора. Это намного упрощает скриптинг. Мы рекомендуем Notepad++ или LuaEdit. Также имеется неофициальный MTA Script Editor (на стадии разработки), который вы можете испытать.

Создание работающего скрипта

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

Где находятся все скрипты?

Давайте взглянем на файловую структуру скрипта. Зайдите в папку сервера MTA и пройдите по следующему пути:

/server/mods/deathmatch/resources/

Вы увидите множество .zip-архивов, являющихся упакованными пробными скриптами, поставляемыми с MTA DM. Каждый файл - это "ресурс", все они будут распакованы и загружены сервером при его старте. Чтобы создать свой собственный ресурс, просто создайте папку и назовите ее так, как хотите. В нашем случае мы назовем ее "myserver".

Теперь вам нужно зайти в эту папку:

/server/mods/deathmatch/resources/myserver/

Идентификация вашего ресурса

Чтобы сервер мог узнать о содержимом того или иного ресурса, в нем должен быть создан файл meta.xml, перечисляющий его содержимое. Этот файл должен быть расположен в корневой директории ресурса, в нашем случае - это папка "myserver". Просто создайте текстовый файл, назовите его "meta.xml" и откройте с помощью Блокнота (notepad).

В файл meta.xml введите следующий код:

<meta>
     <info author="YourName" type="gamemode" name="Kontol memek" description="My Mta Sa" />
     <script src="script.lua" type="server"/>
</meta>

В теге <info /> есть поле "type", которое говорит о том, что данный ресурс - gamemode ("мод", игровой режим), а не обычный include или map (карта), о которых мы поговорим чуть позже. Gamemode - то, что вам нужно, чтобы создать независимый сервер.

Тег <script /> оговаривает сценарии (скрипты), которые содержит ресурс, о них мы сейчас и поговорим. Поле "type" говорит о том, что данный скрипт "script.lua" будет выполняться на стороне сервера.

Создание простого скрипта

Заметьте, что в теге <script /> 'script.lua' - файл не находится в какой-либо вложенной директории. Следовательно, мы создадим файл в той же папке, что и meta.xml. Теперь можно скопировать и вставить в script.lua следующий код:

local spawnX, spawnY, spawnZ = 1959.55, -1714.46, 10
function joinHandler()
	spawnPlayer(source, spawnX, spawnY, spawnZ)
	fadeCamera(source, true)
	setCameraTarget(source, source)
	outputChatBox("Welcome to My Server", source)
end
addEventHandler("onPlayerJoin", getRootElement(), joinHandler)

Этот скрипт заспавнит вас по координатам (x, y, z), указанным выше, когда вы зайдете на сервер. Обратите внимание, что функция fadeCamera обязательно должна быть, иначе экран будет черным. К тому же, в релизах новее DP2 вам нужно установить цель для камеры (иначе все, что увидит игрок - синее небо).

Переменная source указывает на того, кто вызвал срабатывание события. Так как данный код срабатывает при заходе какого-либо игрока, эта переменная используется для установления того, кто зашел. Так что спавнить будет именно этого игрока, а не всех сразу или кого-нибудь случайно.

Если присмотреться к addEventHandler, вы заметите три вещи: 'onPlayerJoin', указывающий на то, когда (почему) произойдет срабатывание; getRootElement(), который показывет благодаря кому/чему может произойти срабатывание (getRootElement() - это все/всё) и joinHandler, который отвечает за функцию, на которую произойдет переключение при срабывании события. Остальные подробности будут изложены позже и на отдельном примере, а теперь давайте просто запустим сервер и попрактикуемся!

Запуск скрипта

Чтобы запустить сервер, просто запустите исполняемый файл (на Windows - .exe) по адресу MTA San Andreas x.x/server, где x.x - номер версии MTA. Сначала будут показаны данные сервера; запомните номер порта (server port), который понадобится вам при подключении. Затем сервер загрузит все ресурсы в папку mods/deathmatch/resources/ и позже будет "ready to accept connections!", то есть готов принимать игроков.

Перед тем, как вы подключитесь к серверу, нужно обязательно запустить мод (gamemode). Введите "start myserver" и нажмите Enter. Сервер запустит мод, который вы только что создали, а также начнет отображать различные ошибки и предупреждения, если таковые будут. Теперь можно запустить клиент MTA DM и подключиться через "Quick Connect", воспользовавшись IP-адресом вашего сервера и номером порта, на который мы ранее обратили ваше внимание. Если все пройдет по плану, через несколько секунд ваш персонаж сможет пройтись по улицам Los Santos'а.

Затем мы добавим в скрипт команду, которую игроки смогут использовать для того, чтобы спавнить рядом с собой транспортное средство. Вы можете это пропустить и взглянуть на статью про более продвинутый скриптинг с использованием Map Manager, которая продолжит это руководство. Еще одним ответвлением данного руководства является Введение в скриптинг GUI: прочитав его, вы узнаете, как рисуется и программируется Graphical User Interface в MTA:DM.

Создание простой команды

Давайте вернемся к содержимому файла script.lua. Как уже было сказано, мы хотим предоставить команду для создания трансортного средства рядом с вашей текущей позицией в игре. Во-первых, нам понадобится создать функцию, которую мы будем вызывать, и обработчик команды, который сделает команду доступной для выбора игроком посредством ввода ее в консоли.

-- создаем функцию, вызываемую обработчиком команды, с аргументами: thePlayer, command, vehicleModel
function createVehicleForPlayer(thePlayer, command, vehicleModel)
   -- создаем транспортное средство и другое
end

-- создаем обработчик команды
addCommandHandler("createvehicle", createVehicleForPlayer)

Заметка: Клик по названию функции в образце кода перенаправит на соответствующую страницу с ее описанием.

Про обработчики команд

Первый аргумент addCommandHandler - имя команды, которая будет доступна игроку, второй аргумент - функция, на которую произойдет переключение, в данном случае - это createVehicleForPlayer.

Если у вас уже есть опыт в скриптинге, вы знаете, что функции вызываются примерно следующим образом:

functionName(argument1, argument2, argument3, ..)
functionName(thePlayer, commandName, argument3, ..)

Присмотревшись ко второму образцу (выше), мы увидим, что argument1 - thePlayer, а argument2 - commandName. thePlayer - тот, кто набрал команду, так что как бы вы ее не вводили, переменная будет содержать игрока, который ее активировал. commandName - команда, которую ввели. Так что при вводе "/greet", этот аргумент будет содержать "greet". Argument 3 - еще что-то, введенное игроком после, об этом вы узнаете чуть позже из данного руководства. Никогда не забывайте, что первые 2 аргумента являются стандартными, но назвать вы их можете по своему усмотрению. То есть важен порядок, а не название.

Мы уже вызывали таким образом функцию addCommandHandler, и так как createVehicleForPlayer - также функция, ее тоже можно так вызвать. Но мы для этого используем обработчик команд, который вызывает ее схожим образом, только внутренне.

Например: Кто-то вводит "createvehicle 468" в игровой консоли, чтобы заспавнить Sanchez, обработчик команд вызывает функцию createVehicleForPlayer, как если бы мы имели в скрипте следующую строку кода:

createVehicleForPlayer(thePlayer,"createvehicle","468") -- thePlayer - элемент типа player игрока, который ввел команду

Как можно заметить, предоставляются несколько параметров: игрок, который вызвал команду, сама команда, которую он ввел, и какой-нибудь текст, который он после нее ввел, в данном случае - "468" в качестве id трансопртного средства, отвчечающего за Sanchez. Первые два параметра одинаковы для всех обработчиков команд, о них вы можете почитать на странице addCommandHandler. Фактически, вам всегда придется определять как минимум эти два параметра, чтобы смочь использовать какие-нибудь другие, идущие после них (например, для обработки текста, введенного после команды, как id модели транспортного средства в нашем случае).

Заметка: Обработчик команды надо добавлять именно ПОСЛЕ функции, на которую он сошлется, иначе она не будет найдена. Порядок имеет значение!

Написание функции

Чтобы заполнить созданную нами функцию, нам следует подумать, что нам предстоит сделать:

  • Получить позицию игрока, чтобы знать, где спавнить ТС (мы хотим, чтобы оно появлялось прямо рядом с игроком)
  • Вычислить позицию, на которой мы хотим заспавнить ТС (мы же не хотим его появления на голове у игрока)
  • Собственно, заспавнить ТС
  • Проверить, заспавнилось ли оно успешно, в противном случае - вывести сообщение в чат

Чтобы разрешить все поставленные задчаи, нам понадобится задействовать несколько функций. А чтобы найти нужные нам функции, нужно перейти ко списку серверных функций. Для начала нам понадобится функция, которая получит координаты игрока. Так как все игроки являются элементами, мы сразу выбираем Element functions, где и находим функцию getElementPosition. Кликнув по имени функции из списка, вы получите ее описание. Там можно увидеть синтаксис, что она возвращает и, как правило, пример использования. Синтаксис сообщает какие аргументы мы можем или должны ей передать.

Для getElementPosition синтаксис таков:

float, float, float getElementPosition ( element theElement )

Три float перед именем функции и есть типы значений, которые она возвращает. В данном случае это значит, что функция возвращает три числа с плавающей точкой (x, y и z). Внутри круглых скобок указаны аргументы, которые ей необходимо передать. В данном случае это только элемент, чью позицию вы хотите получить, у нас он представлен игроком.

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	-- get the position and put it in the x,y,z variables
	-- (local означает, что переменные существуют только здесь, в этой области, внутри этой функции)
	local x,y,z = getElementPosition(thePlayer)
end

Затем нам надо сделать так, чтобы ТС не спавнилось прямо внутри игрока, поэтому мы прибавим небольшое число к переменной x, что повлечет за собой спавн ТС чуть восточнее самого игрока.

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	local x,y,z = getElementPosition(thePlayer) -- получаем позицию игрока
	x = x + 5 -- прибавляем число 5 к позиции по оси x
end

Теперь нам понадобится другая функция, чтобы непосредственно заспавнить транспортное средство. Мы снова ищем ее в списке серверных функций, на этот раз, так как мы говорим о транспорте - в разделе Vehicle functions, где выберем createVehicle. В синтаксисе этой функции указано только одно возвращаемое значение (что встречается наиболее часто) - элемент типа vehicle, представляющий только что созданное ТС. Также мы видим, что часть аргументов заключена в [ ], следовательно, они необязательны.

Внутри нашей функции у нас уже есть все аргументы, которые нужны функции createVehicle: Только что вычисленная позиция в переменных x,y,z и id модели, который мы получили через команду ("createvehicle 468"), он доступен внутри функции в качестве переменной vehicleModel.

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	local x,y,z = getElementPosition(thePlayer) -- получаем позицию игрока
	x = x + 5 -- прибавляем число 5 к позиции по оси x
	-- создаем ТС и сохраняем возвращенный элемент типа vehicle в переменной ''createdVehicle''
	local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
end

Этот код, конечно же, можно усовершенствовать различными путями, но как минимум мы добавим проверку на то, было ли ТС успешно создано. Как можно прочитать на странице createVehicle под Returns, функция возвращает false, если ТС создать не получилось. Стало быть, мы проверяем значение переменной createVehicle.

Теперь у нас есть готовый скрипт:

function createVehicleForPlayer(thePlayer, command, vehicleModel)
	local x,y,z = getElementPosition(thePlayer) -- получаем позицию игрока
	x = x + 5 -- прибавляем число 5 к позиции по оси x
	local createdVehicle = createVehicle(tonumber(vehicleModel),x,y,z)
	-- проверяем, является ли возвращаемое значение ''false''
	if (createdVehicle == false) then
		-- если да, то выводим сообщение в чат, но только для игрока, который спавнил ТС.
		outputChatBox("Failed to create vehicle.",thePlayer)
	end
end
addCommandHandler("createvehicle", createVehicleForPlayer)

Как вы уже, наверное, заметили, вашему взору предстала новая функция - outputChatBox. Теперь вы самостоятельно можете изучить содержимое ее страницы-документации. Чтобы узнать больше о продвинутом скриптинге, почитайте про Map Manager.

Что вам следует знать

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

Клиентские и серверные скрипты

Может быть, вы уже заметили эти или схожие термины (сервер/клиент) где-либо на данной вики, наиболее вероятно, вкупе с функциями. MTA не только поддерживает работающие на сервере скрипты, предоставляет команды (типа как мы писали выше) и другие возможности, но также и скрипты, выполняющиеся на клиенте MTA, который игроки используют для подключения к серверу. Причиной этому служит то, что некоторые предоставляемые MTA функции не могут быть серверными (например, GUI - Graphical User Interface, т.е. графический интерфейс пользователя), другие там просто работают лучше, но другим все же лучше быть серверными или попросту не работать на клиентской стороне.

Большинство сделанных вами скриптов (модов, карт), вероятно, будут серверными, как и та, которую мы написали в первом разделе. Если вы столкнетесь с чем-то, что не может быть реализовано на серверной стороне, возможно, вы сможете реализовать это на клиентской. Для написания клиентского скрипта, создайте обычный файл-скрипт (например, названный client.lua) и укажите его в meta.xml так:

<script src="client.lua" type="client" />

Атрибут type по умолчанию установлен на 'server', так что надобность указывать его существует только для клиентских скриптов. После этого, клиентский скрипт будет загружаться на компьютеры игроков при заходе. Подробнее о клиентских скриптах.

Более сложные ресурсы

Предыдущий раздел вкратце изложил, как добавлять в ресурс клиентские скрипты, но возможностей на самом деле намного больше. Как написано в самом начале статьи, ресурсы могут быть чем угодно. Их назначение определяется тем, что они делают. Давайте теоретически вообразим некоторые ресурсы, глядя на их файлы-содержимое, meta.xml и подумаем, что они могут делать:

Первый пример - Вспомогательный скрипт

/admin_commands
	/meta.xml
	/commands.lua
	/client.lua
<meta>
	<info author="Someguy" description="admin commands" />
	<script src="commands.lua" />
	<script src="client.lua" type="client" />
</meta>
  • commands.lua предоставляет некоторые администраторские команды, такие как бан и заглушение игроков или еще что-нибудь, что может быть доступно для администраторов сервера
  • client.lua предоставляет GUI, чтобы возможно было с легкостью выполнять вышеуказанные действия

Этот пример может выполняться все время (даже автозапускаться со стартом сервера), так как является полезным на протяжении всего игрового процесса и не конфликтует с ним, если администратор, конечно, сам этого не захочет.

Второй пример - Мод

/counterstrike
	/meta.xml
	/counterstrike.lua
	/buymenu.lua
<meta>
	<info author="Someguy" description="Counterstrike remake" type="gamemode" />
	<script src="counterstrike.lua" />
	<script src="buymenu.lua" type="client" />
</meta>
  • counterstrike.lua содержит схожие с нижеперечисленными функции:
    • Позволить игрокам выбирать свою команду и спавниться
    • Обеспечить их оружием, целями и инструкциями (возможно, взятыми из игровой карты, см. ниже)
    • Определить правила игры, напр., когда кончается раунд, что происходит при смерти игрока
    • .. и, может быть, что-то еще
  • buymenu.lua - клиентский скрипт, создающий меню для покупки оружия

Этот образец может быть назван модом, так как не только влияет на игровой процесс, но, по сути, и задает его рамки. Атрибут type говорит о том, что этот пример работает с Map Manager, уже другим ресурсом, написанным QA Team для управлениями модами и подгрузки карт. Очень рекомендуется основывать свои моды на предоставляемом им функционале.

Это также означает, что мод, возможно, не запустится без карты. Моды всегда должны пользоваться общим функционалом настолько широко, насколько это возможно. Образец карты - в следующем примере.

Третий пример - Карта

/cs-airport
	/meta.xml
	/airport.map
	/airport.lua
<meta>
	<info author="Someguy" description="Counterstrike airport map" type="map" gamemodes="counterstrike" />
	<map src="airport.map" />
	<script src="airport.lua" />
</meta>
  • airport.map - XML-файл, предоставляющий моду информацию о карте, что включает в себя:
    • Где игроки должны спавниться, с каким оружием, какие имеются команды
    • Какие имеются цели
    • Погода, время, ограничение по времени
    • Предоставляемый транспорт
  • airport.lua может содержать присущий данной карте функционал, что включает в себя:
    • Открытие каких-либо дверей, подрыв чего-нибудь при определенных условиях
    • Создание или передвижение определенных игровых объектов, или управление теми, что были созданы через .map-файл
    • .. все что еще угодно, связанное с картами

Как вы уже заметили, атрибут type поменялся на 'map', сообщая Map Manager, что этот ресурс - карта, в то время как атрибут gamemodes говорит, с какими модами эта карта совместима, в данном случае - это мод из примера выше. Сюрпризом может показаться то, что в ресурс-карту также входит и скрипт. Конечно, это совсем не обязательно для карты, но открывает широкий спектр возможностей для их создателей, позволяя создавать собственный мир с правилами мода, на котором он основывается.

Файл airport.map может выглядеть примерно так:

<map mode="deathmatch" version="1.0">
	<terrorists>
		<spawnpoint posX="2332.23" posY="-12232.33" posZ="4.42223" skins="23-40" />
	</terrorists>
	<counterterrorists>
		<spawnpoint posX="2334.23443" posY="-12300.233" posZ="10.2344" skins="40-50" />
	</counterterrorists>

	<bomb posX="23342.23" posY="" posZ="" />
	
	<vehicle posX="" posY="" posZ="" model="602" />	
	<vehicle posX="" posY="" posZ="" model="603" />	
</map>

Когда мод запускается с картой, ресурс-карта автоматически запускается mapmanager'ом, и информация, которую он содержит, может быть прочитана ресурсом-модом. При смене карты, текущий ресурс-карта останавливается, а следующий - запускается. Для более детального разъяснения и образцов того, как ресурсы-карты используются основным скриптом, посетите страницу RU/Writing Gamemodes.

События

События - способ MTA сообщать скриптам о происходящем. Например, при смерти игрока, срабатывает событие onPlayerWasted. Чтобы при смерти игрока что-то происходило, вам придется проделать действия, схожие с добавлением обработчика команд, как об этом рассказано в первом разделе.

Этот пример будет выводить сообщение с именем игрока, который умер:

function playerDied(totalAmmo, killer, killerWeapon, bodypart)
	outputChatBox(getPlayerName(source).." умер!")
end
addEventHandler("onPlayerWasted",getRootElement(),playerDied)

Вместо того, чтобы сначала вывести список требуемых аргументов, страница документации для событий отображает, какие параметры передаются функции-обработчику, так же, как делает обработчик команд, просто это разнится от события к событию. Другим важным моментом является существующая в функциях-обработчиках переменная source. Ее необязательно добавлять в список параметров функции, но она, тем не менее, существует. Ее значение меняется от события к событию, для событий, связанных с игроком (как в образце выше), это - элемент типа player. В качестве другого образца служит базовый скрипт для респавна игрока в первом разделе, на его примере можно понять, как используется source.

Что делать теперь

Теперь вы знакомы с наиболее базовыми аспектами скриптинга в MTA, а также чуть-чуть с документацией. Главная страница обеспечит вас ссылками на множество различной информации, руководства и указания, которые позволят глубже взглянуть на интересующие вас темы.

[[{{{image}}}|link=|]] Note: Теперь мы рекомендуем вам прочитать руководство по отладке. Умение хорошо отлаживать - абсолютная необходимость при написании скриптов. Мы также рекомендуем вам пользоваться списком предписанных переменных, который поможет вам в выполнении определенных задач, а писать скрипты станет намного легче и быстрее.

Также смотрите: