Модератор форума: 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? Пиши не в ЛС, а в эту тему.
Holtof55  Offline  Сообщение №1351 написано: 24 января 2015, 08:32 | Отредактировано: Holtof55 - 24 января 2015, 08:34



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

Код
Event OnEffectStart(Actor akTarget, Actor akCaster)
    if(akTarget)
      akTarget.AllowPCDialogue(true)
     endif
endEvent


Но дело все в том, что этот AllowPCDialogue(true) ставится навечно, а мне надо на время, либо(что предпочтительней), код на удаление этого AllowPCDialogue(true)
Для тех кто знает, это секундное дело, напишите плиз

Dsion  Offline  Сообщение №1352 написано: 24 января 2015, 09:47 | Отредактировано: Dsion - 24 января 2015, 09:45



Попробуй добавить к этому же скрипту такое:


Код
Event OnEffectFinish(Actor akTarget, Actor akCaster)
     akTarget.AllowPCDialogue(false)
EndEvent

OnEffectStart срабатывает, когда эффект на кого-то накладывается и устанавливает для NPC
AllowPCDialogue - Да

А OnEffectFinish срабатывает, когда эффект заканчивает действие и устанавливает
AllowPCDialogue - Нет

Добавлено (24 Января 2015, 12:47)
---------------------------------------------
If (akTarget)
EndIf

Там не нужно, я думаю. Если эффект наложился, то только на какого-то Actor. Значит, в akTarget всегда кто-то есть.


Holtof55  Offline  Сообщение №1353 написано: 24 января 2015, 11:14 | Отредактировано: Holtof55 - 24 января 2015, 11:26



49
Цитата Dsion

OnEffectStart срабатывает, когда эффект на кого-то накладывается и устанавливает для NPCAllowPCDialogue - Да

А OnEffectFinish срабатывает, когда эффект заканчивает действие и устанавливает
AllowPCDialogue - Нет

Тут-то весь и вопрос, а как мы это время поймем, если оно не задано?
Когда должен сработать финишь эффекта? Или это надо указать в Duration?

Скрипт скомпилировался, пойду пробовать в игре
Спасибо!

Все в игре работает, СПАСИБО ОГРОМНОЕ!..мне может еще кое что понадобится, в частности простой код на следование за игроком, и после какого-то действия код должен удалится(перестать работать), могу обратится?

Dsion  Offline  Сообщение №1354 написано: 24 января 2015, 11:23 | Отредактировано: Dsion - 24 января 2015, 11:23



Цитата Holtof55

Когда должен сработать финишь эффекта?


Это уж тебе точно виднее :)
Если это заклинание (Spell), то будет висеть столько, сколько длительность действия заклинания. Если зачарование, то эффект пропадет, когда предмет снимется итп.

Можно, конечно:

Код
Event OnEffectStart(Actor akTarget, Actor akCaster)   
     akTarget.AllowPCDialogue(true)
     Utility.Wait(60)
     akTarget.AllowPCDialogue(false)
EndEvent

Но это не круто...

Holtof55  Offline  Сообщение №1355 написано: 24 января 2015, 11:30 | Отредактировано: Holtof55 - 24 января 2015, 11:34



49
Dsion Спасибо! Код работает! good

Holtof55  Offline  Сообщение №1356 написано: 27 января 2015, 08:16



49
Так, теперь новая задача. Нужен скрипт магического эффекта который снимет с Драугров, Фалмеров, и Дремор их экипировку,, включая одежду и доспехи, а после окончания эффекта, оденет обратно. Кто-то может такой скрипт соорудить?  Зачем мне это нужно? :( Ну, вот ...надо... ;)

Myprism  Offline  Сообщение №1357 написано: 27 января 2015, 10:12


Физик


To all:
Как обнулить действие скрипта, который сохранён в сейве игрока?
У меня в моде есть кольца со скриптом на них. Мне нужно выложить обновление мода, в котором этот скрипт изменён. Но те игроки, которые не ставят мод заново, а обновляют его, столкнутся с проблемой, что на тех кольцах, которые у них уже есть, будет работать старый скрипт. Я проверяю так: у меня есть сохранение со старым кольцом. Я изменил кольцо, в старом сохранении изменения не работают. Но стоит подобрать то же самое кольцо, но которого не существовало в сохранении, то оно работает как надо. Сама игра кольца не различает и складывает их в инвентаре в одну позицию - кольцо 2 шт. В редакторе это тоже одно и то же кольцо, но вот сохранённый и не сохранённый экземпляры работают по-разному :( Конечно, я могу объяснять игрокам, что им следует заменить кольца, но правильнее было бы избавить игрока от этой проблемы :)
Да, смена имени скрипта не помогает.

Holtof55, экипировка персонажей содержится в списке одежды Outfit персонажа. Его можно менять заклинаниями или скриптами.  Если заменить на специально сделанный пустой Outfit, то все шмотки переходят в инвентарь персонажа, но он может их оставить одетыми на себя. Так что надо ещё и оттуда всё забирать. Потом всё возвращать. Хлопот много, а стоит ли того задача? Помимо этого учти, что одёжка персонажей (у драугров точно) и не одёжка вовсе, а просто их тело. Чтобы раздеть такого персонажа ему надо сделать новое голое тело, которого в игре нет.

Dsion  Offline  Сообщение №1358 написано: 27 января 2015, 13:15



Сам скрипт должен обновляться. Ивенты и функции должны срабатывать уже новые. Но вот OnInit(), если изменен, заново уже не вызовется. А с чего бы ему вызываться? И значение уже заполненных Property не изменится.
Можно было с самого-самого начала проектировать мод с учетом возможности обновления...

anton  Offline  Сообщение №1359 написано: 27 января 2015, 13:18



362
Myprism, можно в техническом квесте по событию OnPlayerGameLoad() проверять инвентарь ГГ, и если там уже будут наши кольца - удалить их оттуда.

Мой Блог
Myprism  Offline  Сообщение №1360 написано: 27 января 2015, 13:27


Физик


anton, удалить - не проблема. Игрок сам выкинет или продаст.

Dsion, там всего два события - equip и unequip, но вот свойство одно добавлено. Обработка старых свойств сохранилась, а вот новое работает только у нового экземпляра кольца. Предвидеть обновления невозможно, особенно такие. Теперь кольцо у меня не занимает слота, не имеет ArmorAddon и рисуется как ArtObject. Это даёт ему вид ещё и от первого лица. Вообще, если предвидятся обновления, то и мод не надо выкладывать, пока эти обновления не будут сделаны :)

Dsion  Offline  Сообщение №1361 написано: 27 января 2015, 13:43



Я когда-то таки придумал систему, позволяющую (теоретически) избежать проблем при обновлении. Но тогда уже особо не делал моды и так её и не проверил.
Там смысл в полном отсутствии OnInit() где-либо и отсутствии Property в том виде, в котором мы к ним привыкли.

Multigone  Offline  Сообщение №1362 написано: 29 января 2015, 18:20 | Отредактировано: Multigone - 29 января 2015, 19:20



832
Кто-нибудь знает, как измерить угол Х поверхности, на которой стоит игрок, с учетом направления его взгляда по оси Z?

Myprism, по поводу события OnDying (возможно, и OnDeath тоже?) - при завершении маг. эффекта с архетипом SummonCreature по времени это событие должно срабатывать (возможно, и под действием Banish тоже). Вот почему нужна проверка уровня здоровья, т.к. в ванильной игре взрыв должен происходить только при гибели атронаха от действий источников, снижающих AV Health.

Но простого условия Target.GetAV("Health") <= 0.0 недостаточно, т.к. при добивании в ближнем бою с помощью KillMove это условие не сработает (атронах погибнет с уровнем здоровья больше нуля). Конечно, ванильные атронахи не имеют анимаций добивания их игроком, речь о призванных существах с наличием таких анимаций (призванный огненный взрывающийся питомец, например). Поэтому нужно использовать:



Это к слову о том, зачем там проверка уровня здоровья.

По поводу шлемов: разве нельзя вместо периодической проверки "оружие взято в руки" отслеживать анимацию Draw \ Sheatle с помощью RegisterForAnimationEvent(ObjectReference akSender, string asEventName)?

Во-вторых, необязательно для каждого шлема создавать отдельный скрипт. Достаточно одного скрипта на алиасе игрока и 2х FormList (можно вообще одного) с открытыми и закрытыми версиями. При экипировании к-л. открытой формы из первого листа находится его позиция Х и устанавливается соответствующая закрытая форма из второго. Можно и наоборот.

Dsion, дай угадаю: отсутствие Property подразумевает присутствие FormList (тоже Property, но уже одно-единственное)? Все равно, Property нужны для обмена переменными между скриптами, верно? Как минимум - текстовыми переменными и переменными форм, а числовые можно передавать через глобальные.

Myprism  Offline  Сообщение №1363 написано: 29 января 2015, 22:32


Физик


Multigone, я просто написал новый скрипт, в котором у события EVENT onDeath(actor myKiller) нет никаких проверок. Ведь мне не нужно обрабатывать смерть призванных атронахов. Всё работает как нужно.

Насчёт шлемов: @perture сделал анимацию забрала и она хорошо работает не только для вида от третьего лица, но даже от первого. Забрало поднимается и опускается закрывая лицо.

Multigone  Offline  Сообщение №1364 написано: 30 января 2015, 00:05 | Отредактировано: Multigone - 30 января 2015, 00:06



832
Myprism, ну так ты вопросил же следующее...

Цитата Myprism

Зачем там проверяется:
atronachHealth = selfRef.GetAV("Health") as int
if atronachHealth > 0 ?



... я и ответил.

Myprism  Offline  Сообщение №1365 написано: 30 января 2015, 05:38


Физик


Multigone, ты ответил совершенно понятно. Твой ответ рассеял мои сомнения по поводу этого скрипта и всё мне объяснил. Я же ведь до этого не был уверен что меняю его правильно. Спасибо!

А это RegisterForAnimationEvent(ObjectReference akSender, string asEventName) я пока использовать не умею :(

W@nTeD  Offline  Сообщение №1366 написано: 31 января 2015, 23:26


l3g3nD@rY cR3@tuR3


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

Тема по Hammer Editor
Myprism  Offline  Сообщение №1367 написано: 1 февраля 2015, 01:13


Физик


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

W@nTeD  Offline  Сообщение №1368 написано: 1 февраля 2015, 01:34


l3g3nD@rY cR3@tuR3


Myprism, Это я знаю, проблема в том, что я незнаю, как примерно должен выглядеть скрипт! Изначально у него стоит бандитская фракция (которая по моему вообще не враждует с игроком) и нейтральное отношение!

Тема по Hammer Editor
Myprism  Offline  Сообщение №1369 написано: 1 февраля 2015, 08:27 | Отредактировано: Myprism - 1 февраля 2015, 08:38


Физик


W@nTeD, я не гожусь в учителя скриптописания. На этот язык нет нормального описания как, скажем, на Паскаль, поэтому я всё делаю там методом тыка и по ванильным образцам.
Вот фрагмент кода из моего квеста, который меняет и фракцию и отношение к игроку:

Alias_Victim00.GetActorReference().SetFactionRank(CurrentFollowerFaction, -1)
Alias_Victim00.GetActorReference().SetRelationshipRank(Game.GetPlayer(), 4)
Alias_Victim00.GetActorReference().AddToFaction(PlayerFaction)


Это строки из квеста и тут используются Алиасы (псевдонимы) персонажа.
Вот полный код моего заклинания развода:


Вроде, этого должно хватить, чтобы сварганить своё заклинание :)

Добавлено (01 Февраля 2015, 11:27)
---------------------------------------------
Цитата @perture

Действие кольца можно периодически освежать с помощью RegisterForSingleUpdate. Освежаться будет как при загрузке сейва так и при переходе между локациями. Да и во всех прочих случаях.

Похоже, это то, что нужно.
В руководстве нашёл вот такой пример:


Я понял это так: Событие OnUpdate этого скрипта назначается как событие обновления этого объекта и это обновление происходит каждые 2 секунды до тех пор, пока не выполнится условие. После этого назначение снимается. Дальше событие OnUpdate переключается в рамки State active, где оно ничего не делает. Возникает вопрос, зачем нужно UnregisterForUpdate(), если потом переходит переключение в пустой Event OnUpdate?
Вопрос возникает потому, что мне нужно поставить это для кольца, которое одевается и снимается. Т.е. мне надо правильно начать процесс и правильно его закончить.

1. Может мне использовать RegisterForUpdate при одевании кольца вместо RegisterForSingleUpdate? Тогда не нужно указывать интервала обновления.
2. При снимании кольца, видимо, надо выполнить UnregisterForUpdate()?
3. Нужно ли оставлять пустой State active и переключать в него в моём случае?

Сейчас на кольце висит вот такой скрипт:


@perture  Offline  Сообщение №1370 написано: 1 февраля 2015, 09:05


$cience innov@tor


MyprismRegisterForSingleUpdate используется в скриптах расширяющих ActiveMagicEffect Script, Alias Script и Form Script. Эта функция регистрирует однократное обновление события, и рекомендуется использовать его, а не RegisterForUpdate везде где возможно. Смысл в том, что если в какой-то непредвиденной ситуации не отработает UnregisterForUpdate, то получим зависший цикл. Интервал обновления указывается в обеих функциях.

При снимании кольца надо выполнить Unregister.

State active вообще не понятен в данном случае. Я бы сделал как то так

Код
ScriptName MyScript Extends ActiveMagicEffect

Event OnEffectStart(Actor akTarget, Actor akCaster)
       Тело скрипта
       RegisterForSingleUpdate(1.0)
EndEvent

Event OnUpdate()
       Тело скрипта
       RegisterForSingleUpdate(1.0)
EndEvent

Event OnEffectFinish(Actor akTarget, Actor akCaster)
       UnregisterForUpdate()
EndEvent

"Не спорьте с идиотами! Вы опуститесь до их уровня, а там они вас задавят своим опытом!" ©
Myprism  Offline  Сообщение №1371 написано: 1 февраля 2015, 09:34


Физик


@perture, спасибо!

Dsion  Offline  Сообщение №1372 написано: 1 февраля 2015, 09:41 | Отредактировано: Dsion - 1 февраля 2015, 09:50



Цитата W@nTeD

после диалога враждебным


В диалоге есть поле для скрипта "End:".
Можно просто всписать туда
akSpeaker.StartCombat(Game.GetPlayer())
Тогда NPC договорит свою фразу и набросится на игрока. Но не станет врагом игрока перманентно.

Если NPC должен стать врагом навсегда, можно всписать такое:
akSpeaker.SetRelationshipRank(Game.GetPlayer(), -4)
NPC станет врагом игрока. Но будет ли он на игрока набрасываться - зависит от характеристики Aggression. Если Aggression == 0, то не будет. Если Aggression == 1, будет набрасываться на врагов. Если Aggression == 2, то (тут я не уверен) будет набрасываться на всех не-союзников.

Aggression можно задвать в настройках Actor'а или изменять в том же скрипте:
akSpeaker.SetActorValue("Aggression", 1)

@perture  Offline  Сообщение №1373 написано: 1 февраля 2015, 10:01


$cience innov@tor


Myprism, в своем скрипте оставляй только

Event OnEquipped(Actor akActor)
akActor.AddSpell(RingVisibility, false)
endEvent

Event OnUnequipped(Actor akActor)
akActor.RemoveSpell(RingVisibility)
endEvent


остальное переноси в другой скрипт, который будет висеть на маг. эффекте, добавляемом спеллом RingVisibility. Ну а там по вышеприведенному примеру. В событии OnUpdate() будет осуществляться проверка экипировки, и если что-то слетело, то поправляться. И при каждой проверке будет регистрироваться следующая разовая проверка.

"Не спорьте с идиотами! Вы опуститесь до их уровня, а там они вас задавят своим опытом!" ©
Multigone  Offline  Сообщение №1374 написано: 1 февраля 2015, 15:16



832
Цитата @perture

Event OnEffectFinish(Actor akTarget, Actor akCaster)
    UnregisterForUpdate()
EndEvent

Это можно не писать.

@perture  Offline  Сообщение №1375 написано: 1 февраля 2015, 15:22


$cience innov@tor


Event OnEffectFinish(Actor akTarget, Actor akCaster)
     Тело скрипта
EndEvent

Наверное правильнее будет так. Регистрация обновления в принципе автоматически отменится, а в теле скрипта будет сниматься экипировка.

"Не спорьте с идиотами! Вы опуститесь до их уровня, а там они вас задавят своим опытом!" ©
Myprism  Offline  Сообщение №1376 написано: 1 февраля 2015, 16:11 | Отредактировано: Myprism - 1 февраля 2015, 16:13


Физик


Multigone@perture, а почему надо разбивать на два скрипта? Может, можно так:

?
в OnUpdate я проверяю только не слетел ли скин и оутфит.
Компилятор не ругается и в игре работает. Конечно, для уверенности надо тестировать долго (до респавна) и с чистого сохранения, это будет позже.

@perture  Offline  Сообщение №1377 написано: 1 февраля 2015, 17:35


$cience innov@tor


Myprism, в вики сказано

Код
Member of: ActiveMagicEffect Script, Alias Script, and Form Script

Registers this form/alias/magic effect for a single update event.


Не известно, как апдейт в объект_референсе работает. Надо по дебаггеру смотреть. Ты в Event OnUpdate() внеси вывод сообщения, и смотри в логе.

"Не спорьте с идиотами! Вы опуститесь до их уровня, а там они вас задавят своим опытом!" ©
Multigone  Offline  Сообщение №1378 написано: 1 февраля 2015, 21:53



832
@perture, все события из Form.psc будут работать в любых скриптах, т.к. Form является высшей ступенью в иерархии скриптовых объектов.

@perture  Offline  Сообщение №1379 написано: 2 февраля 2015, 05:37


$cience innov@tor


Multigone, не спорю, я в скриптописании не силен, однако в таком контексте лог выводит следующее:

Код
[02/02/2015 - 08:34:18AM] Error: Unable to call RegisterForSingleUpdate - no native object bound to the script object, or object is of incorrect type
stack:
                [Item 5 in container  (00000014)].aaa.RegisterForSingleUpdate() - "<native>" Line ?
                [Item 5 in container  (00000014)].aaa.OnEquipped() - "aaa.psc" Line 5

Скрипт чисто для лога. Скомпилировался без ошибок.


Код
Scriptname aaa extends ObjectReference

Event OnEquipped(Actor akActor)

           RegisterForSingleUpdate(2.0)

endEvent

Event OnUpdate()

           Debug.Trace("It's work!")
           RegisterForSingleUpdate(2.0)

EndEvent

"Не спорьте с идиотами! Вы опуститесь до их уровня, а там они вас задавят своим опытом!" ©
Myprism  Offline  Сообщение №1380 написано: 2 февраля 2015, 11:24


Физик


Значит, не работает :(

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





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