00059. Подключение текстовых файлов, scm-функции
Подключение текстовых файлов, scm-функции|Сегодня мы рассмотрим одну из интереснейших тем - создание SCM-функций.|wmysterio|wmysterio||||Здравствуйте, дорогие друзья. Начинаем очередной урок по скриптингу. Использование функций очень удобно, когда нужно выполнять один и тот же код несколько раз. Действуют функции по аналогии с gosub, только в функции можно передавать параметры. Есть два опкода для работы с функциями:
0AB1: call_scm_func @GetSQR 1 10 $result
Здесь:
@GetSQR - указывается метка, где будет выполнятся функция
1 - количество передаваемых параметров
10 - это сами параметры
$result - результат выполнения функции ( если такой есть )
0AB2: ret 1 0@
Здесь:
1 - количество возвращаемых параметров
0@ - сами параметры
Давайте напишем саму функцию:
:GetSQR
wait 0
006A: 0@ *= 0@ // (int)
0AB2: ret 1 0@
Обратите внимание, что передаваемые параметры имеют переменные 0@, 1@, 2@ и так до 32-х штук. Но они не влияют на переменные в самом потоке. То есть если у нас был раньше актёр в переменной 0@, то после выполнения функции он так и останется в ней. Рассмотрим лучший пример:
:LABEL
thread 'LABEL'
wait 0
0AB1: call_scm_func @SPAWN_ACTOR 4 spawn_at -1390.0 14.0 39.0 angle 180.0 $ACTOR
05E2: AS_actor $ACTOR kill_actor $PLAYER_ACTOR
end_thread
:SPAWN_ACTOR
wait 0
model.Load(#WMYDRUG)
038B: load_requested_models
:SPAWN_ACTOR_1
wait 0
if
model.Available(#WMYDRUG)
jf @SPAWN_ACTOR_1
4@ = actor.Create(4, #WMYDRUG, 0@, 1@, 2@)
actor.Angle(4@) = 3@
model.Destroy(#WMYDRUG)
0AB2: ret 1 4@
Обратите внимание на параметры функции. При вызове каждый параметр получает свою локальную переменную в функции, где мы можем обрабатывать их с какой-то целью. Рассмотрим рисунок, который покажет как работает функция:
× **ВАЖНО:** Параметры функции, который возвращает опкод "0AB2" всегда должны стоять после передаваемых параметров

Запускаем игру - отлично! Созданный нами актёр хочет убить нас, что и нужно было доказать :)
Один интересный факт насчет опкода 0AB1. Как видите, в нём мы можем дописывать различные строки, например: "pawn_at" и в любых местах. Компилятору будет по-барабану :) Даже если функция будет написана так:
0AB1: @SPAWN_ACTOR 4 2475.1167 -1674.4192 13.3368 287.7152 $ACTOR
Главное, что бы бы ли параметры и метка ;)
"Зачем это нужно?" - Спросите Вы. Ведь функцию всё равно нужно будет писать каждый раз в скрипте. Естественно можно и обойтись без функций, но что если нужно одну и туже функцию применять в 2-х разных скриптах? Зачем писать их две штуки, если можно написать только одну, которая будет хранится в файле! Мы только подключим его в нужный скрипт и будем использовать функцию.
Подключение файла напоминает команду из языка программирования C/C++: #include "file.h", только здесь нужно писать так:
{$I file.txt}
Здесь:
$i - указываем компилятору, что нужно подключить файл ( include )
file.txt - название файла. Расширение может быть любое, но в нём должен быть текст, то есть что бы мы могли его редактировать блокнотом и прочими текстовыми редакторами
Поиск файла ведётся относительно следующих папок:
- Папка, где находится файл, содержащий данную директиву;
- Папка Sanny Builder\data\<game>
- Корневая папка Sanny Builder;
- Корневая папка игры;
Давайте создадим текстовый файл "function.txt" в папке с "gta_sa.exe". Открываем файл. Копируем код функции с SB в текстовый файл. После этого очищаем скрипт от кода функции. В скрипте должно быть только эти строки:
{$CLEO}
{$I function.txt}
:LABEL
thread 'LABEL'
wait 0
0AB1: call_scm_func @SPAWN_ACTOR 4 spawn_actor_at 2475.1167 -1674.4192 13.3368 angle 287.7152 $ACTOR
05E2: AS_actor $ACTOR kill_actor $PLAYER_ACTOR
0A93: end_custom_thread
Сохраняем файл "function.txt" и пытаемся скомпилировать скрипт. В нас ошибка: "Переход на нулевой оффсет". Давайте поставим опкод "0000". Та же ошибка! Что делать? А спасёт нас оператор goto. Действует он точно как и "jump". Нам нужно отредактировать текстовый файл. Для этого создадим метку ":SPAWN_ACTOR_END" в самом конце файла "function.txt". А в самом верху, перед меткой ":SPAWN_ACTOR" делаем переход с помощью оператора "goto". Таким образом содержимое "function.txt" будет таково:
goto @SPAWN_ACTOR_END // начало "обёртки" функции
:SPAWN_ACTOR
wait 0
model.Load(#WMYDRUG)
038B: load_requested_models
:SPAWN_ACTOR_1
wait 0
if
model.Available(#WMYDRUG)
jf @SPAWN_ACTOR_1
4@ = actor.Create(6, #WMYDRUG, 0@, 1@, 2@)
actor.Angle(4@) = 3@
model.Destroy(#WMYDRUG)
0AB2: ret 1 4@
:SPAWN_ACTOR_END // конец "обёртки" функции
Думаю постоянно метку писать как то неудобно, да большинство из них можно и не запомнить а постоянно открывать файл ещё неудобнее. Поэтому давайте дадим имя метки с помощью констант:
const
spawn_actor = @SPAWN_ACTOR
end
и добавим этот текст в начало файла "function.txt". Теперь сама функция может иметь такой вид:
0AB1: spawn_actor 4 at 2475.1167 -1674.4192 13.3368 angle 287.7152 handle $ACTOR
Как видите мы сократили длину функции, что очень удобно и легко запоминается! Теперь эту функцию можно использовать в лю бом скрипте, подключив этот файл :)
× **Примечание:** испольховать такие константы в крупных проектах проблематично, по-этому рекомендую использовать метки× **ВАЖНО:** функции нужно объявлять в начале скрипта и только потом писать его код
Задания!
- Написать две функции:
- Функция считывает цвета машины и заносит их в ini-файл "color.ini";
- Функция устанавливает цвета машины, используя параметры ini-файла "color.ini";
- Написать скрипт, что бы каждая новая машина, в которую входит СЖ, меняла свои цвета на цвета предыдущей машины;
Посмотрите на картинку выше. На ней есть незначительная ошибка. Тот, кто первый найдёт её - получит + к репутации :D|1496|1|0|36274742
png
1171564
399`192``||podkljuchenie_tekstovykh_fajlov_scm_funkcii|1499599651Last modified 1yr ago