Scripting overview/ru

From Dragon Age Toolset Wiki
< Scripting overview
Revision as of 00:46, 24 June 2013 by Kelamor (Talk | contribs) (Writing scripts: Предварительно)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Обзор языка DAScript
Начало / Русская DA Builder Wiki / Поделиться ВКонтакте
Скрипты
все статьи категории
описание функций

Введение

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

Детальная документация по языку DAScript вы сможете найти в файле "dascript.chm", находящемся в папке "Dragon Age\packages\core".

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

  • Запуск и обработка событий plot-файлов
  • Программирование диалогов
  • Управление существами и партийцами AI (en)
  • Программирование способностей

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

  • Событие посылается в скрипт, ассоциированный с Plot-файлом, когда его флаг считывается или устанавливается.
  • Событие посылается в скрипт, ассоциированный с локацией, когда в локации умирает команда существ, когда в локацию входит игрок.
  • Событие посылается в скрипт, ассоциированный с модулем, во время генерации персонажа.
  • Событие посылается существу, когда с ним что-то происходит (например - бьют).

Со скриптами в DA связаны несколько типов файлов:

  • NSS - исходный файл скрипта (можно открыть блокнотом)
  • NCS - компилированный файл скрипта
  • NDB - файл с информацией об отладке (позволяет проследить выполнение скрипта)

В DA также существуют клиентские скрипты, с помощью которых происходит автоматическое тестирование игры. Смотрите Клиентские скрипты (en) для получения более подробной информации.

Встроенный редактор

Скрипты пишутся во встроенном в тулсет редакторе (en).

После создания можно использовать скрипт двумя способами:

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

Встроенный редактор поддерживает следующие возможности:

  • Отмена и повтор.
  • Поиск и замена.
  • Закладки (View -> Other Windows -> Bookmarks).
  • Окно быстрого доступа к функциям, переменным, константам и списку шаблонов с возможностью фильтрации (находится в правой части редактора). Шаблоны содержат наиболее распространённые в игре скрипты. Вы можете добавить свой собственный шаблон, поместив текстовый файл в папку "Dragon Age\Toolset\scripttemplates".
  • Автозавершение типовых функций и переменных.
  • Подсветка синтаксиса.
  • Автоматический отступ.
  • Подсветка (выделение) парных скобок.
  • Проверка наличия ошибок, в том числе синтаксических, ошибки в переменных, константах (кнопка Compile script).
  • Быстрый переход к определению функции, переменной, константы (в контекстном меню пункт Jump to definition). При переходе к определению функции слева открывается окно помощи с описанием, при переходе к определению константы или переменной открывается скрипт с её определением.

Написание скриптов

В общих случаях скрипт должен иметь основную функцию:

void main()
{
}

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

Скрипты, ассоциированные с репликой диалога (когда реплика вызывает исполнение скрипта) должны иметь следующую конструкцию:

int StartingConditional()
{
    return 1;
}

Скрипты, содержащие отдельные функции или список констант (пишу по памяти):

Функции

//Объявления функций
void Function (parametres);
 
//Функции
void Function (parametres)
{
 
}

Константы

//Список констант
const DARKSPAWN_TEAM  = 1021213;
const FRIEND_TEAM  = 1021214;

Подключение файлов

Подключение других скриптов и plot-файлов происходит при использовании управляющей конструкции "#include".

//Скрипты
#include "rules_h"
#include "plt_plotfile" // Префикс "plt_" перед именем plot-файла обязателен
 
void main()
{
    DoSomethingOrOther();
}

Обратите внимание:

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

Подключить таким образом можно любое количество файлов.

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

Операторы

DAScript поддерживает следующие операторы:

Математические операторы

Operator Name Example
Prefix Increment
while ( ++a < 10) { }
Postfix Increment
 for (i = 0; i < 10; i++) { }
Assignment by addition
a += b;
Subtraction (difference)
x = a - b;
Addition (sum)
x = a + b;
Prefix decrement
while (--a > 10) { }
Postfix decrement
while (a-- > 10) { }
Assignment by subtraction
a -= b;
Multiplication (product)
x = a * b;
Division (quotient)
x = a / b;
Modulo (remainder)
if (a % b == 1) { }

Операторы сравнения

Operator Name Example
Less than
if (a < b) { }
Less than or equal to
if (a <= b) { }
Greater than
if (a > b) { }
Greater than or equal to
if (a >= b) { }
Not Equal to
if (a != b) { }
Equal to
if (a == b) { }

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

Operator Name Example
Logical negation (NOT)
if (!a) { }
Logical AND
if (a && b) { }
Logical OR
if (a || b) { }

Другие операторы

Operator Name Example
Basic assignment
a = b;
Function call
a();
Array subscript
array[0] = 1;
Member (on structures)
structure.member = 0;
Ternary conditional
return a < b ? c : d;

Types & Variable

The scripting language natively supports:

The server language has been expanded to support these engine defined structures:

  • event - events are signals that are sent to scripts by other scripts or by the world engine.
  • location
  • command - a command for a creature or object to do something. Commands are constructed using functions that return them, and then are added to a target's command queue with the AddCommand function.
  • effect
  • itemproperty
  • player

All of these types are always passed by value, which means a new copy is made whenever they are passed into a function or copied to another variable.

This means that most functions that are supposed to modify a structure in some way need to return the modified one:

void main()
{
    effect e1 = Effect(100);
    effect e2 = SetEffectType(e1, 101); // e1 != e2
}

Structures

Users can define their own structures using the struct keyword:

// user-defined type
struct quaternion
{
    float w, x, y, z;
};
 
// constructor
struct quaternion Quaternion(float fW, float fX, float fY, float fZ)
{
    struct quaternion q;
 
    q.w = fW;
    q.x = fX;
    q.y = fY;
    q.z = fZ;
 
    return q;
}
 
void main()
{
    struct quaternion q = Quaternion(0.0, 0.0, 0.0, 0.0);
}

Arrays

Variables can be declared as arrays for any type except user-defined structs. Designers can create their own arrays of any major data type (int, string, object). Many functions will also return arrays (for example, creatures in an area will be returned as an array, and the action queue will be returned as an array).

These are different from C-style arrays in that they can be resized like STL vectors, and their notation is slightly different.

Arrays also behave differently from other objects in the scripting language because they are passed by reference. If an array is passed into a function and modified:

void main()
{
    int[] i;                 // new array of integers with a size of zero 
    i[0] = 5;                // value of array position 0 is now 5
    i[1] = -1;               // value of array position 1 is now -1
 
    int[] j = i;             // i and j point to the same array
    j[1] = 12;               // value of array position 1 for both i and j is now 12!
 
    SortArrayDescending(i);  // i and j are both sorted now, this function has no return value
}

GetArraySize returns the size of an array.

Local Variables

In Neverwinter Nights, variables for various objects could be created and set with functions such as SetLocalInt(). Dragon Age does not have analogous functions. Instead, all of the variables that a given object is able to have values assigned to must be defined ahead of time in a 2DA. This more restrictive approach is intended to improve performance and reduce the opportunity for errors (for example, making a typo in the name of a variable and losing track of it as a result).

Functions

There are two ways to discover a function and what it does.

If you type in the name of a function that's been defined and then an opening bracket, a tooltip will pop up showing the function's parameter types and return type.

Alternately, if you have the help window open (View -> Other Windows -> Help Window), then whenever you select a function in the function browser a help page describing the function will be displayed.

Passing parameters to scripts

To pass parameters to scripts they must be called with the 'runscript' command. This can be useful for writing debug scripts or changing actions based on input. To accept parameters simply add this line to your script:

string sParams = GetLocalString(GetModule(),"RUNSCRIPT_VAR");

You can then type 'runscript scriptname parameter1 parameter2 ... paramaterN' to pass parameters.

Some examples:

// Debug script: heals the object with the given tag. If tag is invalid, nothing happens
void main()
{
 
    string sTag = GetLocalString(GetModule(),"RUNSCRIPT_VAR");    
    object oCreature = GetObjectByTag(sTag);
    effect   eHeal = EffectHeal(25.0f)
    //ApplyEffect...
}
// Debug script: applies the visual effect passed in as parameter to the player
void main()
{
 
    string sEffect = GetLocalString(GetModule(),"RUNSCRIPT_VAR");    
    int    nEffect = StringToInt(sEffect);
    effect eVfx = EffectVisualEffect(nEffect);
    //ApplyEffect...
}

Error messages and logging

See Script error for details of how to correct errors in scripts.

To enable script logging, edit or create <DragonAgeInstallDirectory>\bin_ship\ECLog.ini and set Script=1 in the [LogTypes] section.

The PrintToLog function prints messages to the log file once logging is enabled.

Timing

Commands, delayed events and object destruction all take place after the current script is finished running. Plot flags set in script are set in-line but the triggered plot script runs before the flag is actually set (this is clarified a bit in the plot script template).

Given that ExecuteScript is deprecated, HandleEvent should be used when you want the script to run in-line and DelayEvent should be used when you want to delay execution.

To delay execution when dealing with creatures, custom AI and (safe) command complete are nice tools. DelayEvent should be used whenever you know how long you want to wait before the event fires. (It can also be used in quite small time increments to give the illusion of smoothly sliding placeables with SetPosition or interpolate between two different atmosphere/lighting settings, but the overhead of this is noticeable if overused).


Язык: English  • русский