Модератор форума: Kris†a™  
Форум » TES V: Skyrim » Мастерская » Вопросы по скриптам Papyrus (О скриптах Papyrus (Skyrim). Скриптеры не проходите мимо!)

Вопросы по скриптам Papyrus
sansuli  Offline  Сообщение №1 написано: 31 августа 2012, 13:29 | Отредактировано: Multigone - 23 апреля 2020, 14:24


The Red Sun


193
Уроки по скриптованию на языке Papyrus
Прежде чем задать вопрос просмотрите вышеуказанные уроки.
ok


Тема регламентирована.


• Прежде, чем задать вопрос, пожалуйста, убедитесь, что такой вопрос не задавался раньше. Старайтесь описать суть вопроса как можно подробней.
• Прежде, чем опубликовать ответ на вопрос, пожалуйста, убедитесь, что обладаете необходимыми для этого знаниями. Старайтесь cформулировать суть ответа как можно лаконичней.
• При желании ответить в приватном порядке, пожалуйста, воспользуйтесь ЛС.
• При желании поблагодарить ответившего, пожалуйста, воспользуйтесь кнопкой "
+" полезного сообщения.

Сообщения, не относящиеся к вопросам по скриптам Papyrus, ответам на них или уточнениям, являются оффтопом и могут быть удалены.

Красное солнце
Есть вопросы по скриптам Papyrus? Пиши не в ЛС, а в эту тему.
AleksTirex  Offline  Сообщение №361 написано: 19 августа 2013, 19:57


Архимаг


371
Цитата slastik

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



Actor akActor = Game.GetPlayer()
akActor.UnequipItemEx(akActor.GetEquippedObject(1), 1, true) ; SKSE
akActor.UnequipItemEx(akActor.GetEquippedObject(0), 2, true) ; SKSE

slastik  Offline  Сообщение №362 написано: 20 августа 2013, 09:34 | Отредактировано: slastik - 20 августа 2013, 09:35


Жаждущий


209
Цитата AleksTirex

Actor akActor = Game.GetPlayer()


Такой вариант не хочет компилировать. Пробовал по-всякому :(

Работает команда Game.GetPlayer().UnequipItemSlot(39) для снятия щита.
Теперь не могу понять какой номер слота у факела. Буду пытаться методом проб и ошибок.

Добавлено (20.08.2013, 13:34)
---------------------------------------------
Очень странно. Все указывает на то, что факел занимает 11-й слот. Но команда Game.GetPlayer().UnequipItemSlot(11) не убирает факел. Поэтому решил проблему самым примитивным способом - добавил Game.GetPlayer().UnequipItem(Torch) и Light Property Torch Auto. Благо, что в игре используется только один тип факелов.

- Что это за горы стоят?
- А, это орки бегут!
AleksTirex  Offline  Сообщение №363 написано: 20 августа 2013, 11:55


Архимаг


371
Цитата slastik

Такой вариант не хочет компилировать. Пробовал по-всякому



Это команда, а не свойство, поэтому такое писать надо только в теле события или функции, точно также, как все остальные команды. (а ты писал вне тела, рядом со свойствами, поэтому и не компилировалось) К тому же, если в скрипте уже есть свойство akActor, то здесь надо было переименовать эту данную переменную.
 
Цитата:

Все указывает на то, что факел занимает 11-й слот.

У факела нет слота, он не одежда. (слоты с 30 по 61, а 11 - это номер типа объекта, а не слот) Факел одевается как оружие.
 
************************************
 
Raser0919, сделай функцию запуска в пусковом скрипте:
 
ObjectReference Property akObject  auto ; объект
float fDistanc = 100.0 ; дистанция объекта от актёра
float fHight =  75.0 ; высота объекта от земли
float fSpeed = 650.0 ; скорость движения 300-1000

Function TranslateStart()
 Actor akActor = Game.GetPlayer()
 float XX = akActor.X + fDistanc * Math.Sin(akActor.GetAngleZ())
 float YY = akActor.Y + fDistanc * Math.Cos(akActor.GetAngleZ())
 float ZZ = akActor.Z + fHight
 akObject.TranslateTo(XX, YY, ZZ, akActor.GetAngleX(), akActor.GetAngleY(), akActor.GetAngleZ(), fSpeed)
endFunction

Это подтянет к актёру твой объект и запустит цикл на его удержание около актёра. Если объекта нет рядом и/или его надо создать, то в теле функции ObjectReference akObject = akActor.PlaceAtMe(akObjectBase) ; (свойство на объект удалить и эту строку писать сразу под Actor akActor = Game.GetPlayer())
 
На самом объекте вешается скрипт:
 
float fDistanc = 100.0 ; дистанция объекта от актёра
float fHight =  75.0 ; высота объекта от земли
float fSpeed = 650.0 ; скорость движения 300-1000
 
Event OnTranslationComplete()
Actor akActor = Game.GetPlayer()
float XX = akActor.X + fDistanc * Math.Sin(akActor.GetAngleZ())
float YY = akActor.Y + fDistanc * Math.Cos(akActor.GetAngleZ())
float ZZ = akActor.Z + fHight
self.TranslateTo(XX, YY, ZZ, akActor.GetAngleX(), akActor.GetAngleY(), akActor.GetAngleZ(), fSpeed)
EndEvent
 
Event OnTranslationFailed()
Actor akActor = Game.GetPlayer()
float XX = akActor.X + fDistanc * Math.Sin(akActor.GetAngleZ())
float YY = akActor.Y + fDistanc * Math.Cos(akActor.GetAngleZ())
float ZZ = akActor.Z + fHight
self.TranslateTo(XX, YY, ZZ, akActor.GetAngleX(), akActor.GetAngleY(), akActor.GetAngleZ(), fSpeed)
EndEvent

Так объект будет "стремиться" постоянно оставаться на нужном расстоянии от актёра ровно перед ним. Это не будет работать на предметах (череп, одежда, меч и т.д.)
Если будешь перемещаться по локациям, то можешь применить функцию с SetPosition, а после неё обязательно опять пусковую функцию, чтобы по новой запустить цикл удержания объекта.
 
Function Translate()
Actor akActor = Game.GetPlayer()
  float XX = akActor.X + fDistanc * Math.Sin(akActor.GetAngleZ())
  float YY = akActor.Y + fDistanc * Math.Cos(akActor.GetAngleZ())
  float ZZ = akActor.Z + fHight
  akObject.SetPosition(XX, YY, ZZ)
endFunction

***********

slastik  Offline  Сообщение №364 написано: 20 августа 2013, 12:18 | Отредактировано: slastik - 20 августа 2013, 12:20


Жаждущий


209
Цитата AleksTirex

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


Я вписывал его в событие:

Event OnEffectStart(Actor Target, Actor Caster)
If game.getPlayer().GetItemCount(Item01) >= 1
Actor akActor = Game.GetPlayer()
Game.ForceThirdPerson()
akActor.UnequipItemEx(akActor.GetEquippedObject(1), 1, true)
akActor.UnequipItemEx(akActor.GetEquippedObject(0), 2, true)
Game.GetPlayer().PlayIdle(Idle01)
Utility.Wait(1)
Sound01.play(game.getPlayer())
Utility.Wait(Time01)
Game.GetPlayer().PlayIdle(Idle02)
Game.EnablePlayerControls()
Else
Message01.Show()
EndIf
endEVENT

Пробовал изменять akActor на Actor. Потом убирал строку Actor akActor = Game.GetPlayer() и менял akActor на Game.GetPlayer(), но безрезультатно. Наверно я слишком слаб еще в скриптах. А по поводу слотов - спасибо большое за информацию. Я думал, что у оружия тоже есть слоты, только скрытые.

- Что это за горы стоят?
- А, это орки бегут!
AleksTirex  Offline  Сообщение №365 написано: 20 августа 2013, 12:43


Архимаг


371
Цитата slastik

Пробовал изменять akActor на Actor.



Actor Actor = Game.GetPlayer() - это да, так компилятор сразу пошлёт подальше.

Скорее всего, ты забыл, что UnequipItemEx  - это функция SKSE, поэтому без установленного SKSE компилятор тоже пошлёт, а игра не обработает такой скрипт.

"менял akActor на Game.GetPlayer()" - правильный вариант.

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

mayor  Offline  Сообщение №366 написано: 20 августа 2013, 21:38



194
кто скажет скрипты для диалогов?а именно - драка на кулаках на 100з,пить на спор,и игра в пятнашки.

El_Barrent  Offline  Сообщение №367 написано: 21 августа 2013, 20:45



45
Цитата slastik

Artem13, спасибо. А теперь бы узнать какие слоты нужны :)

Добавлено (19.08.2013, 19:26)
---------------------------------------------
Разобрался со слотом для щита, а вот факел какой слот занимает? :(


http://www.creationkit.com/Biped_Object

mayor  Offline  Сообщение №368 написано: 23 августа 2013, 17:36



194
Цитата mayor

кто скажет скрипты для диалогов?а именно - драка на кулаках на 100з,пить на спор,и игра в пятнашки.

поможет кто нибудь?

Artem13  Offline  Сообщение №369 написано: 28 августа 2013, 10:17


Mercenaries. Со смертью на ты.


Подскажите шаблончик скрипта для однократной выдачи перка герою. Т.е. такого, который крепится к квесту, стартующему однократно при первом запуске игры. А то что-то  ДЛЦ-шные скрипты мне СК отказывается показывать :(

<a class="link" href="http://nick-name.ru/sertificates/278209/" rel="nofollow" target="_blank"> border="0" alt=""/</a>
Да, мы бандиты и бродяги, как злословит молва,
Мы попадаем в передряги, помня эти слова.
Смотри вперед и не сдавайся ты на милость судьбе!
Предай их всех, останься верен себе. (Канцлер Ги - Кантри Бреган Д'Эрт)
AleksTirex  Offline  Сообщение №370 написано: 29 августа 2013, 15:44


Архимаг


371
Цитата Artem13

Подскажите шаблончик скрипта для однократной выдачи перка герою. Т.е. такого, который крепится к квесту, стартующему однократно при первом запуске игры. А то что-то  ДЛЦ-шные скрипты мне СК отказывается показывать



Perk Property akPerk auto
 
 Event OnInit()
   Game.GetPlayer().AddPerk(akPerk)
 endEVENT

 
Исходники DLC лежать в той же папке с другими исходниками, но в своей отдельной папке. Надо просто их переложить в общую папку.

Artem13  Offline  Сообщение №371 написано: 29 августа 2013, 15:46 | Отредактировано: Artem13 - 29 августа 2013, 15:47


Mercenaries. Со смертью на ты.


AleksTirex, ага, сенькс. Т.е. для прикрепляемого к квесту скрипта нет особого типа? Тип определяется выполняемой функцией? Вместо akPerk рисовать ид своего перка или как там параметр передаётся?

<a class="link" href="http://nick-name.ru/sertificates/278209/" rel="nofollow" target="_blank"> border="0" alt=""/</a>
Да, мы бандиты и бродяги, как злословит молва,
Мы попадаем в передряги, помня эти слова.
Смотри вперед и не сдавайся ты на милость судьбе!
Предай их всех, останься верен себе. (Канцлер Ги - Кантри Бреган Д'Эрт)
AleksTirex  Offline  Сообщение №372 написано: 29 августа 2013, 16:38


Архимаг


371
У скриптов всегда есть "тип". При создании нового скрипта в квесте ты пишешь название этого скрипта (его ID), а тип скрипта сам добавится. (кнопка Add, в списке верхняя строка [New Script])
 
Свойству akPerk надо будет назначить твой перк: у окна рядом со скриптом есть кнопочка Properties, на неё нажимаешь и выскочит окошко. Там выделяешь akPerk и жмёшь кнопку Edit Value, там в списке ищешь свой перк, потом везде ОК.
 
Вот так будет выглядеть готовый скрипт (название придумаешь своё) :
 
Scriptname aaMyQuestScript Extends Quest
 
Perk Property akPerk auto
 
 Event OnInit()
   Game.GetPlayer().AddPerk(akPerk)
 endEVENT

Artem13  Offline  Сообщение №373 написано: 29 августа 2013, 17:09


Mercenaries. Со смертью на ты.


AleksTirex, спасибо. Вот теперь понял.

<a class="link" href="http://nick-name.ru/sertificates/278209/" rel="nofollow" target="_blank"> border="0" alt=""/</a>
Да, мы бандиты и бродяги, как злословит молва,
Мы попадаем в передряги, помня эти слова.
Смотри вперед и не сдавайся ты на милость судьбе!
Предай их всех, останься верен себе. (Канцлер Ги - Кантри Бреган Д'Эрт)
AleksTirex  Offline  Сообщение №374 написано: 30 августа 2013, 10:34


Архимаг


371
Raser0919, вот фрагмент скрипта самого определения нужного движения, это для примера:
 




Raser0919  Offline  Сообщение №375 написано: 30 августа 2013, 11:05



409
Скинь еще и инициализаторы скрипта..... Ну типы, property, перед событием.

AleksTirex  Offline  Сообщение №376 написано: 30 августа 2013, 11:24


Архимаг


371
Raser0919
 


Jocc  Offline  Сообщение №377 написано: 10 сентября 2013, 19:56



12
Подскажите пож. возможно сделать на кровать скрипт, чтобы когда на ней засыпали просыпались на другой кровати в другом месте? unsure

AleksTirex  Offline  Сообщение №378 написано: 13 сентября 2013, 12:17


Архимаг


371
Цитата Jocc

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



НПС или ГГ?

Jocc  Offline  Сообщение №379 написано: 13 сентября 2013, 12:25



12
Цитата AleksTirex

НПС или ГГ?

ГГ

AleksTirex  Offline  Сообщение №380 написано: 14 сентября 2013, 02:00


Архимаг


371
Цитата Jocc

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



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

Вот сам принцип. Делается такой скрипт на любом постоянном предмете или в своём квесте:
 
ObjectReference Property akObjectBed  auto ; кровать, на которой должен проснуться ГГ
 
Event OnInit()
  RegisterForSleep()
endEvent

 
Event OnSleepStop(bool abInterrupted)
  Game.GetPlayer().MoveTo(akObjectBed)
endEvent

 
Для отмены эффекта команда UnregisterForSleep()
 
Можно сделать форм-лист, в котором будут прописаны хоть двести разных кроватей из игрового мира, которые стоят где-то в помещениях, т.е. имеют референс. Тогда можно рендомно выбирать одну из этих кроватей.
 
FormList Property kListReferenceBed  auto ; форм-лист с референсами кроватей
 
Event OnInit()
  RegisterForSleep()
endEvent

 
Event OnSleepStop(bool abInterrupted)
  int iIndex = kListReferenceBed.GetSize() - 1
  int irandom = Utility.RandomInt(0, iIndex)
  ObjectReference akReferenceBed = ListArmorPL.GetAt(irandom) as ObjectReference
  Game.GetPlayer().MoveTo(akReferenceBed)
endEvent

 
Создание форм-листа:
создаёшь новый форм-лист, в его окно просто перетаскиваешь нужную кровать из окна Cell View (правая часть окна, там список объектов этой ячейки). И так все понравившиеся кровати из разных локаций добавляются в этот список.
 
ГГ будет просыпаться на кровати как простой НПС, т.е. будет реально лежать на ней. Для подъёма с кровати надо нажать "E", т.е. активировать.

Добавлено (14.09.2013, 06:00)
---------------------------------------------
Если надо чтобы только на определённой кровати был такой эффект, то надо повесить скрипт на эту кровать:
 
ObjectReference Property akObjectBed  auto ; кровать, на которой должен проснуться ГГ
 
Event OnActivate(ObjectReference akActionRef)
  if akActionRef == Game.GetPlayer()
    RegisterForSleep()
  endif
endEvent

 
Event OnSleepStop(bool abInterrupted)
  UnregisterForSleep()
  Game.GetPlayer().MoveTo(akObjectBed)
endEvent


Jocc  Offline  Сообщение №381 написано: 14 сентября 2013, 10:37 | Отредактировано: Jocc - 14 сентября 2013, 10:49



12
AleksTirex, спасибо за помощь.
Я только вот сразу не уточнил, что необходимо связать две заранее определенные кровати, на одной ГГ засыпает, а на другой просыпается. blush
Тут, наверное, где то условие нужно сделать с проверкой на "нужную кровать засыпания".

AleksTirex  Offline  Сообщение №382 написано: 14 сентября 2013, 18:19


Архимаг


371
Цитата Jocc

Подскажите, как задать отдельный период респауна для контейнера?



Надо повесить скрипт на этот контейнер:
 
Респаун будет через 5 дней при условии, что ГГ не будет посещать эту локацию с объектом, иначе отсчёт начинается снова.

Event OnCellDetach()
  UnregisterForUpdateGameTime()
  RegisterForSingleUpdateGameTime(120.0) ; 24 часа * 5 дней
EndEvent

 
Event OnUpdateGameTime() 
  self.Reset()
endEvent

-----------------------------------------------------
Респаун через 5 дней произойдёт в любом случае, бывал в той локации ГГ или нет.
 
auto state StateDefault
Event OnCellDetach()
  RegisterForSingleUpdateGameTime(120.0) ; 24 часа * 5 дней
  gotoState("StateWait")
EndEvent
endState

 
state StateWait
Event OnUpdateGameTime() 
  self.Reset()
  gotoState("StateDefault")
endEvent
endState

slastik  Offline  Сообщение №383 написано: 14 сентября 2013, 20:00


Жаждущий


209
Цитата AleksTirex

Респаун через 5 дней произойдёт в любом случае, бывал в той локации ГГ или нет.


Нужен был именно такой вариант. Все прекрасно скомпилировалось, но не работает :(

- Что это за горы стоят?
- А, это орки бегут!
AleksTirex  Offline  Сообщение №384 написано: 14 сентября 2013, 20:19 | Отредактировано: AleksTirex - 14 сентября 2013, 20:27


Архимаг


371
Цитата slastik

Нужен был именно такой вариант. Все прекрасно скомпилировалось, но не работает



А ты так и стоял около сундука все 5 дней? :D

Так вышел бы погулять на улицу, в игре именно так и делают. Но если тебе надо обязательно иметь возможность дождаться респауна не отходя от сундука, то замени событие OnCellDetach() на OnActivate().

*****************
Кстати, а ты проверил наличие галочки Respawns на сундуке? ;)

slastik  Offline  Сообщение №385 написано: 14 сентября 2013, 20:36


Жаждущий


209
Цитата AleksTirex

Кстати, а ты проверил наличие галочки Respawns на сундуке?

Конечно.
И пять дней я не ждал, а изменил для теста UpdateGameTime на 1.0 :)

У меня вышел абсолютно рабочим вариант с событием OnItemRemoved.
Сейчас попробую с OnActivate, может так даже проще будет.
Спасибо.

- Что это за горы стоят?
- А, это орки бегут!
Jocc  Offline  Сообщение №386 написано: 15 сентября 2013, 00:35



12
Цитата AleksTirex

Если надо чтобы только на определённой кровати был такой эффект, то надо повесить скрипт на эту кровать:

Если надо чтобы только на определённой кровати был такой эффект, то надо повесить скрипт на эту кровать:
 
ObjectReference Property akObjectBed  auto ; кровать, на которой должен проснуться ГГ
 
Event OnActivate(ObjectReference akActionRef)
  if akActionRef == Game.GetPlayer()
    RegisterForSleep()
  endif
endEvent
 
Event OnSleepStop(bool abInterrupted)
  UnregisterForSleep()
  Game.GetPlayer().MoveTo(akObjectBed)
endEvent


Получилось. Тебе, AleksTirex,  цены просто нет good

StanislavD  Offline  Сообщение №387 написано: 29 сентября 2013, 07:56 | Отредактировано: StanislavD - 29 сентября 2013, 07:59



123
какой/какое оператор/свойство даёт команду нпс ждать, а какой/какое оператор/свойство даёт команду продолжать действие?

anton  Offline  Сообщение №388 написано: 6 октября 2013, 10:35



362
С помощью команды Debug.SendAnimationEvent(Game.GetPlayer(), "MyAnimation") я запускаю свою анимацию.
Как определить момент времени, когда она закончится ? (чтобы вовремя запустить другую анимацию)

Сейчас у меня там просто Utility.Wait(30.0) стоит, потому что я знаю продолжительность этой анимации.

Я так понял, что для этого можно использовать функцию RegisterForAnimationEvent(). Но что ей указать в параметре asEventName ? Если имя своей анимации указать, то словится её начало, а нужен конец...

Мой Блог
Artem13  Offline  Сообщение №389 написано: 6 октября 2013, 14:33 | Отредактировано: Artem13 - 6 октября 2013, 14:37


Mercenaries. Со смертью на ты.


Цитата anton

Но что ей указать в параметре asEventName ? Если имя своей анимации указать, то словится её начало, а нужен конец...

На вики пример с Reset (но это, так понимаю, перезапуск) и IdleFurnitureExit. Линка на перечень ивентов не нашел. Есть подозрение, что эти самые ивенты прописаны в самих анимациях (собственно, похоже так и есть - первое сообщение  http://forums.nexusmods.com/index.p....d-spell ).

<a class="link" href="http://nick-name.ru/sertificates/278209/" rel="nofollow" target="_blank"> border="0" alt=""/</a>
Да, мы бандиты и бродяги, как злословит молва,
Мы попадаем в передряги, помня эти слова.
Смотри вперед и не сдавайся ты на милость судьбе!
Предай их всех, останься верен себе. (Канцлер Ги - Кантри Бреган Д'Эрт)
anton  Offline  Сообщение №390 написано: 7 октября 2013, 17:34 | Отредактировано: anton - 7 октября 2013, 17:35



362
Artem13, в анимациях нельзя прописать свои "ивенты" (я такого до сих пор не встречал), но с помощью "аннотаций" есть возможность выполнять кое какие движения, заданные где то в дебрях BHV файлов. Их совсем немного (около 10) и в основном они используются для синхронизации движений ног и вынимания оружия. Да, ещё звуки можно в "аннотациях" прописать.
А "Reset" и "IdleFurnitureExit" как мне кажется это не что иное как те же анимации. Только они вызываются в связке с основной анимацией, при её завершении.

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

Добавлено (07.10.2013, 21:34)
---------------------------------------------
Подскажите, можно ли в Папирусе можно создать двухмерный массив ( матрицу [m][n]) не прибегая в "виртуализации" ?

И ещё, можно ли как нибудь быстро заполнить массив, не указывая каждый элемент, т.е. можно ли как то записать Array = {1,2,3}, а не Array[1]=1, Array[2]=2, Array[3]=3 ?

Мой Блог
Форум » TES V: Skyrim » Мастерская » Вопросы по скриптам Papyrus (О скриптах Papyrus (Skyrim). Скриптеры не проходите мимо!)
Поиск:





Ответ на жалобу смотрите в разделе жалоб