CLEO
August 26, 2020

CLEO: Урок 1 - Основы



И так, в этом уроке мы разберем что такое CLEO скрипты, как они работают, и как их создавать.

Что же такое скрипт? Скрипт - это файл, содержащий набор команд, которые будут выполняться игрой. Благодаря скриптам можно добавить в игру множество дополнительных функций и нововведений.

Чтобы написать свой собственный скрипт первым делом вам нужно скачать и установить Sanny Builder. Именно в нем и пишутся CLEO скрипты.

Теперь открываем SB и нажимаем Файл/Создать.

Файл создан, далее пишем такой код:

{$CLEO}
0000:

С этих строк начинается любой CLEO скрипт, поэтому его обязательно нужно писать.

В самом конце скрипта добавляем эту строку:

0A93: end_custom_thread

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

В последних версиях SB появился пункт в меню: Файл/Новый CLEO скрипт. Код написанный выше сам вставляется в редактор при создании скрипта таким способом.

Теперь разберемся с базовыми терминами и понятиями, которые будут вам необходимы при написании скриптов.

Опкод - действие выполняемое скриптом. Данный опкод устанавливает игроку игнорирование копами.

01F7: set_player $PLAYER_CHAR ignored_by_cops 1

Список опкодов можно посмотреть нажав Сервис/ Инструменты/ Поиск опкодов.
Чтобы скопировать опкод, выберите его и нажмите Enter (Ctrl+C тут не работает).

Поиск опкодов

Переменная - контейнер в котором можно хранить какие-либо данные: целые числа (int), дробные числа (float) или текст (string).
В CLEO существуют локальные и глобальные переменные.

Локальных переменных существует всего 32 штуки + 2 таймера. Обозначаются они цифрой и знаком @ после нее. Например: 0@, 1@, 2@, 3@ и так далее до 33@.

Глобальные переменные обозначаются так: $MYGUN, $WEATHER, $SITE и так далее. Их названия можно придумывать самим в отличии от локальных переменных. Но в CLEO скриптах ими пользоваться не рекомендуется, так как их использование может приводить к случайным вылетам игры.
Такие глобальные переменные как $PLAYER_ACTOR, $PLAYER_CHAR, $ONMISSION использовать в CLEO можно, первые две переменные обозначают игрока, а третья хранит данные о том запущена какая-либо миссия или нет.

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

С переменными можно проделывать арифметические действия, приравнивать, умножать, делить, прибавлять и отнимать. Арифметические действия выглядят так: 1+=2, 3/=4, 5*=9 и тд. То есть после знака операции всегда ставится знак = (не просто 2+1, а 2+=1).

Задание:

1@ = 10
2@ = 25
1@ += 2@
1@ -= 1

Как думаете чему будет равна переменная 1@ после выполнения всех операций?
Подсказка: 10+25-1 = 34

Переменной можно обозначать актера, транспорт, объекты, эффекты, оружие и много много чего еще. Простыми словами переменная в данном случае - это имя актера. В жизни мы могли бы назвать его Вася, но мы в GTA SA и поэтому назовем его, например, 5@. В скриптинге это называется не имя, а хэндл. Не получив хэндл актера, машины, объекта, мы не можем производить никаких действий с ними.

Первый опкод записывает в переменную 4@ ближайший автомобиль, а в переменную 5@ ближайшего педа. Второй опкод убивает актера 5@. Третий опкод взрывает машину 4@:

0AB5: store_actor $PLAYER_ACTOR closest_vehicle_to 4@ closest_ped_to 5@
05BE: AS_actor 5@ die
020B: explode_car 4@


Метка - обозначение определенного места в коде, к которому можно переходить командой jump. Метки нужны для передвижения по скрипту.

Обозначаются они двоеточием:

:LABEL1
:GUNS
:DYOM_MENU

Названия меток могут быть любыми, но обязательно английскими буквами и без пробелов.

Стоит сказать, что выполнение скрипта всегда происходит сверху вниз, каждая строка выполняется по очереди. Не может выполняться 2 или 3 куска кода одновременно. Для того и нужны метки, чтобы, к примеру, при достижении конца скрипта мы могли вернуться в его начало и заново выполнить код.

По меткам можно передвигаться с помощью опкодов jump @NAME, jf @NAME, gosub @NAME.

Задание:

:METKA1
jump @METKA3

:METKA2
jump @METKA1

:METKA3
jump @METKA2

На какой метке мы окажемся после выполнения кода?
Подсказка: мы окажемся на :METKA1, и далее код будет повторяться по кругу бесконечное число раз.


Условия - в любых скриптах всегда есть условия при которых выполняется то или иное действие. Чтобы проверить выполнено то или иное условие, нужно использовать опкод IF и после него добавить специальные условные опкоды. Их можно узнать по большому пробелу после двоеточия.

if
00DF:   actor $PLAYER_ACTOR driving 

Рассмотрим использование условий на примере небольшого скрипта.
Суть скрипта: если игрок в машине, то выключается HUD.

IF jf @NAME (сокращение от "jump if false") - если условие не выполнено, то переходим к метке NAME. Если выполнено - продолжаем движение вниз по коду.

:RADAR
wait 0 
if  
00DF:   actor $PLAYER_ACTOR driving 
jf @RADAR
0826: enable_hud 0 
jump @RADAR

IF Then End - если условие выполнено, то сработает код после Then, если нет, то скрипт пропустит эту часть и перейдет сразу к End

:RADAR
wait 0 
if  
00DF:   actor $PLAYER_ACTOR driving 
then 
0826: enable_hud 0 
end 
jump @RADAR

IF Then Else End - если условие выполнено, то сработает код после Then и сразу перепрыгнет к End. Если условие не выполнено, то сразу выполнится код после Else

:RADAR
wait 0 
if  
00DF:   actor $PLAYER_ACTOR driving 
then 
0826: enable_hud 0 
else
0826: enable_hud 1
end
jump @RADAR


Если должно быть выполнено сразу несколько условий, то нужно использовать IF AND

if and
00E1:   player 0 pressed_key 6 
00DF:   actor $PLAYER_ACTOR driving 
jf @NAME

Если нужно чтобы хотя бы одно из условий было выполнено, то используйте IF OR

if or
00E1:   player 0 pressed_key 6 
00DF:   actor $PLAYER_ACTOR driving 
jf @NAME

Задание:

{$CLEO}
0000:

:ONE
wait 0
if 
00DF:   actor $PLAYER_ACTOR driving 
then
jump @TWO
else
jump @TREE
end

:TWO
wait 0
0223: set_actor $PLAYER_ACTOR health_to 500
041E: set_radio_station 0
0826: enable_hud 0
jump @ONE

:TREE
wait 0
0826: enable_hud 1
JUMP @ONE

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

wait 0 - вы наверняка заметили в скрипте этот опкод, так зачем же он нужен? Это задержка 0 миллисекунд. Вы спросите, зачем же она нужна, если она равна 0? Это же означает что задержки нет! На самом деле это не так. Wait 0 - это минимально возможная задержка для скрипта.
Её необходимо ставить в том участке кода, который выполняется бесконечное или неопределенное количество раз. Если не добавить эту задержку, то игра просто зависнет так как скрипт будет выполняться бесконечно без какой-либо задержки и попросту не даст игре работать и выполнять другие функции.

Поначалу я не понимал, как это работает и просто ставил wait 0 после каждой новой метки. Например так:

:1
wait 0
jump @2

:2
wait 0
jump @1

В данном коде хватило бы всего одного опкода wait 0, так как в любом случае скрипт будет переходить на одну из меток, где есть задержка.

Но если мы напишем такой код:

:1
wait 0
jump @2

:2
jump @2

Нас гарантированно ждет зависание игры, так как скрипт будет бесконечно переходить на метку 2 без какой либо задержки.

Если вы всё же не поняли, в чем смысл этого опкода, то можете так же ставить его после каждой метки. Если вам не нужна максимальная скорость работы скрипта, в этом ничего страшного нет.

К следующему уроку ->


Полезные ссылки:

Руководство по Sanny Builder
Уроки по скриптингу от wmysterio
Программа-учебник по скриптингу
База данных опкодов
Темы для Sunny Builder