Форум » TES V: Skyrim » Мастерская » Уроки по скриптованию и примеры скриптов на языке Papyrus (Уроки по скриптованию на языке Papyrus для TES5 Skyrim)
Уроки по скриптованию и примеры скриптов на языке Papyrus
Изменение репутации для пользователя sansuli
sansuliOffline
Сообщение №1
написано: 17 апреля 2015, 15:56
| Отредактировано: sansuli - 17 апреля 2015, 18:03
Урок 11. Создание функции. Создание "сборника" функций. Создание функции с аргументами. Создание функции для обработки информации. Доступ к функции из другого скрипта.
Урок 12. Массивы. Массивы - переменные-хранилища.
Урок 13. FormList и GlobalVariable. FormList - как вариант массивов. GlobalVariable - глобальные переменные.
Урок 14. Работа с Message. Польза Message. Использование их со скриптом.
Урок 1. Основной принцип работы скрипта.
Основной принцип работы скрипта.
Все скрипты папируса состоят из функций и событий.
Что такое функция? Функция - это команда, которая что, то делает в игре, с игрой и т.п. Функции - это основной рабочий инструмент.
Что такое событие? Событие - это команда, которая нужна для работы функций. Функция сама по себе запуститься не может, вот для этого и нужны события.
Обычный простой скрипт выглядит вот так (образный пример): ________________ | Событие1 | | (Функция2) | | (Функция1) | | (Функция3) | |_______________|
Скрипт толкуется так: вовремя События1 будут выполнены сначала Функция2, после Функция1 и в конце Функция3.
Что из этого примера видно: 1.Чтобы функция работала, она должна быть внутри события. 2.Внутри события может быть любое количество функций. 3.Функции внутри события работают по порядку следования (сверху вниз). 4.Время между выполнением функций почти мгновенно, то есть все три функции будут выполнены по порядку в долю секунды.
Урок 2. Создание и сохранение скриптов в СК.
Как создать.
Для начала вы должны уже уметь хоть чуть-чуть пользоваться Creation Kitом. У многих объектов в СК при редактировании есть окно под названием Papyrus Script (у магических эффектов, актеров, предметов и др.). В этом окне указаны скрипты, привязанные к объекту. Если кликнуть по пустому окну правой клавишей мыши, то вылезет контекстное меню с единственной доступной строкой Add Script, нажимаем на него. Появляется окно со всеми существующими скриптами, мы можем взять любой из них и нажав ОК "повесить" его на наш объект, но нам нужно создать новый, для этого мы выбираем строчку [New Script], откроется маленькое окошечко где в Name пишем имя нашего скрипта, остальное не трогаем (об этом ниже). Жмем Ок. Все мы видим что у нас в окне появился наш скрипт, кликаем на него правой клавишей и выбираем строчку Edit Source. Появится окно редактирования скрипта. В нем вы должны увидеть только одну строчку:
Scriptname Имя_скрипта extends Form
Далее подробнее о ней.Скрипт. Первая строка.
Scriptname Имя_скрипта extends Form
"Scriptname" - обязательная строка указывающая на имя скрипта. "Имя_скрипта" - имя заданное вами при его создании в строчке Name. "extends" - слово означает что наш скрипт расширяет другой скрипт (пока о расширениях скрипта ломать голову не стоит). "Form" - это тот самый скрипт, который мы расширяем. Его мы могли задать при создании скрипта в строчке Extends, но СК автоматически вставляет туда слово, которое зависит от объекта на котором был создан скрипт, так что менять его смысла нет. Вместо этого слова могут быть другие слова, к примеру если вы создали скрипт на заклинании, то там будет "activemagiceffect", если на оружии, актере или другом предмете, то будет "ObjectReference".
С этой строчкой разобрались. После этой строки пишется наш скрипт (чтобы писать скрипты, вы должны ознакомится со следующими уроками).Как сохранить.
Допустим вы записали скрипт и хотите его скомпилировать, для этого надо просто нажать на кнопку File > Save или нажать на комбинацию клавиш Ctrl + S. После произойдет компиляция и если скрипт написан правильно, то под окном редактирования появится мини окошко с надписью Compilation succeeded. Все теперь закрываете окно скрипта и сохраняете ваш плагин. Если при компиляции вылезет ошибка, то что-то вы сделали не правильно. О возможных ошибках расскажу позже.
Урок 3. Функции.
Как работают функции.
Каждая существующая функция в Papyrus что-то делает (убивает, толкает, восстанавливает, заставляет что то делать и т.п.), а что-то делают они с объектами. Объекты - это все составляющие игры (НПС, квесты, оружия, двери, деревья, заклинания и др.). Функции будут творить что-то именно с объектами. Так же у функции есть свои аргументы. Аргументы - это данные для функции, которые используются в действии над объектами.Построение функций в скрипте.
Пример:
Объект.Функция(Аргументы функции)
"Объект" - это тот объект в игре на который будет работать наша функция. Объект всегда пишется слева от самой функции и разделен от нее точкой. Объектом может быть все что угодно (НПС, квест, дверь, меч и др.). "Функция" - наша функция, которая должна сделать что-то с нашим объектом. "Аргументы функции" (то что в круглых скобках) - любая функция должна иметь скобки, ну а содержание скобок зависит от самой функции. Некоторые функции не нуждаются в введении дополнительных данных (аргументов), а другие напротив обязательно нуждаются в введении аргументов. Смотрим следующий пример:
Функция добавления заклинания (AddSpell) обязательно должен иметь в скобке добавляемое заклинание, в противном случае выйдет ошибка при компиляции, мол не указаны аргументы функции. Но есть функции в которых скобка может быть как пустой, так и с введенными данными. Почему? Просто эти функции по умолчанию уже имеют данные в скобках и если оставить скобки пустыми, то будут работать данные по умолчанию. Ну а если вы впишите туда данные, то функция будет работать с вашими введенными данными. Смотрим пример:
Объект.Kill()
Примечание: функция Kill() убивает свой объект, работает на объекты типа Actor (Люди, Волки, Драугры, Драконы и т.п.). Если у этой функции в скобках будет пусто, то наш объект просто умрет сам по себе. Ну а если мы впишем туда данные:
Объект.Kill(Объект2)
Примечание: для этой функции в скобках могут быть только "живые" объекты. И еще вспомним то что мы упоминали раннее "содержание скобок зависит от самой функции". Теперь наш объект не просто умрет сам, а его убийцей станет объект2. Помните, что разные функции нуждаются в разных аргументах, которыми могут быть числа, текст или определенный тип объекта.Внутриигровые функции (native).
Внутриигровые функции - это функции уже заложенные разработчиками в движок игры, такие функции отмечены словом "native" в конце строки функции. Остальные же функции не отмеченные словом "native", являются расширенными функциями, которые разработчики или мододелы создали из функций native, то есть из существующих функций (о создании функций речь пойдет позже).Виды функций по глобальности.
Функции в игре в целом можно разделить на два вида: частные и глобальные.
Частные функции - это большая часть внутриигровых функций, которые работают только с определенным объектом, как показано выше. К примеру функция убийства работает только на живые объекты (НПС, волки, драугры и др.) и для него нужно указать кого именно убить. Пример:
Алдуин.Kill()
Убить Алдуина (Алдуин должен быть объектом типа Actor)Глобальные функции - обозначаются словом "global" в конце строки функции (у частных нет такого слова). Эти функции работают не с определенным объектом, а с игровыми настройками (настройки, погода и т.п.) и для них не указываются объекты. Пример:
Game.ForceThirdPerson()
Выставить вид камеры от третьего лица (естественно камеру игрока).
Урок 4. События.
События (Event).
Основной принцип функции мы знаем, теперь о событиях. Событие - это тоже некоторое подобие функции, но метод его действий совсем другой. Событие работает без объектов, то есть для работы им не нужны объекты (как функциям), а некоторые из событий сами выдают объекты в аргументах. Основное и единственное применение событий - это работа функций во время определенного события (во время начала эффекта, активации предмета и т.п.). Для примера, если в скрипте мы напишем просто функцию, то эта функция не заработает, игра просто не поймет когда надо запускать данную функцию. И чтобы функция заработала мы должны вписать его в событие. Как и функции события тоже уже заложены в движке игры, но в отличии от функций мы не сможем создать новое событие (повторюсь, о создании функций речь пойдет позже).Построение событий.
Пример:
Event НашеСобытие(Объекты события) EndEvent
"Event" - это объявление открытия события. "EndEvent" - это закрытие и их запись вместе с Event обязательна. "НашеСобытие" - тут должно быть одно из игровых событий (onEffectStart, onActivation и др.). "Объекты события" (в скобке) - это объекты данного события. У каждого события содержание скобок будет зависеть от самого события, то есть если там пусто, то там всегда должно быть пусто, если там два объекта типа Actor, то там всегда будет два объекта типа Actor. К примеру:
Event onEffectStart(Actor Target, Actor Caster) EndEvent
Примечание: имена объектов, в нашем случае это Target и Caster, мы можем изменять по своему усмотрению, но помните, что после изменения имени вызывать эти объекты вы будете по новому имени и имя желательно должно нести информацию о себе (у нас Target (перевод с анг. Цель) - это цель магического эффекта). Событие это работает при начале магического эффекта и имеет два объекта это Actor Цель эффекта и Actor Создатель эффекта.
И вот теперь самое главное, вписываем в строчки между строками Event и EndEvent нашу желаемую функцию.
Все теперь функция будет работать во время данного события.
Урок 5. Объекты и переменные.
Откуда брать объекты.
Мы сказали что функции работают на объектах, но откуда брать наши объекты?
1.Берем из аргументов событий. Как мы упоминали ранее, некоторые события выдают в аргументах объекты, с которыми могут работать функции. Давайте вспомним ранее показанное событие в прошлом уроке:
Event onEffectStart(Actor Target, Actor Caster) EndEvent
Обратите внимание на запись в скобке, видите, это событие нам выдаёт аж два объекта: цель заклинания и создателя заклинания (оба объекты типа Actor). Вот с этими самыми объектами могут работать функции. Давайте впишем в наше событие функцию:
Event onEffectStart(Actor Target, Actor Caster) Kill() EndEvent
Вот написали, но эта запись не верна, вспоминаем построение функции и исправляем:
Event onEffectStart(Actor Target, Actor Caster) Target.Kill() EndEvent
Все теперь все в порядке. Мы взяли объект из данных события, а именно цель заклинания Target и прописали на него функцию убийства. Теперь цель заклинания мгновенно умрет. Но это непорядок, что он просто умрет, давайте еще впишем в аргумент функции объект:
Event onEffectStart(Actor Target, Actor Caster) Target.Kill(Caster) EndEvent
Все теперь цель умрет и виноват будет в этом создатель заклинания Caster. Это был пример взятие объекта из аргумента функции.
2.Введение объекта из вне через свойства. Прежде чем мы ознакомимся с этим способом вызова объекта, вам нужно познакомиться с переменными. К описанию данного способа вернемся позже.Переменные - хранители информации.
Еще один немаловажный тип инструмента - переменные. Переменные способны хранить в себе различную информацию (числа, слова, актера и др.).
Существую простые переменные так называемые литералы, которые делятся на 4 вида: int - хранит в себе только целые числа. (57) float - способен хранить в себе не целые числа, числа с плавающей точкой. (5.45) string - хранит в себе символы, то есть текст. ("Алдуин мертв!") bool - способен хранить в себе только два значения True или False (Правда или Ложь).Другой вид переменных, более сложные переменные, которые хранят в себе различные объекты, с которыми могут работать функции. Их есть столько, сколько типов объектов есть в общем. Вызываются они названиями своих типов. Actor хранит в себе НПС Armor хранит все доспехи и одежду Quest хранит квест Spell хранит заклинание Sound - звук и т.д.Объявление переменной в скрипте.
Пример объявления простой переменной:
int Имя_переменной
int - это тип переменной, зависит от того что вы хотите хранить. Имя_переменной - имя для переменной вы придумаете сами.Пример объявления сложной переменной:
Actor Имя_переменной Weapon Имя_переменной Spell Имя_переменной
Описание аналогично предыдущей.Передача на хранение.
Существует несколько способов передачи информации нашей переменной: 1.Пропишем сами. 2.Выдернем информацию из объектов. 3.Возмем информацию из аргументов событий. И так начнем:
1.Пропишем сами. Такой способ подойдет только для литералов: int, float, string и bool. Пример:
Int MyIntName = 14
Теперь наша переменная хранит число 14. Примечание: знак равно "=" - это оператор присвоения, который передает значение правого объекта левому.String MyStringName = "У меня ваще не стрингов"
Примечание для переменной String: текст для хранения в переменной должен быть в кавычках.
Если не передать литералам информацию для хранения, то их значение будет выставлено по умолчанию. Для Int и Float 0, для Bool false, для String пустой текст.2.Выдернем информацию из объектов. Такой способ подходит для всех типов переменных. Выносить информацию из объектов способны некоторые функции, большая часть которых начинается со слова Get или Is. Пример:
Int MyIntName
Event onEffectStart(Actor Target, Actor Caster) MyIntName = Target.GetLevel() EndEvent
Функция GetLevel возвращает число от уровня объекта типа Actor. То есть наша переменная хранит число равное уровню персонажа, который является целью магического эффекта. Помните функция работает только внутри события!3.Возмем информацию из данных событий. Вы так же можете взять на хранение объект из аргументов событий (если он есть). Пример:
Actor MyActorName
Event onEffectStart(Actor Target, Actor Caster) MyActorName = Target EndEvent
При начале эффекта мы сохраним цель заклинания в нашу переменную.При объявлении переменной нужно помнить, что если переменную объявить вне события, то информацию в нем можно использовать в нескольких событиях этого скрипта. Ну а если объявить его внутри события, то его можно использовать лишь в внутри этого события. Смотрим примеры:
Actor MyActorName
Event onEffectStart(Actor Target, Actor Caster) MyActorName = Target EndEvent
Event onEffectFinish(Actor Target, Actor Caster) MyActorName.Kill() EndEvent
Здесь объявив переменную вне события мы дали возможность использовать его во всех событиях нашего скрипта. Смотрим следующий пример:
Event onEffectStart(Actor Target, Actor Caster) Actor MyActorName MyActorName = Target EndEvent
Event onEffectFinish(Actor Target, Actor Caster) EndEvent
Здесь мы объявили нашу переменную внутри события, и теперь им не может воспользоваться функция в другом событии.
Если вы передадите переменной информацию, которую он не способен хранить, то компилятор выдаст ошибку.Ну вот с переменными вы знакомы, теперь продолжим урок о введении объекта из вне через свойства скрипта, который к тому же относится к одному из видов передачи информации переменной. Но этот способ достойный отдельного урока, так что читайте следующий урок.
Урок 6. Свойства. Введение объекта из вне.
Введение объекта из вне через свойства.
Внедрение объектов из вне требует переменную для хранения введенной информации и осуществляется следующей командой:
Actor property MyActorName auto
"Actor" - тип внедряемого объекта. "property" - команда указывающая на то что мы берем объект из свойств (каких свойств? Читаем дальше). "MyActorName" - имя заданное переменной. "auto" - ключевое слово для определения свойства автоматически, оно нужно обязательно, без него компиляция выдает ошибку. После внесения этой строки в скрипт, компилируем его (как? смотрим урок 02) и закрываем окно редактирования скрипта. Потом кликаем правой клавишей мыши по нашему скрипту и выбираем строку Edit Properties. Появится окно где мы видим все свойства скрипта (вот они свойства). В нашем случае там будет только одно свойство, выделяем его и нажимаем кнопку Edit Value и выбираем наш объект Actor либо из списка, либо через окно рендера (Render Window).
Давайте что-нибудь сделаем с введенным персонажем. Открываем окно редактирования скрипта и пропишем функцию для нашего персонажа.
Actor property MyActorName auto
Event onEffectStart(Actor Target, Actor Caster) MyActorName.Kill() EndEvent
При начале данного магического эффекта наш выбранный в свойствах персонаж умрет. Или вот:
Actor property MyActorName auto
Event onEffectStart(Actor Target, Actor Caster) Target.Kill(MyActorName) EndEvent
При начале данного магического эффекта цель заклинания умрет и убийцей его будет наш выбранный в свойствах персонаж. (Вот такая вот подстава)Так же для литералов int, float, string и bool мы можем прописать значение из свойств. Смотрим пример:
Int property MyInt auto
После в свойствах мы можем задать число.
Так же мы можем сделать так:
Int property MyInt = 112 auto
Здесь мы объявили нашу переменную через свойство и тут же выставили значение 112. То есть если мы не зададим в свойствах число, то наша переменная будет равна 112.
Урок 7. Условие if и операторы.
Условие "If" (Если).
Для создания более продвинутого скрипта, вам нужно обязательно уметь ставить условия в скрипте. Для чего нужны условия? Условия помогают "фильтровать" действие разных функций в событии или созданной функции (о создании функции позже). И принцип работы условий выглядит так:
Если это так то делаем эту функцию Если вот так то эту функцию Если не так и не сяк то эту
Пример конечно далек от оригинала, но он описывает принцип работы условий.Построение условия.
Любое начало условий и первое условие объявляется словом If, последующие условия объявляются словом ElseIf или Else, ну а закрываем условия словом EndIf. Вот как это выглядит:
Это читается так: если XXX равно 1, то выполняется функция1, если 2 - функция2, если 3 - функция3, а если ни одна из выше указанных условий не выполнена выполняется функция5. Что из этого примера видно: 1.Команда открытия If пишется всегда и только для первого условия. 2.Команды ElseIf пишутся после первого условия, и их количество может быть не ограничено. 3.Команда Else нужна в случае того, что если ни один из условий не будет выполнен, то выполнится функция в этом условии (там нет условия). 4.Команды If и Else в одном условии могут быть только по одному.Выше написанный пример это полная версия условий, но условия можно писать и так:
If XXX == 1 Функция1 EndIf
Здесь только одно условие, и если это условие не будет выполнено, то функция1 не заработает.If XXX == 1 Функция1 Else Функция5 EndIf
Если условие верно то выполняем функцию1, ну а в любом другом случае выполняем функцию5.If XXX == 1 Функция1 ElseIf XXX == 2 Функция2 ElseIf XXX == 3 Функция3 EndIf
Выполняем функции только по условиям, если ни одна из условий не будет равна, то ни одна функция не заработает.Так же условия можно вписать в условия и можно создавать дерево условий:
If XXX == 1 If YYY == 1 If ZZZ == 1 If BBB == 1 Функция1 EndIf EndIf ElseIf YYY == 2 Функция12 EndIf Else Функция7 EndIf
Так с построением разобрались, теперь об операторах сравнения, которые мы будем использовать в условиях.Операторы для условий.
Операторы сравнения. С одним из них вы уже знакомы: == - двойное равно, выполняется если правое и левое значения равны. Не путайте с одиночным равном, который является оператором присвоения. != - восклицательный знак со знаком равно, выполняется если правое и левое значения не равны. > - знак больше, выполняется если левое значение больше правого. < - знак меньше, выполняется если левое значение меньше правого. >= - знак больше со знаком равно, выполняется если левое значение больше или равно правому. <= - знак меньше со знаком равно, выполняется если левое значение меньше или равно правому.Так же в одном условии могут быть две или более проверок. Вот как это выглядет:
Скрипт читается так: если XXX равно 1 и ZZZ не равно 2 и YYY меньше 10, то выполняем Функцию1. То есть пример условия выше аналогична следующему примеру:
If XXX == 1 If ZZZ != 2 If YYY < 10 Функция1 EndIf EndIf EndIfЛогические операторы. В примере где в одном условии мы показали несколько проверок вы должно быть заметили знаки "&&", это и есть логические операторы. О них подробнее: && - ставится между проверками условий и означает "И" (Саша и Таня == Саша && Таня). || - ставится между проверками условий и означает "ИЛИ" (Пряник или Кнут == Пряник || Кнут) ! - ставится перед проверкой условия и означает "НЕ" (Не дурак == !дурак)
Пример для "ИЛИ":
If XXX == 1 || ZZZ != 2 Функция1 EndIf
Функция1 будет выполнена если XXX будет равен 1 или ZZZ не будет равен 2. Это тоже самое:
If XXX == 1 Функция1 ElseIf ZZZ != 2 Функция1 EndIfПример для "НЕ":
If !XXX == 1 Функция1 EndIf
Это то же самое что:
If XXX != 1 Функция1 EndIf
Надеюсь с построением все понятно. Тогда идем дальше.Объявление условия.
Условие как мы говорили выше объявляется условие либо внутри события, либо внутри созданной функции. Мы для примера создадим условие для события:
Actor property MyActor auto
Event onEffectStart(Actor Target, Actor Caster) If Target == MyActor Target.Kill() Else Caster.Kill() EndIf EndEvent
Растолкуем: при начале эффекта если наша цель заклинания будет нашим персонажем заданным в свойствах, то цель умрет, в противном случае умрет создатель заклинания. Или вот еще пример:
При начале эффекта если уровень цели заклинания меньше или равно 10, то убиваем цель, если уровень больше 10 и меньше 40, то подбрасываем врага вверх с силой 10, в любом другом случае убиваем создателя заклинания.Так же есть булевые условия, в которых можно не писать двойное равно, потому что булевые условия имеют только два значения true(правда) или false(ложь) например:
Event onEffectStart(Actor Target, Actor Caster) If Target.IsRunning() Target.Kill() EndIf EndEvent
При начале заклинания если цель заклинания бежит, то он умрет. Вот то же самое что и выше:
Event onEffectStart(Actor Target, Actor Caster) If Target.IsRunning() == true Target.Kill() EndIf EndEvent
Или вместо True и False можно использовать цифры 1 и 0, где 1 == True, а 0 == False, вот так:
Event onEffectStart(Actor Target, Actor Caster) If Target.IsRunning() == 1 Target.Kill() EndIf EndEvent
Ну а если хотите отрицать, к примеру если наша цель не бежит, то умрет, можно поставить равно False или 0, ну или просто выставить логический оператор, означающий "НЕ", вот так:
Event onEffectStart(Actor Target, Actor Caster) If !Target.IsRunning() Target.Kill() EndIf EndEvent
Помните: вы можете ставить любые условия, в которых вам помогут функции извлекатели информации, которые обычно начинаются со слова Get или Is.
Урок 8. Условие while и операторы присвоения
Дуб, орех или мочала. Начинаем все с начала.
Условие While, очень интересное условие, которое повторяет функцию у себя внутри, пока заданное в нем условие не будет выполнено. Вот пример:
Повторяем пока у Свена вырастут рога 100 см Увеличиваем рога Свена на 1 см Закрываем условие
В этом условии рога у Свена будут увеличиваться по 1 см пока не станут 100 см.Объявляются условия словом While, а закрываются словом EndWhile, вот так:
While XXX <= 100 Функция2 XXX = XXX + 1 EndWhile
Здесь условие будет повторятся пока XXX меньше или равна 100. И мы при каждом повторе задали что к XXX будет прибавлена единица и выполнена функция2, то есть в нашем скрипте функция2 будет выполнена 101 раз, при условии что XXX при начале повтора была равна нулю. Давайте запишем в скрипте:
Event onEffectStart(Actor Target, Actor Caster) Int XXX = 0 While XXX <= 30 Target.PushActorAway(Target, 5) XXX = XXX + 1 EndWhile EndEvent
Здесь при начале эффекта наша цель будет подпрыгивать 30 раз. Обратите внимание если бы мы в условии не написали XXX = XXX + 1, то прыжки были бы до бесконечности. Ну как вы здесь заметили, мы начали уже выполнять сложения, с помощью операторов присвоения.Операторы присвоения.
Вот они операторы присвоения: "=" - одиночный знак равно, давно знакомый, передает левому значение правого. "+" - знак плюс, суммирует значения левого и правого. "-" - минус, вычитает от левого значения правое. "*" - умножение, умножает левое значение на правое. "/" - деление, делит левое значение на правое. "%" - знак процента, делит левое значение на правое и возвращает его остаток (89 % 9 = 8). Так же есть сокращения для записи операторов присвоения, вот: X += Y - прибавить к левому значению правое и вернуть результат (эквивалентно X = X + Y) X -= Y - отнять у левого значения правое и вернуть результат (эквивалентно X = X - Y) X *= Y - умножить левое значение к правому и вернуть результат (эквивалентно X = X * Y) X /= Y - разделить левое значение на правое и вернуть результат (эквивалентно X = X / Y) X %= Y - найти остаток от деления левого значения на правое и вернуть результат (эквивалентно X = X % Y)
С помощью данных операторов можно творить любые математические операции.Ну теперь зная операторы присвоения, мы могли бы написать предыдущий пример так:
Event onEffectStart(Actor Target, Actor Caster) Int XXX = 0 While XXX <= 30 Target.PushActorAway(Target, 5) XXX += 1 EndWhile EndEvent
Осторожно с использованием данного условия, при ошибке это может вызвать бесконечную работу скрипта, что плохо скажется на производительности игры.Оператор приведения типов As.
Данный оператор предназначен для приведения объекта к определенному типу. Зачем это нужно? Нужно это прежде всего чтобы выполнить на объекте функцию, которая не работает с полученным типом объектов, смотрим пример:
Вот это событие выдает нам в аргументах того кто активировал, но обратите внимание что он выдает тип объекта не Actor, а ObjectReference, то есть ссылку на объект. Если мы сделаем так:
Этот скрипт не скомпилируется, так как функция Kill() не работает с типом ObjectReference, вот для этого нам и нужно приведение типов as, давайте сделаем это:
Event OnActivate(ObjectReference akActionRef) Actor MyActor = akActionRef as Actor MyActor.Kill() EndEvent
Мы создали нужную нам переменную Actor и сохранили в нем ссылку на объект приведя его в тип Actor. После функция Kill() уже спокойно будет работать с типом Actor. Вот еще примеры:
Int XXX = 1 Float ZZZ = XXX as FloatActor Target ObjectReference TargetOR = Target as ObjectReferenceВнимание! Оператор приведения типов не превращает один тип объекта в другой, а в какой-то степени просто уточняет его тип. К примеру вы не сможете превратить топор в актера, дверь в квест или заклинание в звук.
Продолжение в комментарии №3
Изменение репутации для пользователя sansuli
sansuliOffline
Сообщение №2
написано: 17 апреля 2015, 16:20
| Отредактировано: sansuli - 17 апреля 2015, 17:59
В игре существует не много глобальных функций, но все они очень полезны. Как мы упоминали для их использования не нужны определенные объекты. Они используются так:
Debug.MessageBox("Свободу Изгоям!")
Показать сообщение в окне, или
Utility.Wait(10)
Оcтановить работу скрипта на 10 секунд. Как видно из этих примеров им нужно лишь приписать на место объекта тип объекта с которым он работает. Есть 6 типов глобальных скриптов это: Debug, Game, Math, Utility, Weather, Message (в Message только одна глобальная функция). Но можно избежать запись этих типов если сделать импорт. Как, смотрим пример:
Event onEffectStart(Actor Target, Actor Caster) Utility.Wait(5) Target.Kill() EndEvent
При начале эффекта через 5 секунд цель эффекта умрет. Вот пример без импорта, теперь сделаем импорт:
Import Utility
Event onEffectStart(Actor Target, Actor Caster) Wait(5) Target.Kill() EndEvent
Вот теперь можно писать функцию без его типа. Примечание: импорт должен быть сделан обязательно вне события или функции, в самом "теле" скрипта.Функции извлекатели.
Функции извлекатели информации, они в отличии от других функций не совершают действия, а просто извлекают информацию из объекта. Вот так:
Int MyActorLevel = MyActor.GetLevel()
Эта функция возвращает число равное уровню объекта.Faction MyFaction = MyActor.GetFactionOwner()
Возвращает фракцию которой владеет наш объект.Weapon MyWeapon = MyActor.GetEquippedWeapon()
Возвращает оружие, которое в руках у нашего объекта (в правой руке, для левой нужно в аргументах функции установить True).Есть извлекатели которые возвращаю только два значения true или false. Вот пример:
Возвращает true если наш объект состоит в фракции, которая указана в аргументах.
Обычно булевые функции начинаются со слова Is, а вытаскивающие информацию со слова Get.Прочие функции.
Остальные функции делают свое дело с объектом, то есть делают что-то. Вот к примеру:
MyActor.SetActorValue("Health", 10000)
Установить объекту здоровье равное 10000 единиц. Супер Босс прям.MyObject.Disable()
Деактивировать объект, он пропадет из игры, но не исчезнет совсем. Чтобы вернуть надо снова применить такую функцию:
MyObject.Enable()
Помните: каждая функция работает только со своим типом объектов.
Урок 10. Комментарии.
Добавление подсказок.
В скрипте если после строки имени и расширения, на нижней строке добавить фигурные скобки {}, и записать в нем что-то, то этот текст будет отображаться при наведении курсора на скрипт в окне скрипта или выбора скрипта.
{Этот скрипт толкает актера и убивает его}
То есть таким образом можно добавить подсказку о вашем скрипте, что он делает, для чего он и т.п.Комментарии.
В теле скрипта все что находится за точкой с запятой ; не учитывается в скрипте.
Player.Kill(Player) ; он убивает сам себя
Таким образом можно добавлять комментарии в больших скриптах чтобы не путаться в функциях. Или это же можно использовать для того чтобы убрать какую-нибудь функцию (если вы думаете, что вы ее еще вернете и не хотите стирать совсем).
;Player.Kill(Player)
Урок 11. Создание функции.
Создание "сборника" функций.
Вот и наконец давно обещанное создание функции. И так начнем. Можно создать функцию, которая просто работает сама по себе, как можно выразиться простым языком "сборник" функций. Ну для его работы не нужны объекты, все нужные объекты уже в внутри "сборника". Вот пример обычного события с рядом функций:
Event onEffectStart(Actor Target, Actor Caster) Actor Player = Game.GetPlayer() ; укажем что Player это игрок Int RandomHaleRate Int XXX = 1 While XXX <= 50 RandomHaleRate = Utility.RandomInt(1, 10) ; выбираем случайное значение от 1 до 10 Player.RestoreAV("Health", RandomHaleRate) ; восстанавливаем здоровье игроку Utility.Wait(3) ; ждем 3 сек XXX += 1 EndWhile EndEvent
При начале эффекта наш персонаж будет восстанавливать здоровье 50 раз каждые 3 секунды от 1 до 10 единиц здоровья. Обратите внимание что наш ряд функций совершенно "автономный", то есть у них нет объектов, которые мы брали из свойств или аргументов события. Теперь давайте создадим сборник этих функций, для этого надо объявить функцию вне события в "теле" скрипта, вот так:
Function MyFunction()
EndFunction
"Function" - объявление новой функции. "MyFunction" - название вашей функции. "EndFunction" - закрываем "тело" функции. И теперь в "тело" нашей функции впишем наш ряд функций:
Function MyFunction() Actor Player = Game.GetPlayer() ; укажем что Player это игрок Int RandomHaleRate Int XXX = 1 While XXX <= 50 RandomHaleRate = Utility.RandomInt(1, 10) ; выбираем случайное значение от 1 до 10 Player.RestoreAV("Health", RandomHaleRate) ; восстанавливаем здоровье игроку Utility.Wait(3) ; ждем 3 сек XXX += 1 EndWhile EndFunction
Вот, теперь в событии напишем название нашей функции:
Event onEffectStart(Actor Target, Actor Caster) MyFunction() EndEvent
Вот и все. Теперь во время нашего события произойдет, то же самое что и в первом примере. Помните, что новая функция и наше событие находятся в одном скрипте.Создание функции с аргументами.
Это уже более сложный вид новой функции и в отличии от него у нас новая функция будет иметь аргументы. Вот пример события с использованием в нем объектов события:
Event onEffectStart(Actor Target, Actor Caster) If Target.GetLevel() < Caster.GetLevel() ; если уровень цели ниже Caster Target.SetAlpha(0.5) ; делаем цель полупрозрачным Target.StartCombat(Caster) ; начать атаку на Caster Target.SetGhost() ; делаем неуязвимым Utility.Wait(60) ; ждем 60 сек Target.Kill(Caster) ; умирай! Else ; в противном случае Target.StartCombat(Caster) ; начать атаку на Caster EndIf EndEvent
При начале эффекта если уровень цели ниже уровня создателя заклинания, то делаем цель полупрозрачным, начинаем атаку на заклинателя, устанавливаем не восприимчивость к урону, ждем 60 секунд, убиваем цель. В противном случае цель просто атакует заклинателя. Вот такой вот ряд функций, ну давайте теперь создадим функцию и впишем туда все что мы писали в событии:
Function MyFunction() If Target.GetLevel() < Caster.GetLevel() Target.SetAlpha(0.5) Target.StartCombat(Caster) Target.SetGhost() Utility.Wait(60) Target.Kill(Caster) Else Target.StartCombat(Caster) EndIf EndFunction
Вот написали, но здесь есть большое НО! В событии мы использовали объекты события, а здесь нам нечего брать, так что придется передать объекты через аргументы нашей функции, впишем два объекта в аргумент нашей функции (два Actor), а так же переименуем наши объекты в "теле" нашей функции:
Function MyFunction(Actor TargetSpell, Actor CasterSpell) If TargetSpell.GetLevel() < CasterSpell.GetLevel() TargetSpell.SetAlpha(0.5) TargetSpell.StartCombat(CasterSpell) TargetSpell.SetGhost() Utility.Wait(60) TargetSpell.Kill(CasterSpell) Else TargetSpell.StartCombat(CasterSpell) EndIf EndFunction
Вот так вот. Все теперь впишем нашу функцию в событие:
Event onEffectStart(Actor Target, Actor Caster) MyFunction(Actor TargetSpell, Actor CasterSpell) EndEvent
Мы вписали, но надо выдать в аргументы функции, объекты (в данном случае там ничего нет):
Event onEffectStart(Actor Target, Actor Caster) MyFunction(Target, Caster) EndEvent
Все теперь наша функция будет работать во время этого события с выданными объектами. Помните, что новая функция и наше событие находятся в одном скрипте.Создание функции для обработки информации.
Давайте пропустим показ примеров функций в событии и сразу начнем к созданию функции. Мы создадим функцию, которая вернет нам среднее число от записанных в аргументе функции, в отличии от предыдущих созданных функций здесь мы зададим тип функции, в нашем случае это тип Float:
Вот и все в игре будет выведено сообщение со средним навыком владения магии. Как видите наша функция выводит число решив его из введенных аргументов.
Помните, что функция и событие находятся в одном скрипте. Ну а если вы хотите использовать функцию из другого скрипта, то читаем дальше.Доступ к функции из другого скрипта.
Для доступа к функции из другого скрипта нам нужно добавить вот такую строчку:
Имя_скрипта property NameForCallFunctions auto
"Имя_скрипта" - имя скрипта, который содержит нашу желаемую функцию. "NameForCallFunctions" - имя для вызова нашей функции из другого скрипта, придумываем сами. После записи этой строчки мы уже можем вызывать функцию, вот так:
Event onEffectStart(Actor Target, Actor Caster) NameForCallFunctions.MyFunction1() NameForCallFunctions.MyFunction2() EndEvent
Урок 12. Массивы.
Массивы - переменные-хранилища.
Массивы - это возможность переменной хранить в себе большое количество однотипных объектов. Это очень помогает когда вам надо создать множество объектов, при этом вы не будете создавать для каждого объекта переменную. Размер массива вы задаете сами, но его размер не может превысить более 128 элементов. Массив сам автоматически пронумерует объекты, и по этим номерам вы можете обращаются к каждому элементу массива. Массивы объявляются как переменные, но с одним небольшим элементом - это квадратные скобки:
Actor[] MyTargets
Так же мы можем объявить массив как свойство:
Actor[] property MyTargets auto
Вот мы объявили массив, но сейчас он пуст и ничего в себе не хранит. Давайте объявим размер массива, для этого нам поможет ключевое слово New:
Actor[] MyTargets
Event onEffectStart(Actor Target, Actor Caster) MyTargets = new Actor[10] EndEvent
Вот размер массива объявлен, он равен десяти, и как видите мы объявили размер массива внутри события (можно внутри функции), так как объявления размера вне события или функции приведет к ошибке компиляции. Ну у нас теперь есть массив, есть его размер, теперь давайте что-нибудь туда "положим", чтобы положить туда что-нибудь надо вызвать каждый элемент массива, вот так:
Actor[] MyTargets
Event onEffectStart(Actor Target, Actor Caster) MyTargets = new Actor[10] MyTargets[0] = Target MyTargets[4] = Caster EndEvent
Вот, здесь мы сохранили цель заклинания в нулевой ячейке массива, а заклинателя в ячейке 4. Как видите вызов элемента массива осуществляется через его номер, помните, что нумерация в массиве начинается с нуля. По таким же номерам к ним нужно обращаться:
Actor[] MyTargets
Event onEffectStart(Actor Target, Actor Caster) MyTargets = new Actor[10] MyTargets[0] = Target MyTargets[4] = Caster Utility.Wait(10) MyTargets[0].Kill() EndEvent
Вот через 10 секунд мы объявляем функцию объекту в ячейке 0, то есть цели заклинания. И еще надо отметить что чаще всего можно увидеть то, что массивы используются вместе с условием While, давайте сделаем что-нибудь используя массив и while:
Actor[] MyTargets
Event onEffectStart(Actor Target, Actor Caster) MyTargets = new Actor[10] Int XXX = 0 While XXX <= 10 MyTargets[XXX] = Target.PlaceActorAtMe(Target.GetActorBase()) MyTargets[XXX].Enable() XXX += 1 EndWhile EndEvent
Вот при начале эффекта будет создано 10 клонов цели заклинания. Все 10 клонов сохранены в нашем массиве, и мы можем обратиться к каждому из них и что-то сделать с ними:
Actor[] MyTargets
Event onEffectStart(Actor Target, Actor Caster) MyTargets = new Actor[10] Int XXX = 0 While XXX <= 10 MyTargets[XXX] = Target.PlaceActorAtMe(Target.GetActorBase()) MyTargets[XXX].Enable() XXX += 1 EndWhile EndEvent
Event onEffecFinish(Actor Target, Actor Caster) MyTargets[5].Kill() MyTargets[3].PushActorAway(MyTargets[0], 30) EndEvent
При окончании эффекта мы убьем объект в ячейке 5 и объект3 оттолкнет объект0.
Урок 13. FormList и GlobalVariable.
FormList - как вариант массивов.
FormList - это объект в игре, который может хранить в себе любые объекты. Можно использовать его как переменную для хранения всего. Создать FormList можно во вкладке Miscellaneous/FormList (CK), после обращаться к нему через свойства скрипта, вот так:
FormList property MyFL auto
FormList будет хранить любой объект, который вы ему передадите, ну а вызывать объекты из него можно по его индексу в FormList. Например, я создал для себя FormList и "запихал" в него Меч, Щит и Шлем. Меч будет иметь индекс 0, щит - 1, шлем 2. Потом в скрипте я вложил в него еще кинжал, который встал под индекс 3:
MyFM.AddForm(MyDagger)
Теперь я могу вызвать любой из этих предметов в скрипте, так:
FormList property MyFL auto Weapon[] MyWeapon Armor[] MyArmor
Event OnActivate(ObjectReference akActionRef) MyWeapon = new Weapon[2] MyArmor = new Armor[2] If akActionRef == Game.GetPlayer() MyWeapon[0] = MyFL.GetAt(0) as Weapon MyWeapon[1] = MyFL.GetAt(3) as Weapon MyArmor[0] = MyFL.GetAt(1) as Armor MyArmor[1] = MyFL.GetAt(2) as Armor Game.GetPlayer().AddItem(MyWeapon[0], 1) Game.GetPlayer().AddItem(MyWeapon[1], 1) Game.GetPlayer().AddItem(MyArmor[0], 1) Game.GetPlayer().AddItem(MyArmor[1], 1) EndIf EndEvent
Event OnActivate(ObjectReference akActionRef) If akActionRef == Game.GetPlayer() MyWeapon1 = MyFL.GetAt(0) as Weapon MyWeapon2 = MyFL.GetAt(3) as Weapon MyArmor1 = MyFL.GetAt(1) as Armor MyArmor2 = MyFL.GetAt(2) as Armor Game.GetPlayer().AddItem(MyWeapon1, 1) Game.GetPlayer().AddItem(MyWeapon2, 1) Game.GetPlayer().AddItem(MyArmor1, 1) Game.GetPlayer().AddItem(MyArmor2, 1) EndIf EndEvent
При активации мне выдадут: меч, щит, шлем и кинжал из моего FormList. Приведение типов "as" было использовано потому, что функция GetAt возвращает тип Form, а не нужный нам Armor и Weapon.Функции для FormList:
FormList.AddForm(Form apForm) ; добавляет в FL объект в аргументе FormList.RemoveAddedForm(Form apForm) ; удаляет из FL объект в аргументе FormList.Revert() ; удаляет все объекты в FL, которые добавили скрипты Form = FormList.GetAt(int aiIndex) ; возвращает объект под индексом в аргументе bool = FormList.HasForm(Form akForm) ; возвращает True если в FL есть объект в аргументе int = FormList.Find(Form apForm) ; возвращает индекс объекта в аргументе int = FormList.GetSize() ; возвращает размер FL (количество объектов)GlobalVariable - глобальные переменные.
GlobalVariable - это глобальные переменные, которые игра хранит в вашем сохранении. Это очень удобный инструмент при скриптовании, с их помощью можно передавать значения из скрипта или в скрипт. К примеру игра хранит в GlobalVariable, игровое время, скорость течения времени и многое другое. Вы же для себя можете создать GlobalVariable во вкладке Miscellaneous/Global (CK). И вызывать его через свойства скрипта:
GlobalVariable property MyGV auto
Надеюсь вы поняли и обойдемся без примеров.Функции для GlobalVariable:
GlobalVariable.SetValue(float afNewValue) ; установить значение в аргументах GlobalVariable.SetValueInt(int aiNewValue) ; установить целое значение в аргументах GlobalVariable.Set(float afValue) ; сокращенное SetValue Int = GlobalVariable.GetValueInt() ; возвращает целое значение Float = GlobalVariable.GetValue() ; возвращает не целое значение Float = GlobalVariable.Get() ; сокращенное GetValue Float = GlobalVariable.Mod(float afHowMuch) ; добавить к значению GV значение в аргументах
Урок 14. Работа с Message.
Польза Message.
Message - это объекты игры, которые могут выводить на экран сообщения с выбором функций. Они похожи на сообщения, выводимые глобальной функцией Debug.MessageBox(), но в отличии от них имеют приемущество.Использование их со скриптом.
Если вы в скрипте хотите сделать выводимое сообщение с выбором функций (как в настройках некоторых модов), то надо создать сообщение. Такие сообщения вы можете создать во вкладке Miscellaneous/Message. На что надо обратить внимание, если вы используете его для скрипта: Окно Message Text - в этом окне будет отображаться основной текст сообщения. Я напишу: "Что вы хотите сделать?" После в окне Menu Buttons создаем строчки необходимые для выбора функций, я создал 3 и задал текст в строчке под индексом 0 - Убить; 1 - Толкнуть; 2 - Раздеть. Ставим галочку на MessageBox и сохраняем наш Message.
Теперь используем его в скрипте:
Event onEffectStart(Actor Target, Actor Caster) EndEvent
Вот у меня есть событие. Введем наш Message через свойства и введем переменную int:
Message property MyMessage auto Int MyButton
Теперь в событии передадим в нашу переменную параметр нашей Message:
Message property MyMessage auto Int MyButton
Event onEffectStart(Actor Target, Actor Caster) MyButton = MyMessage.Show() EndEvent
Все теперь запишем условия зависящие от нашей переменной и функции в условия:
Вот теперь во время начала эффекта, будет выведено сообщение с текстом "Что вы хотите сделать?" и на выбор 3 параметра: Убить, Толкнуть, Раздеть. Теперь выбрав параметр произойдет соответствующая функция.Можно так же создать дерево сообщений:
Message property MyMessage1 auto Message property MyMessage2 auto Message property MyMessage3 auto
Event onEffectStart(Actor Target, Actor Caster) Int MyButton1 = MyMessage1.Show() If MyButton1 == 0 Int MyButton2 = MyMessage2.Show() If MyButton2 == 0 Функция1 ElseIf MyButton2 == 1 Функция2 EndIf ElseIf MyButton1 == 1 Int MyButton3 = MyMessage3.Show() If MyButton3 == 0 Функция3 ElseIf MyButton3 == 1 Функция4 ElseIf MyButton3 == 2 Функция5 ElseIf MyButton3 == 3 Функция6 EndIf EndIf EndEvent
Красное солнце Есть вопросы по скриптам Papyrus? Пиши не в ЛС, а в эту тему.
Изменение репутации для пользователя sansuli
sansuliOffline
Сообщение №3
написано: 17 апреля 2015, 16:55
| Отредактировано: ApeX - 7 февраля 2018, 17:02
Примеры скриптовМногие из этих скриптов я хотел использовать в моем глобал моде, но увы завязал на пол путиРеалистичное изучение заклинания по книге, скрипт вешаем на книгу
Import Debug Import Utility Import Game
Spell property SpellTeachSpell auto ;Изучаемое заклинание Spell property SpellTimeSpeed auto ;Заклинание эффект при наложении ускоряет время Idle property IdleBookReading auto ;IdleBook_Reading айдл чтения книги GlobalVariable property TimeScale auto ;скорость времени(а именно движения часов) Int property MinTeachTime auto ;мин время чтения книги Int property MaxTeachTime auto ;мах время чтения книги
Event OnRead() Actor Player = GetPlayer() Int TeachHours = RandomInt(MinTeachTime, MaxTeachTime) Int TimeScaleMod = 25 ;модификатор ускорения времени Float OriginTS = TimeScale.GetValue() WaitMenuMode(2) If Player.IsInCombat() ;если вы в бою Notification("Вы не можете изучать книгу в бою") ElseIf !Player.IsInCombat() If !Player.HasSpell(SpellTeachSpell) ;работает если у вас еще нет изучаемого заклининия DisablePlayerControls() ;убираем контроль ForceThirdPerson() ;вид от 3го лица Player.AddSpell(SpellTimeSpeed) TimeScale.SetValue(TimeScale.GetValue() * TimeScaleMod) ;ускоряем время WaitGameTime(TeachHours) Player.RemoveSpell(SpellTimeSpeed) TimeScale.SetValue(OriginTS) EnablePlayerControls() Player.AddSpell(SpellTeachSpell) Player.EquipSpell(SpellTeachSpell, 1) Else Notification("Вы уже знаете данное заклинание") EndIf EndIf EndEvent
Скрипт перемещает предмет попавший в контейнер (на котором висит скрипт) обратно хозяину если его нет в выбранном формлисте, хотел использовать его чтобы в маленьких шкатулках нельзы было положить бивень мамонта или эльфийскую броню)
FormList Property AcceptedItemFL Auto
Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) If akSourceContainer == Game.GetPlayer() If !AcceptedItemFL.HasForm(akBaseItem) RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer) Debug.Trace("Этот предмет сюда не поместится") EndIf EndIf EndEvent
При снятии лука снимает и стрелы, данный скрипт уже реализован в моде
Keyword property WeapTypeBow auto Keyword property WeapTypeBoundArrow auto Ammo Arrows
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) Actor Player = GetTargetActor() If (akBaseObject as Ammo) Utility.Wait(0.1) If !akBaseObject.HasKeyword(WeapTypeBoundArrow) && Player.IsEquipped(akBaseObject) Arrows = akBaseObject as Ammo Endif ElseIf (akBaseObject as Weapon) If akBaseObject.HasKeyword(WeapTypeBow) && !Player.IsEquipped(Arrows) && !Player.WornHasKeyword(WeapTypeBoundArrow) If Player.GetItemCount(Arrows) > 0 Player.EquipItem(Arrows, false, true) Endif Endif Endif EndEvent
Event OnObjectUnequipped(Form akBaseObject, ObjectReference akReference) Actor Player = GetTargetActor() If (akBaseObject as weapon) If akBaseObject.HasKeyword(WeapTypeBow) If Player.IsEquipped(Arrows) && !Player.GetEquippedWeapon().HasKeyword(WeapTypeBow) Player.UnequipItem(Arrows, false, true) Endif Endif Endif EndEvent
Скрипт не позволяющий одевать женскую броню на персонажа мужчину и наобарот, хотел реализовать это для моделей брони не имеющих второй модели для другого пола
Keyword property MaleKey auto Keyword property FemaleKey auto
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) Actor Player = GetTargetActor() ActorBase ActorSex = Player.GetActorBase() If akBaseObject.HasKeyword(MaleKey) If ActorSex.GetSex() != 0 GetTargetActor().UnequipItem(akBaseObject) Debug.Notification("Вы не можете одеть мужскую броню") ElseIf ActorSex.GetSex() == 0 EndIf ElseIf akBaseObject.HasKeyword(FemaleKey) If ActorSex.GetSex() != 1 GetTargetActor().UnequipItem(akBaseObject) Debug.Notification("Вы не можете одеть женскую броню") ElseIf ActorSex.GetSex() == 1 EndIf EndIf EndEvent
Скрипт для магического эффекта, который по замыслу должен был выдаваться при распитии спиртных напитков, скрипт делает походку пьяного, вы иногда падаете и раняете оружие, если вы падаете при беге/спринте то еще и получаете небольшой урон
Import Utility Import Game
Idle property DrunkStart auto Idle property DrunkStop auto Idle property DrunkToFall auto Idle property StopIdle auto Actor Drunking
Event onEffectStart(actor Target, actor Caster) RegisterForUpdate(3) Drunking = Target If Drunking == GetPlayer() DisablePlayerControls() Drunking.playidle(DrunkStart) Wait(3) EnablePlayerControls() EndIf Drunking.playidle(DrunkStart) EndEvent
Event OnUpdate() Int XXX = RandomInt(1, 10) If XXX >= 5 ShakeCamera(Drunking , 0.5, 2) EndIf If !Drunking.IsRunning() && !Drunking.IsSprinting() && !Drunking.IsSneaking() If XXX == 1 Dranking.PlayIdle(DrunkToFall) Drunking.PushActorAway(Drunking, 0) If Drunking.IsWeaponDrawn() == 1 Wait(0.5) Drunking.DropObject(Drunking.GetEquippedWeapon(true), 1) Drunking.DropObject(Drunking.GetEquippedWeapon(false), 1) EndIf EndIf ElseIf Drunking.IsRunning() || Drunking.IsSprinting() If XXX <= 3 Wait(1) Drunking.PushActorAway(Drunking, 0) Drunking.DamageAV("Health", 5) If Drunking.IsWeaponDrawn() Wait(0.5) Drunking.DropObject(Drunking.GetEquippedWeapon(true), 1) Drunking.DropObject(Drunking.GetEquippedWeapon(false), 1) EndIf EndIf ElseIf Drunking.IsSneaking() If XXX <=4 Drunking.PushActorAway(Drunking, 0) If Drunking.IsWeaponDrawn() Wait(0.5) Drunking.DropObject(Drunking.GetEquippedWeapon(true), 1) Drunking.DropObject(Drunking.GetEquippedWeapon(false), 1) EndIf EndIf EndEvent
Event onEffectFinish(actor Target, actor Caster) Drunking.PlayIdle(DrunkStop) Wait(1) Drunking.PlayIdle(StopIdle) UnregisterForUpdate() EndEvent
Скрипт сильной опьяненности, выдавался бы при продолжении "бухать", игрок здесь вырубится на несколько часов (здесь странно нет выпадания оружия)
Import Utility Idle property DrunkStart auto Idle property DrunkStop auto ImageSpaceModifier property BlackISM auto GlobalVariable property TimeScale auto Spell property TimeSpeedSpell auto ;заклинание эффекта ускорения времени Actor Drunking Float TimeScaleFloat
Idle property StartBleedOut auto Idle property StopBleedOut auto
Event onEffectStart(actor Target, actor Caster) If Target.IsWeaponDrawn() == 1 Target.DropObject(Target.GetEquippedWeapon(false), 1) Target.DropObject(Target.GetEquippedWeapon(true), 1) Target.DropObject(Target.GetEquippedShield(), 1) EndIf Int LifeTime = Utility.RandomInt(5, 20) Target.PlayIdle(StartBleedOut) Utility.Wait(LifeTime) Target.Kill() If Target.IsDead() == 0 Target.PlayIdle(StopBleedOut) EndIf EndEvent
Вариант без смерти
Idle property StartBleedOut auto Idle property StopBleedOut auto Int property SickHeartTime auto
Event onEffectStart(actor Target, actor Caster) If Target.IsWeaponDrawn() == 1 Target.DropObject(Target.GetEquippedWeapon(true), 1) Target.DropObject(Target.GetEquippedWeapon(false), 1) EndIf Target.PlayIdle(StartBleedOut) Utility.Wait(SickHeartTime) Target.PlayIdle(StopBleedOut) EndEvent
Скрипт создан для нового типа заклинания, например: в проперти укажем эффект чтобы видеть души животных, при касте данного заклинания выдаем эффект из проперти и начинаем поддерживать его маной, так можно просто включить магию пока не иссякнет магия
Spell property SpellOnOff auto Int property DamageMagickaInt auto
Event onEffectStart(actor Target, actor Caster) Int XXX = DamageMagickaInt * 2 If !Target.HasSpell(SpellOnOff) Target.AddSpell(SpellOnOff) While Target.GetAV("Magicka") > XXX If Target.HasSpell(SpellOnOff) Target.DamageAV("Magicka", DamageMagickaInt) Utility.Wait(0.1) ElseIf !Target.HasSpell(SpellOnOff) XXX = 10000 EndIf EndWhile Target.RemoveSpell(SpellOnOff) ElseIf Target.HasSpell(SpellOnOff) Target.RemoveSpell(SpellOnOff) EndIf EndEvent
Заклинание похоже на эффект ФусРоДа, но толкает очень сильно, жертва раняет оружие и получает урон
Int Property PushForce auto Int property DamageHealth auto
Event onEffectStart(actor Target, actor Caster) Caster.PushActorAway(Target, 20) If Target.IsWeaponDrawn() Target.DropObject(Target.GetEquippedWeapon(True), 1) Target.DropObject(Target.GetEquippedWeapon(False), 1) EndIf Target.DamageAV("Health", DamageHealth) EndEvent
Используем на мертвое тело, тело постепенно исчезает и пропадает из игры, но далее я хотел добавить к этому чтобы тело при испарении восполняло очки ХП или Маны (ну или еще чего нибудь)
Event onEffectStart(actor Target, actor Caster) Float AlphaValue = 1 Int XXX = 0 If Target.IsDead() While XXX < 100 Target.SetAlpha(AlphaValue) Utility.Wait(0.1) AlphaValue -= 0.01 XXX += 1 EndWhile Target.Disable() Target.Delete() EndIf EndEvent
Второй вариант:
EffectShader property MagicEffectShader auto ;shockdisintegrate01fxs
Event onEffectStart(actor Target, actor Caster) If Target.IsDead() MagicEffectShader.Play(Target, 10) Utility.Wait(3) Target.Disable() Target.Delete() EndIf EndEvent
Заклинание выталкиванию души, при контакте душа жертвы выталкивается и исчезает
Actor CloneTarget Actor TargetEff Spell property PhantomForm auto
Заклинание ожидание, хотел заменить стандартное ожидание на это, это заклинание для работы должно иметь другой эффект который дает эффект ускорения времени + изменяет ход течения часов
Spell property SpellSpeedTime auto ;данное заклинание должно дать ускорение времени + TimeScaleMod
Event onEffectStart(Actor Target, Actor Caster) Actor Player = Game.GetPlayer() If !Player.HasSpell(SpellSpeedTime) Debug.Notification("On") Player.AddSpell(SpellSpeedTime) Game.DisablePlayerControls(true, false, true, false, true, false, true, true) ElseIf Player.HasSpell(SpellSpeedTime) Debug.Notification("Off") Player.RemoveSpell(SpellSpeedTime) Game.EnablePlayerControls() EndIf EndEvent
Пока пусто
Тело скрипта
Пока пусто
Тело скрипта
Пока пусто
Тело скрипта
Пока пусто
Тело скрипта
Пока пусто
Тело скрипта
Чтобы не усложнять тему для поиска определенных скриптов, прошу в комментариях писать посты только с примерами скриптов или их исправлением, если обнаружили ошибку; от прочих комментариев прошу воздержаться, заранее спасибо ( _ _)人
Красное солнце Есть вопросы по скриптам Papyrus? Пиши не в ЛС, а в эту тему.
Форум » TES V: Skyrim » Мастерская » Уроки по скриптованию и примеры скриптов на языке Papyrus (Уроки по скриптованию на языке Papyrus для TES5 Skyrim)