TESAll.Ru
OBSE В МАССЫ
YourBunnyWrote
2011
ЧАСТЬ 2
СОДЕРЖАНИЕ
4. Глава 4. ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ
4.1. Что такое функция?
4.2. Пользовательские функции
4.3. Обработчики событий
5. Глава 5. СПЕЦИАЛЬНЫЕ ФУНКЦИИ OBSE
5.1. Функции для работы с массивами
Глава 4. ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ
Принципиально новое понятие в рамках скриптового языка Oblivion-а.
Что такое функция?
В программировании, функция – это именуемая часть программы, которая непосредственно не выполняется, но доступна из любой части программы, в том числе и для самой себя, которая может инициировать её выполнения посредствам обращения (вызова) с передачи ей начальных параметров (аргументов функции). По окончании выполнения функция возвращает результат (значение функции) вызвавшей её части программы.
Функция, которая не предусматривает возвращение результатов (не имеет значения), называется процедурой.
Вызов функцией самой себя называется рекурсией.
Функция, которая в качестве аргументов принимает значение другой функции непосредственно, называется суперпозицией. Не столь важное понятие в программировании, но привожу для общего развития.
Функция – очень удобный механизм разделения типичных, востребованных программных действий, делающий их доступным любому скрипту вашего плагина.
Пользовательские функции
Для того чтобы создать функцию, следует создать новый скрипт. Имя скрипта – это имя функции. На то, что этот скрипт есть функцией, указывает ключевое слово Function, которое используется в качестве типа блока с ключевым словом Begin. В скрипте функции может находиться только один блок Begin – End и только типа Function.
Аргументы функции перечисляются в системных скобках, за ключевым словом Function, через запятую. Функция в OBSE может иметь до десяти аргументов, или не иметь их вовсе. Все аргументы функции – переменные, объявляются как в обычном скрипте.
Значение функции определяется ключевым словом SetFunctionValue. Значением функции может служить как константа, так и переменная. Возврат из функции, имеющей или не имеющей значения, выполняется ключевым словом Return. Возврат из функции означает прекращение её выполнения. Помните, нельзя использовать Return в циклах!
| 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. | ScriptName FunctionName ; Имя функции type arg1 ; Первый аргумент функции type arg2 ; Второй аргумент функции … type arg10 ; Десятый аргумент функции type RetVal ; Значение функции Begin Function {arg1, arg2, …, arg10} ; … SetFunctionValue RetVal ; Определение значения функции Return ; Возврат из функции End |
Для примера составим функцию, суммирующую два числа.
| 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. | ScriptName Sum float Num1 ; Первое число float Num2 ; Второе число Begin Function {Num1, Num2} Let Num1 += Num2 ; Находим сумму чисел SetFunctionValue Num1 ; Задаём возвращаемое значение Return ; Возвращаем результат End |
Для вызова пользовательской функции нужно использовать ключевое слово Call.
| 1. 2. 3. 4. 5. 6. 7. 8. | ScriptName SomeScript float Var Begin GameMode Let Var := Call Sum 10 20 ; Var == 30 End |
Как я уже говорил ранее, не все функции обязательно должны иметь аргументы и/или возвращать значение. Давайте составим пример такой функции, она будет просто добавлять сто Септимов в карман игрока.
| 1. 2. 3. 4. 5. | ScriptName ProcedureExample Begin Function {} Player.AddItem Gold001 100 End |
В OBSE существует функция, которая позволяет определить скрипт (функция возвращает ссылку на него), из которого произошёл вызов функции, она называется GetCallingScript.
| 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. | ScriptName GetCallingScriptExample Begin Function {} If GetCallingScript == MyQuestScript SetFunctionValue 1 Else SetFunctionValue 0 EndIf Return End |
Функция GetCallingScript ничего не возвращает, если вызов функции произошёл без помощи оператора Call или функция была использована как обработчик события.
Обработчики событий
Понятие заимствованное из .NET языков программирования. Обработчики событий являются функциями, которые автоматически вызываются программой, если происходит определённое событие. Все события в OBSE предопределены, с большинством из них вы должны быть уже знакомы, если ранее вам уже приходилось писать скрипты на родном скриптовом языке Oblivion-а:
|
Имя события |
Аргумент события : Тип |
Описание |
|
|
Первый аргумент |
Второй аргумент |
||
|
OnHit |
Цель:ref |
Атакующий:ref |
Происходит при нанесении атакующим урона цели |
|
OnHitWith |
Цель:ref |
Оружие:ref |
Происходит при нанесении оружием урона цели |
|
OnMagicEffectHit |
Цель:ref |
Магический_эффект:string (четырёхсимвольный код) |
Происходит при наложении магического эффекта на цель |
|
OnActorEquip |
Цель:ref |
Предмет:form |
Происходит при надевании предмета целью |
|
OnDeath |
Цель:ref |
Убийца:form |
Происходит при смерти цели |
|
OnMurder |
Цель:ref |
Убийца:form |
Происходит при убийстве цели убийцей |
|
OnKnockout |
Цель:ref |
|
Происходит при нокаутировании цели |
|
OnActorUnequip |
Цель:ref |
Предмет:form |
Происходит при снятии предмета целью |
|
OnAlarm Trespass |
Заметивший:ref |
Нарушитель:ref |
Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил взлом. |
|
OnAlarm Steal |
Заметивший:ref |
Нарушитель:ref |
Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил кражу. |
|
OnAlarm Attack |
Заметивший:ref |
Нарушитель:ref |
Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил нападение. |
|
OnAlarm Pickpocket |
Заметивший:ref |
Нарушитель:ref |
Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил карманную кражу. |
|
OnAlarm Murder |
Заметивший:ref |
Нарушитель:ref |
Происходит, когда заметивший актёр поднимает тревогу, если нарушитель совершил убийство. |
|
OnPackageChange |
Цель:ref |
Пакет:form |
Происходит при смене целью AI пакета |
|
OnPackageStart |
Цель:ref |
Пакет:form |
Происходит при старте целью AI пакета |
|
OnPackageDone |
Цель:ref |
Пакет:form |
Происходит при завершении целью AI пакета |
|
OnStartCombat |
Цель:ref |
Опонент:ref |
Происходит, когда цель нападает на оппонента |
|
OnActivate |
Активатор:ref |
Цель:ref |
Происходит, когда цель активирует активатор |
|
OnVampireFeed |
NONE |
|
Происходит, когда вампир перестаёт питаться |
|
OnSkillUp |
Код_навыка:int |
|
Происходит при повышении навыка игрока |
|
OnScriptedSkillUp |
skillActorValueCode:int amount:int |
|
Происходит перед изменением навыка игрока скриптовой командой |
|
OnDrinkPotion |
Цель:ref |
Зелье:form |
Происходит, когда цель принимает зелье |
|
OnEatIngredient |
Цель:ref |
Ингридиент:form |
Происходит, когда цель съедает ингредиент |
|
OnActorDrop |
Цель:ref |
Предмет:ref |
Происходит, когда цель выбрасывает/роняет предмет |
|
OnSpellCast |
Цель:ref |
Заклинание:form |
Происходит, когда цель произносит заклинание |
|
OnScrollCast |
Цель:ref |
свиток:form |
Происходит, когда цель читает заклинание со свитка |
|
OnFallImpact |
Цель:ref |
|
Происходит, когда цель упадёт с опасной высоты, перед тем, как получить повреждение |
|
OnMapMarkerAdd |
Маркер:ref |
|
Происходит при добавлении маркера на карту игрока |
|
OnHealthDamage |
Величина_повреждения:float |
Атакующий:ref |
Происходит перед тем, как актёр получит повреждение. Если актёр свалится с высоты, то аргумент «Атакующий» будет иметь нулевое значение. Для определения актёра получившего повреждение стоит использовать функцию GetSelf. |
|
OnCreateSpell |
Заклинание:ref |
|
Происходит, когда игрок создаёт новое заклинание |
|
OnCreatePotion |
Зелье:ref |
Уникальное_ли:int |
Происходит, когда игрок приготовит новое зелье. Второй аргумент будет равен 1, если игрок впервые приготовил такое зелье, иначе он будет равен 0. |
|
OnEnchant |
Предмет:ref |
|
Происходит, когда игрок зачаровывает предмет. |
|
OnAttack |
Цель:ref |
|
Происходит, когда цель начинает проигрывать анимацию атаки или наложения заклинания. |
|
OnBowAttack |
Цель:ref |
|
Происходит, когда цель начинает проигрывать анимацию стрельбы из лука. |
|
OnRelease |
Цель:ref |
|
Происходит, когда цель заканчивает проигрывать анимацию атаки, стрельбы или наложения заклятья. |
|
OnBlock |
Цель:ref |
|
Происходит, когда цель начинает проигрывать анимацию блокирования ударов. |
|
OnRecoil |
Цель:ref |
|
Происходит, когда цель начинает проигрывать анимацию получения отдачи. |
|
OnStagger |
Цель:ref |
|
Происходит, когда цель начинает проигрывать анимацию получения урона. |
|
OnDodge |
Цель:ref |
|
Происходит, когда цель начинает проигрывать анимацию уклонения от атаки. |
|
LoadGame |
Имя_файла:string |
|
Происходит при загрузке игры |
|
SaveGame |
Имя_файла:string |
|
Происходит при сохранении игры |
|
PostLoadGame |
Игра_загружена_удачно:bool |
|
Происходит после загрузки игры. Передаёт функции-обработчику события 1, если игра была загружена удачно, 0 - если нет |
|
ExitGame |
NONE |
|
Происходит при выходе из игры |
|
ExitToMainMenu |
NONE |
|
Происходит при выходе в главное меню |
|
QQQ |
NONE |
|
Происходит при выходе из игры посредствам вызова консольной команды QQQ |
|
OnNewGame |
NONE |
|
Происходит при старте новой игры |
Для того, чтобы задать обработчик события, существует функция SetEventHandler, её синтаксис таков:
| 1. | (success:bool) SetEventHandler eventID:string functionScript:ref filter1:pair filter2:pair |
Где, eventID – имя события, одно из тех, которые наведены в таблице; functionScript – имя функция, которая будет использована для обработки события;
filter1 – фильтр первого аргумента функции-обработчика;
filter2 – фильтр второго аргумента функции-обработчика.
Функция SetEventHandler возвращает единицу, если удалось назначить указанную функцию обработчиком события, или 0 – если нет.
Аргументы filter1 и filter2 применяются для фильтрации аргументов, передаваемых функции-обработчику события. Если их не задавать, то обработчику события будут передаваться все аргументы, инициируемые определённым событием.
Например, давайте составим функцию, которая будет использована для обработки события OnHit:
| 1. 2. 3. 4. 5. 6. 7. 8. | ScriptName OnHitHandlerExample ref Target ref Attacker Begin Function {Target, Attacker} Print Attacker.GetName + " attacked " + Target.GetName End |
И инициализируем её как обработчик события:
| 1. 2. 3. 4. 5. | ScriptName OnHitHandlerQuestScript Begin GameMode SetEventHandler "OnHit" OnHitHandlerExample End |
В таком случае, в ячейке, где разворачиваются игровые действия, на данный момент, любое событие OnHit инициализирует выполнение функции OnHitHandlerExample. Т.е. если любой NPC или Creature нанесёт урон любому другому NPC или Creature в ячейке, в которой находится игрок, будет вызвана функция OnHitHandlerExample, которой будут переданы ссылки атакуемого и атакующего.
Если мы хотим, допустим, чтобы это событие выполнялось только когда атакуют игрока, следует установить фильтр первому аргументу, согласно описанию события OnHit.
| 1. 2. 3. 4. 5. | ScriptName OnHitHandlerQuestScript Begin GameMode SetEventHandler "OnHit" OnHitHandlerExample "ref"::Player.GetSelf End |
Оператор :: создаёт пару “Ключ”::”Значение”. Ключ должен иметь значение типа соответствующего аргумента, согласно перечню событий.
Независимо от того, что первый аргумент функции-обработчика теперь может принимать только одно значение, и мы заведомо знаем об этом, функция-обработчик всё равно должна иметь два аргумента.
Если мы хотим избавиться от обработчика события, следует использовать функцию RemoveEventHandler. Её синтаксис аналогичен функции SetEventHandler.
| 1. 2. 3. 4. 5. | ScriptName OnHitHandlerQuestScript Begin GameMode RemoveEventHandler "OnHit" OnHitHandlerExample End |
Если у нас есть несколько обработчиков события OnHit, то вызов функции RemoveEventHandler без фильтров приведёт к удалению их всех.
| 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. | ScriptName OnHitHandlerQuestScript Begin GameMode SetEventHandler "OnHit" OnHitHandlerExample SetEventHandler "OnHit" OnHitHandlerExample "ref"::Player.GetSelf ; ---------------------------------------------------------------------- RemoveEventHandler "OnHit" OnHitHandlerExample ; Удалит все события OnHit ; ---------------------------------------------------------------------- RemoveEventHandler "OnHit" OnHitHandlerExample "ref"::Player.GetSelf ; Удалит события только с соответствующим фильтром End |
С помощью функции GetCurrentEventName, вызванной из функции-обработчика события, можно узнать имя текущего события. Это полезно, если одна функция используется как обработчик нескольких событий.
| 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. | ScriptName MultiEventHandlerFunction ref Arg1 ref Arg2 Begin Function {Arg1, Arg2} If Eval (GetCurrentEventName == "OnHit") Print Arg2.GetName + " атаковал " + Arg1.GetName ElseIf Eval (GetCurrentEventName == "OnActorEquip") Print "Игрок " + Arg1.GetName + " одел " + Arg2.GetName EndIf End |
Глава 5. СПЕЦИАЛЬНЫЕ ФУНКЦИИ OBSE
Функции для работы с массивами
|
ar_Construct – создаёт массив. Синтаксис: (array_var) ar_Construct arrayType:string Где, arrayType – тип массива: Array – индексный массив Map – вещественный массив StringMap – ассоциативный массив |
||
|
ar_Size – возвращает количество элементов массива. Синтаксис: (size:int) ar_Size array:array_var Где, array – массив, размер которого стоит определить. |
||
|
ar_Dump – отладочная функция. Выводит в консоль все пары “Ключ”:”Значение” для выбранного массива. Синтаксис: (nothing) ar_Dump array:array_var Где, array – массив.
|
||
|
ar_DumpID – отладочная функция. Делает то же самое, что и ar_Dump, за исключением того, что принимает ID массива вместо array_var . (nothing) ar_Dump array:array_var Где, array – массив.
|
||
|
ar_Erase – удаляет элемент массива, диапазон элементов или все элементы массива. Возвращает количество удалённых элементов. (numRemoved:int) ar_Erase target:array index:arrayIndex (numRemoved:int) ar_Erase target:array range:slice Где, target – массив. index – индекс элемента массива, который стоит удалить. Если этот аргумент пропущен, то будут удалены все элементы массива. Индекс следующих за удалённым элементов будет смещён на единицу. range – стартовый индекс диапазона элементов, которые нужно удалить. slice – конечный индекс диапазона элементов, которые нужно удалить.
|
ar_Find – ищет значение в массиве. Возвращает ключ первого попавшегося элемента массива, значение которого соответствует искомому. Если искомому значению не соответствует ни один элемент массива, то возвращает пустую строку, если поиск происходил в ассоциативном массиве, или число -99999.0 – если в индексном или вещественном.
(key:stringOrNumber) ar_Find value:stringOrNumberOrForm arrayToSearch:array inRange:range
Где, value – искомое значение. Может быть строкой, числом или формой.
arrayToSearch – массив, в котором будет происходить поиск.
inRange – диапазон элементов массива, среди которых будет происходить поиск. Если не указан, то поиск будет происходить среди всех элементов массива.
ar_Sort – сортирует значения элементов массивов по возрастанию или по убыванию. Возвращает новый, отсортированный массив, связь «Ключ»::»Значение» не сохраняется. Внимание, тип элементов массива, который сортируется, должен быть одинаковым (строка, число, или объект), в противном случае функция возвращает пустой массив. Строки сортируются по алфавиту и без учёта регистра, номера - в номерном порядке, объекты - по ID.
(sortedArray:Array) ar_Sort toSort:array sortDescending:bool
Где, toSort – массив, который будет отсортирован.
sortDescending – сортировать в обратном порядке. 1 – ДА, 0 – НЕТ. Указывать этот параметр не обязательно, по умолчанию сортировка происходит в прямом порядке.
ar_SortAlpha – сортирует значения элементов массивов по алфавиту, по возрастанию или по убыванию. Возвращает новый, отсортированный массив, связь «Ключ»::»Значение» не сохраняется. В отличие от функции ar_Sort, не требует, чтобы значения элементов массива имели один тип. Если в массиве содержатся и численные и строковые значения, то численные значения преобразуются в строки, формы сортируются по имени, если такое имеется, иначе - по ID.
(sortedArray:Array) ar_SortAlpha toSort:array sortDescending:bool
Где, toSort – массив, который будет отсортирован.
sortDescending – сортировать в обратном порядке. 1 – ДА, 0 – НЕТ. Указывать этот параметр не обязательно, по умолчанию сортировка происходит в прямом порядке.
ar_Copy – создаёт точную копию массива. Если копируемый массив содержит другие массивы, то копия будет содержать указатели на те самые массивы.
(copy:array) ar_Copy src:array
Где, src – массив, который будет скопирован.
ar_DeepCopy – то же самое, что и ar_Copy, за исключением того, что делает копии всех вложенных массивов.
(copy:array) ar_DeepCopy src:array
Где, src – массив, который будет скопирован.
ar_First – возвращает ключ первого элемента массива.
(key:arrayKey) ar_First src:array
Где, src – массив.
ar_Last – возвращает ключ последнего элемента массива.
(key:arrayKey) ar_Last src:array
Где, src – массив.
ar_Next – возвращает ключ следующего элемента массива.
(key:arrayKey) ar_Next src:array precedingKey:arrayKey
Где, src – массив.
precedingKey – ключ текущего элемента массива.
ar_Prev – возвращает ключ предыдущего элемента массива.
(key:arrayKey) ar_Prev src:array prevKey:arrayKey
Где, src – массив.
precedingKey – ключ текущего элемента массива.
ar_BadNumericIndex – возвращает неправильный ключ индексного или вещественного массива. Может быть использована для проверки значения функций, возвращающих ключ индексного или вещественного массивов.
(badKey:int) ar_BadNumericIndex
ar_BadStringIndex – то же самое, что и ar_BadNumericIndex для ассоциативных массивов.
(badKey:string) ar_BadStringIndex
ar_Keys – возвращает индексный массив, содержащий ключи элементов заданного массва.
(keys:Array) ar_Keys src:array
Где, src – массив.
ar_HasKey – возвращает 1, если заданный массив имеет элемент с заданным ключом, иначе возвращает 0.
(hasKey:bool) ar_HasKey src:array key:arrayKey
Где, src – массив.
key – ключ.
ar_Null – возвращает пустой массив. Может быть использована для проверки значения функций возвращающих массивы, или для разрыва связи между элементом одного массива и другим массивом.
(badKey:int) ar_BadNumericIndex
ar_List – возвращает индексный массив из последовательности аргументов. Может принимать до двадцати аргументов произвольного типа. Рекомендуется разделять аргументы через запятые.
(list:Array) ar_List element0:multi element1:multi ... element19:multi
ar_Resize – изменяет размер указанного индексного массива. Если новый размер меньше текущего размера массива, то элементы с превышающими его индексами будут отброшены. Если новый размер, наоборот - больше, то новые элементы будут добавлены в конец массива. По умолчанию они имеют значение 0, но могут принимать и любое другое значение, определяемое необязательным параметром функции paddingValue. Возвращает единицу, если удалось изменить размер массива, ноль – если нет.
(bResized:bool) ar_Resize array:Array newSize:int paddingValue:multi
Где, array – массив.
newSize – новый размер массива.
paddingValue – значение, которое будет использовано для новых элементов массива.
ar_Insert – добавляет один новый элемент с указанным индексом в указанный индексный массив. При этом существующие элементы будут сдвинуты на позицию вверх. Индекс нового элемента не может превышать текущий размер массива. Возвращает единицу, если удалось добавить новый элемент в массив, ноль – если нет.
(bInserted:bool) ar_Insert array:Array index:int valueToInsert:multi
Где, array – массив.
index – индекс нового элемента.
valueToInsert – значение нового элемента.
ar_InsertRange – добавляет диапазон элементов в указанный индексный массив начиная с указанного индекса. При этом существующие элементы будут сдвинуты на соответствующее количество позиций вверх. Индекс нового элемента не может превышать текущий размер массива. Возвращает единицу, если удалось добавить диапазон элементов в массив, ноль – если нет.
(bInserted:bool) ar_Insert target:Array index:int rangeToInsert:Array
Где, target – массив.
index – индекс первого элемента диапазона в целевом массиве.
rangeToInsert – индексный массив элементов, которые будут добавлены в целевой массив.
ar_Range – возвращает индексный массив, состоящий из последовательности целых чисел, от начального до конечного числа, с заданным шагом.
(range:Array) ar_Range start:int end:int step:int
Где, start – стартовое число.
end – конечное число.
step – величина шага.
| 1. 2. 3. 4. | Let Arr := ar_Range 5 10 2 ; Arr[0] == 5 ; Arr[1] == 7 ; Arr[2] == 9 |
ar_Map – возвращает вещественный или ассоциативный массив, состоящий из аргументов функции. Аргументы «Ключ»::»Значение», которых может быть до двадцати.
(Map/StringMap) ar_Map key-value pair: key-value pair: key-value pair: entry_1:pair
| 1. 2. 3. | Let Arr := ar_Map "Name"::"Alex" "Age"::20 ; Arr["Name"] == "Alex" ; Arr["Age"] == 20 |
ar_Append – добавляет новый элемент в конец массива.
(nothing) ar_Append array: toInsert:
Где, array – массив.
toInsert – значение.
Вернутся к части 1.