000155. Использование SCM-функций (опкод 0AB1)
Использование SCM-функций (опкод 0AB1)|Что же такое SCM-функция? На деле это выглядит так, словно мы вызываем опкод, который создали сами и, он выполняет определённые действия. С одной стороны, он похож на стандартный gosub, но принцип работы у SCM-функции другой - все переменные сохраняют свои значения, несмотря на то, что в функции используются те же переменные ( имеются ввиду локальные переменные )|BoPoH|BoPoH||||Основное назначение SCM-функций - укорачивание кода скрипта и улучшение его читабельности, если в нём используются одни и те же конструкции во многих местах. За вызов SCM-функции отвечает опкод 0AB1. Этот опкод добавляется библиотекой CLEO, поэтому если у вас её нет - опкод работать не будет. Давайте рассмотрим подробнее его параметры.
0AB1: call_scm_func @function num_params 1 10
Здесь:
@function - это метка, указывающая на код нашей SCM-функции
1 - это количество параметров, которые мы передаём в функцию ( не более 32 ). Эти параметры используются функцией для выполнения определённых задач, связанных с этими параметрами. К примеру, если функция будет помещать актёра в определённую точку, то в неё мы будем передавать хендл актёра.
10 ( и т.п. ) - это те параметры, которые будут передаваться в функцию ( не более 32 ). Их количество должно совпадать со вторым параметром. Т.е. если вы вторым параметром указали число 3, значит после него вы должны указать 3 параметра, которые передадутся в функцию.
Например:
0AB1: call_scm_func @function num_params 4 $PLAYER_ACTOR [email protected] [email protected] [email protected]
Оставшиеся параметры ( переменные ) будут получать возвращаемые функцией данные. SCM-функция может возвращать одно и более значений при помощи опкода 0AB2. Если функция не возвращает параметров, то никаких переменных в конце опкода писать не нужно. Попробуем разобрать пример, приведённый ниже:
model.Load(#ELEGY)
038B: load_requested_models
while true
wait 0
if
0AB0: key_pressed 48
then
0AB1: call_scm_func @SpawnCarBeforePlayer 5 $PLAYER_ACTOR 0.0 5.0 0.0 #ELEGY [email protected]
car.SetImmunities([email protected], 1, 1, 1, 1, 1)
while 0AB0: key_pressed 48
wait 0
end
end
end
:SpawnCarBeforePlayer
04C4: store_coords_to [email protected] [email protected] [email protected] from_actor [email protected] with_offset [email protected] [email protected] [email protected]
0AB2: ret 1 [email protected]
По нажатию клавиши 0`, перед игроком заспаунится элегия и ей присвоятся иммунитеты. Рассмотрим вызов функции опкодом 0AB1. Здесь у нас 5 параметров, которые передаются в функцию, и одно возвращаемое значение - хендл созданной машины.
Сама SCM-функция находится за пределами основного цикла скрипта. Исполнение скрипта не должно дойти до неё иным способом, кроме как через опкод 0AB1. Проще говоря, SCM-функции лучше всего оставлять в конце скрипта, а не в середине и уж тем более, не в начале.
Исходя из того, что компилятор спокойно воспринимает изменения описаний опкодов, мы можем спокойно изменить внешний вид опкода 0AB1 под свои нужды. К примеру, так:
0AB1: @SpawnCarBeforePlayer 5 actor $PLAYER_ACTOR offset_XYZ 0.0 5.0 0.0 car_model #ELEGY get_handle_to [email protected]
Таким образом, вызов фукции становится более читабельным. Описание к каждой функции можно придумывать своё.
Лично я перед меткой функции оставляю комментарий с примером вызова функции, чтобы не забывать, какие параметры передаются в функцию и какие возвращаются.
Теперь разберём саму функцию. Параметры, которые передаются опкодом 0AB1 в функцию, записываются последовательно в локальные переменные функции, начиная с [email protected] В нашем случае, в [email protected] запишется хендл актёра, в [email protected], [email protected] и [email protected] - смещение от актёра, а в [email protected] - модель машины.
Заканчивается работа функции опкодом 0AB2.
Первый параметр в этом опкоде - количество параметров, которые возвращаются из функции и запишутся в соответствующие переменные, указанные в опкоде 0AB1. Если функция не должна возвращать параметров, то указываем 0. Если функция возвращает один или несколько параметров - указываем соответствующее значение и далее вписываем необходимые значения или переменные, значения которых должны быть возвращены.
SCM-функции могут быть вложенными, как и gosub-ы - можно использовать SCM-функции внутри других SCM-функций.
У каждой функции есть свой независимый набор локальных переменных - можно вызывать их, не боясь, что вы потеряете данные из локальных переменных основного потока.
У SCM-функций есть один неприятный недостаток - они сильно замедляют работу скрипта. Если использование десятка-другого функций за один цикл игры никак не отразится на производительности игры, то сотня функций за один цикл игры может заметно снизить фпс. Таким образом, не рекомендуется использовать SCM-функции в циклах с большим количеством итераций.
У SCM-функций есть одна особенность - если передавать в неё строковые переменные ( [email protected], например ), то в соответствующую локальную переменную функции запишется указатель на строковую переменную ( т.е. на переменную [email protected] в данном примере). Для тех, кто не разбирается в работе с памятью, могу объяснить проще - строковые параметры в обычном виде в функцию передать нельзя. Если вы хотите передать строку, то нужно передавать её в виде 4 последовательных переменных, начиная с той, в которую записана строка. Например:
[email protected] = "Function"
0AB1: @AddGXT 4 [email protected] [email protected] [email protected] [email protected]
А в функции уже можно использовать её как строковую переменную:
Я думаю, на этом закончим урок. Я постарался раскрыть все известные мне детали, хотя мог чт о-нибудь и упустить. Если есть вопросы или вы хотели бы видеть урок по теме, которая вас интересует - пишите в комментариях.|1983|315|0||ispolzovanie_scm_funkcij_opkod_0ab1|1504597275