fallout.ru

Скрипты, команды, синтаксис – основная информация

Виды скриптов

Местные скрипты

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

Глобальные скрипты

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

AITravel 1150, 8899, 1110

Поэтому Вам придётся писать и имя NPC:

“NPC_ID” -> AITravel 1150, 8899, 1110 ;NPC_ID – это уникальное имя для каждого персонажа Конструктора

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

StartScript "Script ID"

или

StartScript, "Script ID"

С появлением Трибунала и Бладмуна была добавлена опция автоматического запуска Вашего глобального скрипта. Соответствующий список располагается в пункте “Edit starting Scripts”, меню “Gameplay”.

А так они отключаются:

StopScript "Script ID"

или

StopScript, "Script ID"

Прочтите также специальный раздел «нацеленные скрипты» в разделе Секретов и Приёмов.

Синтаксис

Перед тем, как мы начнём погружаться в детали, я должен объяснить Вам некоторые особенности ТЕС Скрипта.

Начало и конец скрипта

Begin Script_ID

End Script_ID

Каждый скрипт должен начинаться и заканчиваться ключевыми словами Begin и End соответственно. Имя – это уникальный идентификатор, с помощью которого Вы будете ссылаться на свой скрипт из других скриптов или из окна свойств объекта. Первой строчкой скрипта может быть комментарий, однако смысловая часть кода должна начинаться непосредственно с “Begin”.

Основной синтаксис функций

"Имя объекта" -> Функция, [параметры]

Стрелка показывает к какому объекту будет применена та или иная функция. Имя объекта (Object ID) – уникальный идентификатор объекта в Конструкторе и игре, отличающий его от других. В свойствах объекта это строка ID, а не Name! Если вызывать функцию без указания того, к какому объекту она применена, то объектом по умолчанию будет тот, к которому прикреплён скрипт с этой функцией.

Имя объекта может быть использовано и в качестве параметра:

"Имя объекта1" -> Функция, "Имя объекта2"

Движок Морровинда нерегистрозависим, однако для удобства чтения кода лучше использовать, скажем, GetSpellEffects вместо getspelleffects. Помните об этом.

Основной синтаксис: запятые, скобки, пробелы

В этом плане ТЕС Скрипт не очень требователен – большинство запятых и пробелов можно не ставить. Тем не менее, я бы посоветовал придерживаться следующих рекомендаций:

  • Ставьте запятые между параметрами функций.
  • Если имя объекта содержит пробелы, то Вам необходимо использовать кавычки: “Object ID”. Будет лучше, если Вы не будете использовать пробела в именах объектов, а пропишете всё в одно слово с использованием символа подчёркивания: “Object_ID”.
  • Привыкайте всегда оставлять пробелы до и после скобок и операторов:
    if ( variable == 1 ), а не if (variable==1); Object_ID1 -> Function, Object_Id2, а не Object_ID1->Function,Object_ID2. В то время как чаще всего это не играет никакой роли, иногда это может вызвать ошибки, отследить которые будет очень и очень сложно. А посему привыкайте.
  • Ввиду особенностей движка не стоит применять функции, к каким либо объектам, когда можно задать ID этих объектов в качестве параметров других функций. Например вместо:

    _dt_Racial_ClothierNord -> PositionCell, -348, 48, -221, 0, "Vivec, Agrippina Herennia: Clothier"

    Следует использовать

    PlaceItemCell, "_dt_Racial_ClothierNord", "Vivec, Agrippina Herennia: Clothier", -348, 48, -221, 0

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

Табуляция

Для Вашего собственного удобства используйте табуляцию в конструкциях типа if – elseif. Так гораздо проще увидеть их структуру, и Вы никогда не забудете поставить endif в конце. Сравните:

If ( variable1 )
            If ( variable2 )
                        [код]
            endif
endif

и

If ( variable1 )
If ( variable2 )
[код]
endif
endif

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

Переменные

Объявление переменных

В ТЕС Скрипте существует три типа переменных: короткие, длинные и с «плавающей» запятой. Как написано в руководстве, каждый из этих типов оперирует с соответствующими значениями:

Short            -32,768 to 32,767 (целочисленные значения)
Long            -2,147,483,648 to 2,147,483,647 (расширенный диапазон целочисленных значений)
Float            3.4E +/- 38 (7 знаков после запятой)

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

Теоретически также должны существовать переменные, работающие с текстом, однако это выходит за рамки моих познаний. К сожалению, также не существует типа данных «запись», чтобы, например, хранить имя объекта. Это значительно уменьшает возможности ТЕС Скрипта до определённых границ.

Переменные можно разделить на местные (действующие только в определённом скрипте) и глобальные (действующие во всех скриптах).

Местные переменные

Местные переменные объявляются непосредственно в скрипте:

Float имя_переменной
Short имя_переменной
Long имя_переменной

Местные переменные уникальны в пределах одного скрипта. Это значит, что объекты с одинаковыми именами в разных скриптах никак друг на друга не влияют. Вы можете выбирать любые имена для своих переменных, однако они должны начинаться с буквы, не должны совпадать с именами функций или команд (это вызовет ошибку) и не могут содержать некоторых зарезервированных символов: -, +, /, *, =, ", ),( и т.д. Например "variable-1" является неправильным именем переменной, а "my_variable" напротив – правильным. Заметьте, что точка – это тоже зарезервированный символ (смотри «Ссылки на переменные из других скриптов»).

Глобальные переменные

Чтобы объявить глобальную переменную в меню “Gameplay” выберите пункт “Globals”. Щёлкните правой кнопкой мыши для создания новой переменной, назовите её и задайте ей тип и начальное значение. Глобальные переменные полезны, например, при создании объёмного квеста, когда необходимо отслеживать события вне пределов действия местных переменных. Это также простой способ передавать информацию из скрипта в скрипт. Они инициализируются нулём.

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

Ссылки на переменные из других скриптов

Если работает скрипт, прикреплённый к какому-либо объекту, то Вы можете изменять значения его переменных извне:

Set ИмяОбъекта.переменная to 100

или

Set ИмяОбъекта.переменная to местная_переменная

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

Заметьте, что следующая строчка работать не будет:

Set местная_переменная to ИмяОбъекта.переменная

Чтобы передавать информацию подобным путём, Вам придётся использовать глобальные переменные, или задавать значение для «местной_переменной» из другого скрипта, пользуясь методом, описанным выше.

if ( ДругойОбъект.x > 0 )

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

К тому же, подобный синтаксис работает и с глобальными скриптами:

set Имя_глобального_скрипта.переменная to 1

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

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

К сожалению, одно из ограничений ТЕС Скрипта состоит в том, что вы можете передавать переменные в качестве параметров только строго определённым функциям. Это показано в списке ниже. Например команды Position и PositionCell не могут получать в качестве параметров переменные, так что перемещение может осуществляться только в рамках определённых заранее.

Математические вычисления

Вы можете использовать стандартные операции в командах set (возможно, и где-то ещё, но я не пробовал), чтобы совершать в скриптах определённые вычисления.

Сложение:
+
Вычитание:
-
Умножение:
*
Деление:
/

Для подобных операций используется следующий синтаксис:

Set итоговая_переменная to (переменная1 + переменная2)

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

set пер1 to ( пер1 + ( знач1 * пер3 ) + ( знач2 * пер2 ) )

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

В скриптах Морровинда не очень много математических возможностей. Существует функция “Random”, а в Трибунале появилась также “GetSquareRoot” (получить квадратный корень). Если Вам необходимы более серьёзные вычисления, я советую Вам скачать Solaris’ Math Mod, доступный на Morrowind Summit.

Проверка условий

Использование if…elseif

Многое в ТЕС Скрипте опирается на конструкции if…elseif и их вариации. Очень важно понимать подобные конструкции, чтобы провоцировать события в игре в зависимости от решений игрока.

Условие верно (“true”), когда его значение равно 1 (во многих языках программирования просто «не 0»), и ложно (“false”), когда его значение – 0. Существуют функции, возвращающие “true”, как результат определённых операций. Например, GetAIPackageDone возвращает 1 на одну долю секунды, когда завершается NPC завершает своё направленное движение. Таким образом примеры:

If ( GetAIPackageDone )
           
endif

и

if ( GetAIPackageDone == 1 )
           
endif

равны по своему значению. Оба примера проверяют, возвращает ли функция 1, то есть ИСТИНУ. Запомните, как правильно употребляются операторы сравнения:

"Равно"
==
"Неравно"
!=
"Больше, чем"
>
"Меньше, чем"
<
"Больше или равно"
>=
"Меньше или равно"
<=

Наряду с if Вы можете использовать и elseif, конструкцию, которая будет проверять Ваше условие на другое значение, отличное от условия в if. Else же будет выполняться только, если ни одно условие не оказалось верным.

If ( переменная == 1 )
            [делать что-то одно]
elseif ( переменная == 2 )
            [делать что-то другое]
else
            [делать что-то совершенно отличное]
endif

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

Существует максимальное количество возможных условных конструкций, которые будут выполняться в вашем скрипте. Точно я не уверен, но, по-моему, это что-то около 256 условий.

Цикл while

While ( условие )
; последовательность действий
EndWhile

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

Short desiredAmnt
SetStrength 0

while ( GetStrength <= desiredAmnt )
            modStrength 1
endwhile

Такой код через довольно короткий отрезок времени установит значение характеристики «Сила» равное значению переменной desiredAmnt. Следующая часть кода будет выполняться несколько дольше, так как условные конструкции для движка более громоздки, чем while:

if ( GetStrength < desiredAmnt )
            modStrength 1
endif

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

Логические операторы

К сожалению в ТЕС Скрипте не существует логических операторов (И, ИЛИ, НЕ, исключающее ИЛИ и т.д.), поэтому Вам придётся создавать их самим, используя условные конструкции:

Вместо И:

if ( переменная1 AND переменная2 ); не существует
            [делать что-то]
endif

Вам придётся использовать:

If ( переменная1 )
            If ( переменная2 )
                        [делать что-то]
            endif
endif

А вместо ИЛИ:

if ( переменная1 OR переменная2 ); не существует
            [делать что-то]
endif

Следующий вариант:

If ( переменная1 )
            [делать что-то одно]
elseif ( переменная2 )
            [делать что-то другое]
endif