Кодинг в Sanny Builder 3

Материал из GTAModding.ru
Перейти к: навигация, поиск
Crystal Clear app kedit.png В этой статье не хватает введения.
Согласно правилам оформления статья должна начинаться с вводной информации, содержащей краткие сведения о предмете статьи.
Вы можете помочь проекту, написав введение.

Содержание

Типы данных

[COLOR=BLUE]$[/COLOR] - обозначение глобальных переменных. Их значения могут использоваться в любом месте кода.

 0004: $MyVar = 100


[COLOR=GREEN]@[/COLOR] - в начале: метка

0002: jump @MyLabel


[COLOR=BLUE]@[/COLOR] - в конце: локальная переменная. Их значения используются только в пределах одного потока

0006: 100@ = 10


[COLOR=RED]'...'[/COLOR] - текст (макс. 15 символов).

Допускается пустое значение: [COLOR=RED]' '[/COLOR]

03A4: name_thread 'MAIN'


[COLOR=RED] "..."[/COLOR] - текст (максимум определяется опкодом)

Также вы можете использовать в тексте одинарные кавычки или двойные кавычки. Для двойных кавычек необходимо использовать специальный префикс \.

Допускается пустое значение: [COLOR=RED]" "[/COLOR]

0662: write_debug_message "Hello, \"world\"! 'Here we go!'"


[COLOR=BLUE]s$[/COLOR] - глобальная стринговая переменная

05A9: s$MyString = 'GLOBAL'


[COLOR=BLUE]@s[/COLOR] - локальная стринговая переменная

05AA: 1@s = 'LOCAL'


[COLOR=BLUE]v$[/COLOR] - глобальная стринговая переменная

06D1: v$MyString = "LONG_GLOBAL"


[COLOR=BLUE]@v[/COLOR] - локальная стринговая переменная

06D2: 1@v = "LONG_LOCAL"


[COLOR=BROWN] '''#''' [/COLOR]- имя модели из одного из IDE - файлов игры

0247: request_model #CELLPHONE


[COLOR=BLUE]&[/COLOR] - прямой байтовый адрес (ADMA). Читает и пишет значения по указанному адресу Может использоваться в тех же случаях, когда используется тип $.

&57 += &120(&231,4i)

(примечание: число после & - локальное смещение внутри файла main.scm, относительно его начала; адрес, куда будет записано значение)


[COLOR=BROWN] 0x[/COLOR] - число в шестнадцатиричном формате. [COLOR=BROWN]-0x[/COLOR] - отрицательное значение

0004: $var = -0xBB08

Число должно быть в интервале [COLOR=BROWN]-80000000..7FFFFFFF[/COLOR]

Переменные

Переменные используются для хранения каких-либо данных. Вы можете читать их значения, записывать в них новые. Переменные бывают двух типов: глобальные (их значения доступны из любой миссии или потока) и локальные (только в пределах одного потока). Переменные используются в качестве операндов (членов) математических и логических выражений. Sanny Builder позволяет не использовать опкоды в подобных выражениях. Например, вы можете писать

$var = 0

вместо

0004: $var = 0

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

Однако, если в выражении в обоих сторон участвуют переменные, то компилятор может не знать, какой именно опкод необходим в данном случае. Это происходит из-за того, что возможны два варианта: если обе переменные типа Integer или типа Float.

Для того чтобы подсказать компилятору тип переменной, она должна быть объявлена через конструкцию VAR..END. Она позволяет объявлять переменные и их типы, для последующего манипулирования ими.

Синтаксис:

var
<имя переменно>: <ноы тип>
end

(При нажатии Ctrl+[space] появится список типов)

Например используйте код

var
$1stIntVar : Integer
$2ndIntVar : Integer
end

и вы можете использовать их в математических операциях подобно

$1stIntVar = $2ndIntVar 
$1stIntVar *= $2ndIntVar

Поддерживаются следующие типы переменных:

  1. Integer, Int - integer values (целые)
  2. Float - floating-points values (дробные)
  3. String, ShortString - Fixed length string variable (только для массивов, используйте s$, @s для переменных)
  4. LongString - Variable length string variable (только для массивов, используйте v$, @v для переменных)

Кроме глобальных переменных можно объявлять и локальные переменные. Но нужно помнить, что в этом случае все такие переменные во всех потоках будут иметь один и тот же тип. Чтобы избежать этого, вы можете переобъявлять переменные в каждом потоке.

Например:

Thread 'Food'
Var
10@ : Float
$Var : Float
End
$var = 1
10@ = $Var
end_thread
 
Thread 'Loop'
Var
10@ : Int
$Var : Int
End
$var = 1
10@ = $Var
end_thread


В первом потоке переменная [color=blue]10@[/color] будет расцениваться как float, во втором - как integer. Вообще вы можете переобъявлять переменные сколько угодно раз.

Также вы можете инициализировать значение переменной сразу при объявлении. Для этого после указания типа поставьте знак = и стартовое значение:

var
$fVar: float = 1.0
end

Переменная $fVar будет запомнена как Float и одновременно в SCM будет записан опкод:

0005: $fVar = 1.0

Инициализация доступна только для переменных, но не массивов!

Константы

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

Чтобы создать константу, используйте конструкцию CONST..END. Ее синтаксис выглядит следующим образом:

CONST
<имя константы> = <значение>
END

Имя константы - любой допустимый идентификатор (латинские буквы, цифры и знак подчеркивания). Не допускается использование преопределенных имен вроде Continue, True, And и т.д. Значение - число (метка, модель); строка; выражение (например, класс или переменная); другая константа.

Пример использования:

const
MoneyRequired = 30
PlayerMoney = $PLAYER_CHAR.Money
end
 
if
PlayerMoney > MoneyRequired
then
PlayerMoney += -1
end

При компиляции константа MoneyRequired будет заменена на число 30, а PlayerMoney на выражение $PLAYER_CHAR.Money

Компилятор также использует 2 внутренние константы True и False, значения которых равны 1 и 0 соответственно.

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

const
VarName = $Var
IndexName = 25
end
VarName[IndexName] = 0

Для компиляции такого выражения вы должны указать опкод, например:

0004: VarName[IndexName] = 0

Также определенные ограничения возникают при компиляции констант-выражений.

Список констант можно вызвать в любом месте кода нажатием Ctrl + [space].

Массивы

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

Массивы поддерживаются играми SA и LCS, VCS.

Синтаксис:

San Andreas:

<имя массива>(<имя индексной переменной>,<размер><тип>)

Liberty City Stories, Vice City Stories:

<имя массива>(<имя индексной переменной>,<размер>)


<Имя массива>: локальная или глобальная переменная. Имя переменной должно быть выбрано с учетом размера массива. Например, в потоке нельзя использовать в качестве имени переменную [COLOR=BLUE]33@[/COLOR], если размер массива больше 1, так как в потоках максимально допустимая локальная переменная это [COLOR=BLUE]33@[/COLOR], а элемент массива [COLOR=BLUE]33@[/COLOR] с индексом больше 0 будет за этими границами.

<Имя индексной переменной>: любая переменная.

<Размер>: любое целое число больше нуля.

<Тип>: буквы i f s v обозначающие один из типов массива:

i: integer, только целые значения, размер элемента 4 байта
f: float, дробные значения, размер элемента 4 байта
s: string, строки с фиксированной длиной 8 байтов
v: longstring, строки с фиксированной длиной 16 байтов

В LCS, VCS элементы массива могут иметь только размер 4 байта, поэтому указание типа не требуется. Массив может содержать элементы только одного типа.

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

$index = 0
$array($index,10i) = 1

Sanny Builder позволяет упростить работу с массивами двумя способами:

1) определить его в блоке VAR..END

Используется следующая запись:

 var
<array name>: array <size> of <type>
end

Например:

var
$FloatArray: array 10 of Float
end

После этого вы можете работать с этим массивом без указания его типа и размера. Например:

$FloatArray[$RndIndex] += 100.0

2) использовать индексированные переменные

Допустим, у вас есть массив [color=blue]$strings[/color], состоящий из 10 элементов типа s. Вы можете обратиться к его элементам, напрямую через переменную [color=blue]$strings[/color]. Например, для записи в последную ячейку массива используйте запись:

s$strings[9] = 'str10'

Индексированные переменные очень удобно использовать для инициализации массива с разными стартовыми значениями элементов:

s$strings[0] = 'str1'
s$strings[1] = 'str2'
 
//...
 
s$strings[9] = 'str10'

После этого вы можете использовать и полный вариант записи:

$index = 9
if 
s$strings($index,10s) == 'str10'
then
0@ += 1
end

Такие переменные могут использоваться и в качестве имени класса, когда они объявлены как массив, например

$cars[0].Destroy

По умолчанию при декомпиляции в режиме SA элементы массива записываются как индексированные переменные. Вы можете отключить эту возможность через консоль (команда toggle constant_indexes off). Тогда переменные будут декомпилироваться как обычно. Возможность декомпилировать с данной опцией доступна и для LCS, VCS (по умолчанию выключено).

Условия

Для проверки условия (-ий) необходимо использовать оператор IF.

Допускается использование двух видов проверки:

  1. низкоуровневый
  2. высокоуровневый

Низкоуровневые условия

00d6: if {<N>}
//... <condition 1>
//... <condition 2>
//...
//... <condition n+1>
004d: jump_if_false {<label>}

<N> - параметр, обозначающий количество условий. 0 - проверяется 1 условие 1..8 - 2 и более условий (максимум 9), связанных логическим оператором AND. Это значит что проверка выполнится, если ВСЕ условия, входящие в нее, верны. 21..28 - 2 и более условий (максимум 9), связанных логическим оператором OR. Это значит что проверка выполнится, если хотя бы ОДНО условие, входящее в нее, верно.

<label> - имя метки, на которую должен перейти скрипт, если условие ложно.

Sanny Builder допускает не использовать параметр 0 для одиночного условия. Таким образом, IF тоже самое что IF 0.

Также вы можете использовать ключевые слова AND или OR вместо числовых параметров*. Тогда компилятор сам будет высчитывать необходимое значение.

Например:

if and 
$var > 0
$var2 == 10.0
jf @anywhere

Компилятор подставит цифру 1 вместо and.

* В опциях должна быть включена проверка условий. IF AND - условия связываются логическим оператором AND (1..8) IF OR - условия связываются логическим оператором OR (21..28)

Высокоуровневые условия

Sanny Builder поддерживает конструкции IF..THEN..END и IF..THEN..ELSE..END*

Создание условия происходит по правилам, описанным выше. После слова THEN вы указываете команду (-ы), которые должны выполняться, если условие верно. После слова ELSE вы указываете команду (-ы), которые должны выполняться, если условие ложно. Условие заканчивается словом End.

if $var == 5
then 
Inc($var)
else
Dec($var)
end

Допускается использование вложенных условий.

*В опциях должна быть включена проверка условий.

В качестве операторов сравнения в условиях могут использоваться следующие их виды*:

a == b   a равно b 
a >= b   a больше либо равно b 
a > b    a больше b 
a < b    a меньше b 
a <= b   a меньше либо равно b 
a <> b   a не равно b 

Поддерживаются также их вариации со словом NOT.

* При условии, что вы не используете опкод в выражении.

Циклы

В SB используются следующие виды циклов:

  1. FOR..END
  2. WHILE..END
  3. REPEAT..UNTIL

Циклы могут быть вложенными (т.е. один цикл внутри другого).

Внимание: не забывайте устанавливать задержку (0001: wait) в циклах, чтобы предотвратить зависание игры.

FOR..END

Этот оператор задает цикл со строго определенным числом итераций (повторений) Для него используется следующий синтаксис:

FOR <counter> = <initial value> TO/DOWNTO <final value> [step <int> = 1] ... END

Основные параметры: <counter> - переменная, которая используется в качестве счетчика итераций (повторений) цикла.

<initial value> - стартовое значение счетчика: любое число (может быть имя модели).

TO/DOWNTO - при TO счетчик будет наращивать свое значение, при DOWNTO уменьшать.

<final value> - конечное значение цикла, при котором он завершит работу: любое число (может быть имя модели). Помните, что при DOWNTO конечное значение должно быть меньше стартового.

<step> - (необязательный параметр) значение приращения или уменьшения счетчика при итерациях. По умолчанию его значение равно 1. При использовании дробных чисел в качестве значений счетчика, вы должны также указать параметр step с дробным значением.

Пример цикла:

var
$value: int = 0
$final: int = 100
end
 
FOR $MyCounter = 1 to $final step 2
$value += $mycounter
end

WHILE..END

Синтаксис:

WHILE <condition> ... END

Цикл WHILE работает до тех пор, пока выполняется условие. Условие проверяется перед итерациями, поэтому если оно будет сразу ложным, то цикл не выполнится никогда.

$var = 10
 
while $var > 11
inc($var)
end

так как условие в цикле ложно, скрипт никогда не придет на команду Inc([COLOR=BLUE]$var[/COLOR])

Оператор While может принимать в качестве условий логические константы True и False: While True .. End - цикл будет выполняться бесконечно, пока вы не прервете его командой Break. While False .. End - цикл будет игнорироваться компилятором.

В текущей версии для цикла WHILE доступно только одно условие. Вы можете проверять большее кол-во условий внутри тела цикла и использовать команды Break и Continue.

REPEAT..UNTIL

Синтаксис:

REPEAT ... UNTIL <condition>

Цикл Repeat работает до тех пор пока не выполнится условие после команды Until. Условие проверяется после итераций, поэтому цикл всегда будет иметь минимум одну итерацию.

Оператор Repeat может принимать в качестве условий логические константы True и False: Repeat .. Until True - цикл будет иметь только одну итерацию Repeat .. Until False - цикл будет выполняться бесконечно, пока вы не прервете его командой Break.

В текущей версии для цикла REPEAT доступно только одно условие. Вы можете проверять большее кол-во условий внутри тела цикла и использовать команды Break и Continue.

Использование Continue и Break

Иногда вам может потребоваться пропустить текущую итерацию и перейти к следующей, например после проверки условия. Для этого существует ключевое слово Continue. Оно может использоваться в качестве параметра. Тогда оно обозначает метку, после которой происходит приращение счетчика и переход к следующей итерации.

Например:

if
$currentactor.dead
jf continue // 'continue' это внутренняя метка в начале цикла

В качестве отдельной команды оно обозначает опкод 0002 (jump), с переходом на следующую итерацию.

if
not $currentactor.dead
jf @next
Continue // jump continue
:next

Кроме этого существует команда Break, которая прерывает цикл. Она может использоваться как отдельная команда так и как параметр (jf break)

Примеры :

1) Пример использование цикла REPEAT...UNTIL:

Смысл следующий: мы создаём машину и актёра в ней , затем заставляем машину понтоваться, т.е. поднимать и удерживать колёса разными способами, прям как на соревновании лоурайдеров.

create_thread @Anims    // создаём поток с именем Anims 
...
 
:Anims    // начинаем поток
wait 0    // ждём 0 мс,если не напишем,то может вылететь
#REMINGTN.Load    // объявляем нужную модель машины - Ремингтон
#FAM2.Load    // объявляем нужную модель актёра - Член Грув Стрит банды
038B: load_requested_models    // загружаем ранее объявленые модели
 
:Anims_2    // создаём второй label
wait 0    // ждём 0 мс,если не напишем,то может вылететь
if and    // условие с выполнением всех подусловий(проверок)
#REMINGTN.Available    // проверка (загрузилась ли модель #REMINGTN)
#FAM2.Available    // проверка (загрузилась ли модель #FAM2)
player.Defined($PLAYER_CHAR)    // проверка (существует ли игрок)
jf @Anims_2    // если хоть одна из проверок возвратила значение False,
    // т.е. не выполнилась, то переходим к началу label'a
wait 5000    // ждём 5 мс,просто для удобства
car.Create(4@,#REMINGTN,2492.6,-1669.5,13.4) // создаём тачку напротив дома Карла
0129: 5@ = create_actor 4 #FAM2 in_car 4@ driverseat // создаём актёра в этой машине
wait 3000    // ждём 3 мс,просто для удобства
Car.ToggleHydraulics(4@) = True // устанавливаем на машину гидравлику, если
    // не поставим, то финтов машина делать не будет
$Timer = 25   // Создаём переменную,и приравниваем её к 25, это будет наш таймер
 
:Anims_3    // создаём следующий label
wait 0        // ждём 0 мс,если не напишем,то может вылететь 
REPEAT    // начинаем цикл
wait 10    // ждём 10 мс
07F5: car 4@ control_hydraulics 1000.0 0.0 0.0 0.0
  // машина поднимает к-л колесо, вот номера колёс 1000.0 - переднее левое,
 // 0.0 - заднее левое, следующий 0.0 - переднее правое и 
 // последний 0.0 - заднее правое.
$Timer -= 1    // отнимаем от нашей переменной 1
UNTIL  $Timer <= 1
 // пока таймер не будет меньше либо равен 1, наш цикл будет выполнятся,
 // так всё запутано из-за того, что чтобы поднять колесо надо выоплнить 
 // эту команду большое количество раз и за маленькое время, и чтобы колесо 
 // держалось навису эту команду тоже надо поддерживать
 // принцип действия заключается в том, что мы задаём переменной $Timer 
 //значение 25, и с каждым разом когда мы выполняем команду поднятия колеса,
 // от этой переменной отнимается еденица,
 // команда выполняется каждые 10 мс(wait 10), и когда $Timer становится  
 //равной или меньше единицы, мы переходим к следующему действию, 
 //поднятие уже  другого колеса, но предварительно опять
 // задаём переменной $Timer значение 25, а то если она равна нулю,
 // то выполнение перекинется на поднятие другого колеса, 
 // и так пока не будет найдено хоть одно нормальное значение $Timer
$Timer = 25
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 0.0 1000.0 0.0 0.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 25
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 0.0 0.0 1000.0 0.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 25
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 0.0 0.0 0.0 1000.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 25
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 1000.0 0.0 1000.0 0.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 25
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 0.0 1000.0 0.0 1000.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 25
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 1000.0 1000.0 0.0 0.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 25
REPEAT
wait 10
07F5: car 4@ control_hydraulics 0.0 0.0 1000.0 1000.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 120
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 1000.0 0.0 0.0 1000.0
$Timer -= 1	
UNTIL  $Timer <= 1
$Timer = 120
REPEAT 
wait 10
07F5: car 4@ control_hydraulics 0.0 1000.0 1000.0 0.0
$Timer -= 1 UNTIL  $Timer <= 1
$Timer = 25
jump @Anims_3    // тут прыгаем на начало label'a , чтобы все действия

Если вытащить из машины актёра,то машина перестанет поднимать колёса.

2) Пример использование цикла FOR...END:

Давайте создадим последовательно 10 актёров на одинаковом расстоянии друг от друга,используя данный тип цикла и массив:

create_thread @Actors    // создаём поток с именем Actors
:Actors   // начинаем поток
wait 5000 // делаем задержку в 5 секунд,чтобы увидить действие цикла в игре самому
var            // объявляем переменные
$num: Integer = 10    // это количесво актёров
$actor: array 10 of Actor    // это массив из 10 актёров
$X: Float    // координата по оси X
$Y: Float    // координата по оси Y 
end           // заканчивание объявления переменных
 
#WMOPJ.Load    // объявляем нужную модель
038B: load_requested_models    // загружаем модель
 
while not #WMOPJ.Available
    //цикл-пока модель не загрузится,действие скрипта дальше не пойдёт
wait 0        // задержка,даже нулевая,неотемлемая часть любого цикла
end        // конец цикла
 
wait 0 // ждём 0 мс, желательно писать после любого цикла,на всякий случай
Actor.StorePos($PLAYER_ACTOR, $x, $y, $z)
    // записываем коорд-ы игрока в переменные $x,$y и $z
inc($y,2)    // прибавляем к Y координате число 2
dec($x,3)   // отнимаем от X координаты число 3
 
FOR $CurrentIndex = 1 TO $num    // начинаем цикл создания актёра
inc($x)// прибавляем к координате X число 1, // 1 - число,которое задаётся автоматически
$actor[$CurrentIndex].Create(4, #WMOPJ,  $x, $y, $z)
  //тут создаём актёра,теперь поподробнее:
 // $actor - имя массива актёров, // $CurrentIndex - номер элемента массива, мы номера
    // элементов перебираем этим циклом,сами посмотрите    
wait 250
 //задержка - неотемлемая часть любого цикла,// если не писать, то толку от цикла не будет
end    // конец цикла
 
#WMOPJ.Destroy    // удаление модели из памяти

Классы

Sanny Builder допускает использование классов при написании кода. Классы - это группа опкодов, относящихся к какому-либо виду объектов в игре: игрок, актер, машина и т.д.

Все классы заранее определены в файле classes.db и изменять их в процессе кодинга невозможно. Все изменения вносятся напрямую в этот файл.

Каждый класс обладает набором команд (опкодов). Их можно разделить на несколько групп:

  1. условные
  2. процедуры (методы)
  3. свойства

Условные команды

Условные опкоды в списке команд, вызываемом нажатием Ctrl + [space], обозначаются словом Check. Чаще всего у них один параметр - это хендл (имя) владельца класса: машины, игрока и т.д. Например:

if
Player.Defined($PLAYER_CHAR)
jf @anywhere

Процедуры

Процедурные опкоды предназначены для выполнения какого-либо конкретного действия в игре: движение объекта, уничтожение его и т.п. Отдельный вид таких опкодов - это конструкторы, которые создают объект (актера, машину) и возвращают его хендл. В SB конструкторы могут использоваться как процедура, так и как свойство.

Player.Create($PLAYER_CHAR, #NULL, 2488.5601, -1666.84, 13.38) - процедура
$PLAYER_CHAR = Player.Create(#NULL, 2488.5601, -1666.84, 13.38) - свойство-конструктор

Эффект будет одинаков.

Свойства

Свойства класса используются для чтения или записи каких-либо значений внутри класса. Например свойство Money класса Player позволяет оперировать с тремя опкодами:

0109: player $PLAYER_CHAR money += 1000000
010A: player $PLAYER_CHAR money > 461@
010B: 4@ = player $PLAYER_CHAR money

После того как это свойство описано в файле classes.db вы можете использовать следующие команды:

player($PLAYER_CHAR).Money += 1000000
player($PLAYER_CHAR).Money > 461@
4@ = player($PLAYER_CHAR).Money

В настоящий момент существует серьезное ограничение по использованию свойств в качестве операндов выражений. Sanny Builder может скомпилировать только такие выражения, которые заранее прописаны в файле classes.db. Т.е. вы не можете, например, использовать такое выражение:

player($PLAYER_CHAR).Money -= 1000000

поскольку для операции вычитания нет отдельного опкода.

Члены класса

Начиная с версии 2.6 также можно инициализировать переменные как члены класса и оперировать с ними как с классом. Например:

var
$PLAYER_CHAR: Player
end

Мы объявили переменную [COLOR=BLUE]$PLAYER_CHAR[/COLOR] как класс Player. Теперь для нее доступны все команды, какие есть для этого класса. Например:

if
$PLAYER_CHAR.Defined
jf @anywhere

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

Player.SetClothes($PLAYER_CHAR, "PLAYER_FACE", "HEAD", Head)
=
$PLAYER_CHAR.SetClothes("PLAYER_FACE", "HEAD", Head)

Такие переменные также можно переобъявлять и изменять их тип.

Класс Model

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

#AK47.Load
 
:loop
wait 0
if
#AK47.Available
jf @loop

Это будет тоже самое что

Model.Load(#AK47)
 
:loop
wait 0
if
Model.Available(#AK47)
jf @loop

Расширенные названия параметров

В классах вы можете использовать текстовые названия для параметров для повышения читабельности кода. Например:

Player.SetClothes($PLAYER_CHAR, "VEST", "VEST", Torso)

Torso - это параметр типа Extended.

Для облегчения использования расширенных названий, их список для текущей команды может вызываться нажатием Ctrl + [space]. Просто установите курсор туда, где должен быть расширенный параметр, (обозначается словом Extended во всплывающей подсказке), нажмите ctrl + [space] и в редакторе появится список возможных имен с указанием числового значения для каждого из них.

Ключевые слова

Заменяют собой опкоды для простых команд. Например кейворд WAIT при компиляции будет заменен на опкод 0001. Т.е. можно писать

wait 0

вместо

0001: wait 0

Список кейвордов содержится в файле keywords.txt (свой для каждой игры). В редакторе его можно вызвать нажатием Ctrl + [space]

Дополнительные команды

INC - эта команда увеличивает значение переменной, переданной как первый параметр, на значение второго параметра. Второй параметр может не использоваться, тогда вместо него будет установлена 1.

Inc($IntVariable, $Value)
=
$IntVariable += $Value
 
Inc(1@)
=
1@ += 1

DEC - эта команда уменьшает значение переменной, переданной как первый параметр, на значение второго параметра. Второй параметр может не использоваться, тогда вместо него будет установлена 1.

Dec($IntVariable, $Value)
=
$IntVariable -= $Value
 
Dec(1@)
=
1@ -= 1

MUL - эта команда умножает значение переменной, переданной как первый параметр, на значение второго параметра.

Mul($IntVariable, $Value)
=
$IntVariable = $IntVariable * $Value

Второй параметр может не использоваться, тогда вместо него будет установлена 2.

Mul(1@)
=
1@ = 1@ * 2

DIV - эта команда делит значение переменной, переданной как первый параметр, на значение второго параметра.

Div($IntVariable, $Value)
=
$IntVariable = $IntVariable / $Value

Второй параметр может не использоваться, тогда вместо него будет установлена 2.

Div(1@)
=
1@ = 1@ / 2

(sys) ALLOC* - эта команда устанавливает адрес памяти для переменной. Должна использоваться только для переменных с ТЕКСТОВЫМИ именами. Для остальных адрес памяти устанавливается по их имени: переменная $40 всегда будет иметь ячейку памяти #40.

Alloc($MyVar, 40) - переменная $MyVar будет иметь адрес 40.
  • команды, обозначенные словом (sys), не отражаются в коде, а являются вспомогательными для компилятора.

SQR - эта команда вычисляет квадрат значения (вторую степень) переменной, переданной в качестве параметра.

sqr($var) 
=
$var *= $var

Тип переменной должен быть определен.

RANDOM - эта функция возвращает случайное число в интервале, указанном параметрами.

$rnd = random(1, $high)

Данную функцию можно использовать как для типа Integer, так и для типа Float. Выбор опкода будет зависеть от типа объявленной переменной, в которую записывается случайное значение ([color=blue]$rnd[/color]).

HEX..END

Данная конструкция предназначена для прямой записи шестнадцатиричных значений в SCM или IMG файл*. Например:

hex
04 00 02 0800 04 01
end
Это будет тоже самое, что
0004: $2 = 1

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

:get_offset
hex
04 00 02 $PLAYER_CHAR 01 @get_offset
end
Это будет тоже самое, что
0004: $PLAYER_CHAR = @get_offset

Также можно использовать в конструкции hex..end тип aDMA. Это удобно использовать для записи чисел. Число после знака & может быть как положительным, так и отрицательным; как в десятичном, так и в шестнадцатиричном формате.

hex
&1000 &-0xA33500
end

Также можно компилировать строковые значения. Для этого заключите слово в двойные кавычки ([color=red]"..."[/color]) и поставьте перед ними пробел.

Например,

hex
09 "Word1" 20 "Word2"
end

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

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

Директивы

Препроцессорные директивы - это специальные слова, которые указывают компилятору на необходимое поведение в процессе компиляции. Они обозначаются символом $, а также заключены в фигурные скобки {}.

Список доступных директив:

  1. $VERSION
  2. $VERSION_RESTORE
  3. $INCLUDE
  4. $EXTERNAL
  5. $CLEO

$VERSION

Данная директива указывает компилятору, какую версию опкодов необходимо использовать из INI-файла (SASCM.INI, VICESCM.INI и т.д.). В настоящий момент INI-файлы содержат только одну версию опкодов, поэтому данная директива может не использоваться.

Синтаксис:

$VERSION x.y.zzzz

x - код игры. 
   1 - gta3; 
   2 - vc; 
   3 - sa;
   4 - lcs;
   5 - vcs;

y - вид порядка следования параметров в опкоде.
   0 - оригинальный (параметры в INI идут последовательно 0, 1, 2 и т.д.)
   1 - неоригинальный (параметры в INI идут непоследовательно 2, 0, 1, и т.д.)

zzzz - код версии файла

По умолчанию компилятор использует версию:

<текущий режим редактирования>.1.0000

$VERSION_RESTORE

Данная директива восстанавливает прежнюю версию, которая была до использования директивы $VERSION. В настоящий момент INI-файлы содержат только одну версию опкодов, поэтому данная директива может не использоваться.

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

[color=green]{$VERSION 3.1.0001}[/color]

... <код, написанный на версии 0001> ....

[color=green]{$VERSION 3.1.0000}[/color]
... <код, написанный на версии 0000> ....
[color=green]{$VERSION_RESTORE}[/color] [color=navy]// восстанавливаем версию 0001[/color]

... <код, написанный на версии 0001> ....

$INCLUDE

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

Синтаксис:

[color=green]{$INCLUDE file_path}[/color]

или

[color=green]{$I file_path}[/color]

Например,

[color=green]{$I loadwav.txt}[/color]

или

[color=green]{$I C:\dev\getarrayindex.txt}[/color]

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

  1. папка, где находится файл, содержащий данную директиву
  2. Sanny Builder\data\<game>
  3. корневая папка Sanny Builder'а
  4. корневая папка игры

Если ни в одной из указанных папок не содержится такой файл, компилятор сообщит об ошибке.

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

$EXTERNAL

Данная директива заставляет скомпилировать файл как внешний скрипт. Это означает, что получившийся файл будет без заголовка и с локальными метками, т.е. полным аналогом scm-файлов из файла script.img. Использование данной директивы подразумевает, что в скрипте будет только один поток (также без миссий и внешних скриптов). Аналогом использования данной директивы является опция SKIP_SCM_HEADER. Данную опцию также можно переключить на главной панели инструментов. Вместо $EXTERNAL можно использовать короткий вариант $E.

Синтаксис:

[color=green]{$EXTERNAL}[/color]

или

[color=green]{$E}[/color]

$CLEO

Данная директива является аналогом директивы $E, однако полученный файл автоматически копируется в директорию ‘игра\CLEO’, и получает расширение, указанное в директиве.

Синтаксис:

[color=green]{$CLEO <расширение файла>}[/color]

Например,

[color=green]{$CLEO .cm}[/color]

или

[color=green]{$CLEO}[/color] [color=navy]// файл получит расширение по умолчанию - .cs[/color]

Таким образом, данная директива является идеальным решением для написания CLEO-скриптов