Вверх Вниз


  • Страница 97 из 97
  • «
  • 1
  • 2
  • 95
  • 96
  • 97
Модератор форума: Kris†a™  
Форум » TES V: Skyrim » Мастерская » Вопросы по скриптам Papyrus (О скриптах Papyrus (Skyrim). Скриптеры не проходите мимо!)
Вопросы по скриптам Papyrus
sansuli  Offline Сообщение №1 написано: 31 Августа 2012 в 17:29 | Отредактировано: sansuli - Пятница, 17 Апреля 2015, 21:08


The Red Sun


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

Красное солнце
Есть вопросы по скриптам Papyrus? Пиши не в ЛС, а в эту тему.
Myprism  Offline Сообщение №2881 написано: 06 Декабря 2018 в 07:43


Физик


1463
Aksyonov, у меня нет проблемы определять, находится ли персонаж в интерьере. Вот скрипт, который я повесил на персонажа:

Код
Scriptname aa_ChangeLocation extends Actor

Armor property HairItem auto

Event OnLocationChange(Location akOldLoc, Location akNewLoc)
     if (Game.GetPlayer().GetCurrentLocation() == akNewLoc) && !(Game.GetPlayer().IsInInterior())    ; Если главный герой в той же локации и если она не интерьер
        AddItem(HairItem)                ; Добавляем новые
        EquipItem(HairItem, true)        ; Устанавливаем новые
        RegisterForSingleUpdate(3.0)    ; Ждём 3 секунды
    endIf
endEvent

Event OnUpdate()
        RemoveItem(HairItem)            ; Удаляем новые волосы
endEvent

И он прекрасно работает.
Мне нужен скрипт для ПРЕДМЕТА. Тех же волос или плаща, находящегося в левельных списках и оутфитах очень многих персонажей. Нужно чтобы при инициализации предмета или при переходе главного героя в данную локацию, все плащи там стали Disable, а через 3 секунды - Enable. Дело в том, что многочисленные мои варианты (не привожу примера, так как никакой не работает :( )тут не работают. Тут есть какая-то фишка, которую я не понимаю. Вот другой пример её: создаю я кольцо со скриптом. Всё отлично работает. Дальше кладу 6 колец в сундук в интерьере - в игре кольца больше не работают. Одно кольцо, лежащее на полу - работает, 6 в сундуке - не работают. А вот если в сундук положить левельный список, в котором уже лежат 6 колец (но не 6 сразу вместе, а отдельно, 6 раз по одному) - то всё работает отлично. Тут есть какая-то фишка с тем, как Скайрим выделяет память под переменные однотипных объектов.

Добавлено (06 Декабря 2018, 08:28)
---------------------------------------------
Я попробую по чётче обрисовать свою задачу.
При переходе Главного Героя в некоторую локацию, она начинает загружать все свои объекты. Мне нужно, чтобы небольшая часть объектов (одежда с физикой на персонажах локации) грузилась не сразу, а спустя 3 секунды после начала загрузки локации. Внимание, задерживаться должны не персонажи с физикой (не поможет), а только некоторые их шмотки.


andrelo-1  Offline Сообщение №2882 написано: 06 Декабря 2018 в 11:19



148
Myprism, есть такая skse-шная функция ArmorAddon::SetModelPath(), может ее как-то можно использовать.

Myprism  Offline Сообщение №2883 написано: 06 Декабря 2018 в 11:56


Физик


1463
andrelo-1, спасибо за наводку. Очень полезные функция:
string Function SetModelPath(string path, bool firstPerson, bool female) native
Открывает большие возможности.
Но моя проблема не в этом, а куда прикрутить её или что-то другое. Мне не удаётся подобрать для шмотки событие в котором я мог бы её менять. У меня тупо ничего не делает даже вот такой код:
Код
Scriptname aa_ChangeLocationObj extends ObjectReference

Event OnEquipped(Actor akActor)
    Delete()
endEvent

Года четыре как не занимался скриптами, из головы всё вылетело, туплю страшно.

Dsion  Offline Сообщение №2884 написано: 06 Декабря 2018 в 12:37



1234
Myprism, мне тоже ничего в голову не приходит...
Ну можно повесить на вещи зачарование с постоянным эффектом. Тогда будет возможно отслеживать момент загрузки актора. Но это как-то не изящно.
Можно дать всем расам умение с постоянным эффектом (или там где-то есть фишка, позволяющая дать умение всем акторам).
Можно заставить вещь проверять состояние (загружен/не загружен) актора-носителя каждые несколько секунд. Эти варианты не только не изящны, но еще и создадут дополнительную нагрузку.
В общем, одни кривые костыли... А меня от костылей уже тошнит...
Я теперь либо делаю красиво, либо не делаю вообще... Если проблему нельзя исправить "по-нормальному" (средствами nifskope итп.), то я бы вообще забил...

andrelo-1  Offline Сообщение №2885 написано: 06 Декабря 2018 в 12:50



148
Myprism, можно например составить список всех вещей, у которых надо отключать физику, и при смене локации просто по этому списку менять модель. Иногда будет конечно много лишней работы, особенно если в локации нет ни у кого нужных вещей. Но все же...

Myprism  Offline Сообщение №2886 написано: 06 Декабря 2018 в 13:50


Физик


1463
Друзья, вы меня утешили. Я наверное, всё же не совсем тупой, а просто задача, которую я поставил, действительно не решается. Дело в том, что у надетой шмотки совсем нет событий! Меня ввело в заблуждение то, что шмотки это как бы ObjectReference. Да, пока их не надели. И даже OnЕquipped это событие ещё не надетой шмотки. И смена слота у надетой шмотки тоже не происходит. Так что, есть только один путь - через Актора.
Dsion, постоянное заклятие это не такое уж и плохое решение.  Во-первых, так работает вся обувь на высоком каблуке и это проблем не вызывает. Во-вторых это открывает возможность создавать плащи (особенно актуально) и причёски с физикой, которые совсем не занимают слотов. Если шмотка привязана только к одной кости, то её можно рисовать магическим эффектом. При этом сам объект к которому привязан магический эффект не показывается, а эффект рисуется. А скелеты у плащей и причёсок с физикой обычно свои и привязаны только к одной из костей обычного скелета. Одна беда, пока занимался только телами и бронёй, совсем забыл (да и знал то не очень) магические эффекты...
А вообще, когда приходится изобретать такие костыли, то это верный признак того, что путь выбран не тот. Ведь главная причина в дефекте физики. И заключается он в том, что если скелет объекта с физикой грузится одновременно со скелетом персонажа, то, похоже, объект с физикой инициализируется не на персонаже, а в центре локации и потом физика старается (иногда тщетно) это исправить. Ведь плащи и причёски всегда вытянуты к центру локации, а вероятность глюка тем больше, чем больше локация.
andrelo-1, идея новая для меня, надо хорошенько её обдумать.

andrelo-1  Offline Сообщение №2887 написано: 06 Декабря 2018 в 17:40



148
Идеальное решение конечно это исправить плагин физики, для него даже исходники где-то есть :) .

@perture  Offline Сообщение №2888 написано: 06 Декабря 2018 в 18:43 | Отредактировано: @perture - Четверг, 06 Декабря 2018, 19:23


$cience innov@tor


1495
Myprism, привет!

Цитата Myprism ()
Дело в том, что у надетой шмотки совсем нет событий!
Если помнишь, я когда то делал урок по анимированному шлему. Так вот, в том случае шлем отслеживал все ивенты персонажа. Сам я сейчас уже плохо помню подробности, но может поднять ту тему?

Цитата andrelo-1 ()
Идеальное решение конечно это исправить плагин физики, для него даже исходники где-то есть
Согласен, идеальное. Сам бы таким путем и пошел.

"Не спорьте с идиотами! Вы опуститесь до их уровня, а там они вас задавят своим опытом!" ©
Myprism  Offline Сообщение №2889 написано: 07 Декабря 2018 в 06:49 | Отредактировано: Myprism - Пятница, 07 Декабря 2018, 06:51


Физик


1463
@perture, Точно! Там на персонажа вешается заклятие (заклятие видимости забрала). Заклятие на персонажа вешает шмотка, а уже у заклятия полно событий и доступ к чему угодно. Так же работают и высокие сапоги. Я сейчас пробую так сделать для укрощения плащей. Кстати, это ещё позволяет сделать плащи не занимающие слотов, так как их видимость может быть обеспечена заклятием.
Кстати, у меня та же проблема, спустя некоторое время уже не помню, как делал ту или иную вещь :( А так как приходится переключаться между очень многими областями программирования, то случается это частенько :(
Цитата @perture ()
Сам бы таким путем и пошел.
Вынужден сам себе запрещать такие решения :( Достаточно посмотреть на размер DLL-ки и тот факт, что её писали на Си (я на нем не писал), чтобы понять, что времени на это уйдёт много. Для меня то это не проблема, я легко в это нырну и даже получу от этого удовольствие, но тогда модов от меня уже долго никто не увидит :( И так уже у меня возникло опасение, что из-за того, что я программирую в слишком большом количестве разных областей, а переключение между ними не очень лёгкое, то процесс создания модов перестаёт быть сходящимся :)

Добавлено (12 Декабря 2018, 21:17)
---------------------------------------------
1. Скажите, пожалуйста, переменные какого уровня сохраняются в скрипте при сохранении и загрузке игры? Наверное, переменные объявленные внутри функции или события не сохраняются. А те, что объявлены в скрипте вне функций и событий?

2. Есть ли способ отследить внутри скрипта extends ActiveMagicEffect событие загрузки игры? Или выхода из игры?


Dsion  Offline Сообщение №2890 написано: 13 Декабря 2018 в 01:08 | Отредактировано: Dsion - Четверг, 13 Декабря 2018, 01:08



1234
Myprism, да, вроде, всё сохраняется... Вход/Выход/Загрузка не должны никак мешать работе скриптов...
Но я бы все-равно не использовал функцию utility.wait()... Это просто воще не круто...

andrelo-1  Offline Сообщение №2891 написано: 13 Декабря 2018 в 16:04



148
Цитата Myprism ()
1. Скажите, пожалуйста, переменные какого уровня сохраняются в скрипте при сохранении и загрузке игры? Наверное, переменные объявленные внутри функции или события не сохраняются. А те, что объявлены в скрипте вне функций и событий?
2. Есть ли способ отследить внутри скрипта extends ActiveMagicEffect событие загрузки игры? Или выхода из игры?
1. Мне тоже кажется, что все переменные сохраняются.
2. OnPlayerLoadGame, если эффект висит на игроке. Выход вроде никак не отследить.

Myprism  Offline Сообщение №2892 написано: 13 Декабря 2018 в 19:34


Физик


1463
andrelo-1, Увы, эффект визит не на игроке, а на других персонажах. :(

Добавлено (13 Декабря 2018, 19:46)
---------------------------------------------
Ещё появились вопросы.
Вот объявляю я в скрипте переменную:
Armor Armor31
Присваиваю ей значение:
Armor31 = (NPC.GetWornForm(0x00000002) as armor)
Дальше меняю свою переменную:
Armor31.SetSlotMask(0x00000800)    ; 41
И обнаруживаю, что соответствующая шмотка на персонаже поменяла свои слоты. Таким образом, знак присваивания означает, что присваивается указатель на объект. А как получить копию объекта?


andrelo-1  Offline Сообщение №2893 написано: 13 Декабря 2018 в 20:08 | Отредактировано: andrelo-1 - Четверг, 13 Декабря 2018, 20:09



148
Myprism, SetSlotMask меняет слоты сразу у всех арморов данного типа.

Myprism  Offline Сообщение №2894 написано: 13 Декабря 2018 в 20:26


Физик


1463
andrelo-1, а это точно? Ведь базовый объект не вызывался...

Добавлено (13 Декабря 2018, 20:28)
---------------------------------------------
А ведь это объясняет непредсказуемое поведение моего скрипта... :(

Добавлено (16 Декабря 2018, 15:59)
---------------------------------------------
Загадки папируса. (Или игры).
Долго я возился над скриптом, задерживающим появление шмоток с физикой через заклятие. Большой получился, хоть и работает. Но не люблю я таких громоздких решений. Тогда отложил его и написал очень простой скрипт, который вешается прямо на шмотку:

Код
Scriptname _HDTPhysics extends ObjectReference

Event OnEquipped(Actor akActor)
    if (akActor != Game.GetPlayer()) ;&&  !(akActor.IsInInterior())
        Armor NPCItem = (Self.GetBaseObject() as armor)
        akActor.UnEquipItem(NPCItem)    
        Utility.Wait(3.0)
        akActor.EquipItem(NPCItem)    
    endif
endEvent
Не бейте ногами за Utility.Wait(3.0). У надетой шмотки нет никаких событий кроме OnEquipped и OnUnEquipped. Не обрабатывает она и событие OnUpdate. И не ругается на событие, но код в нём никакой не работает.
Но даже с этим маленьким кодом возникли непонятки. Если я брошу такую шмотку на пол в интерьере, то она прекрасно работает в соответствии со скриптом. Но если я дам эту шмотку персонажу в оутфит, а в игре заберу эту шмотку, она не работает. Т.е. не пропадает на 3 секунды при надевании. Вот есть 2 шмотки. Одну с пола подобрал, другую с трупа. В моём инвентаре они выглядят идентично. Точнее сливаются в одну с цифрой 2. Но если их выбросить на землю, а потом надеть по-отдельности на персонажа-спутника, то одна шмотка работает, другая - нет. Почему???

Dsion  Offline Сообщение №2895 написано: 16 Декабря 2018 в 19:25



1234
Myprism, круто придумал. А я и забыл, что в момент загрузки все NPC "надевают" вещи из своих аутфитов.
Но лично у меня вот такое:

Код
Scriptname MTESTScript extends ObjectReference  

Armor Property Armor1 Auto;

Event OnEquipped(Actor akActor)

    Debug.MessageBox("UnEq");
    Utility.Wait(1.0);
    akActor.UnequipItem(Armor1);

    Utility.Wait(3.0);

    Debug.MessageBox("Eq");
    akActor.EquipItem(Armor1);

EndEvent

Работает нормально. NPC, у которых такая вещь в аутфите, перенадевают её во время загрузки локации. А если такого NPC убить, забрать вещь и надеть на спутника, тот сразу перенадевает её.
И хреново, конечно, у вещи нет референс id. Ни зарегистрировать её, ни даже Self использовать нельзя.

Myprism  Offline Сообщение №2896 написано: 16 Декабря 2018 в 23:22


Физик


1463
Я сначала написал большой и сложный скрипт, который вешается на заклятие (а оно вешается на персонажа шмоткой) и отслеживает видимость персонажа главным героем. (Работает хорошо, кстати). А в процессе отладки понавешал на все события мессаджей. Вот тут и увидел, что персонаж переодевается, причём делает это только при выходе из интерьера на открытое пространство (как раз, где надо). При переходе из интерьера в интерьер переодевания нет.
Принципиальное отличие твоего скрипта в том, что ты саму шмотку в свойство определил. Скорее всего в этом и причина, что у тебя скрипт работает всюду. Скорее всего, свойству референс id выделяется.
Ещё, скажи, пожалуйста, зачем нужна первая задержка в 1 секунду?
То, что у меня не работает, если шмотка берётся с трупа, скорее всего, связано с тем, что шмотке не выделяется референс id. Если она лежит в игре на полу - то это просто объект и референс id у него быть обязан. Такой глюк у меня был пару лет назад с кольцами. Я тогда повесил скрипт на кольцо, отладил его и всё работало великолепно, пока мне не понадобилось положить кольца в сундук. Кольца извлечённые из сундука не работали категорически. Тогда проблему удалось решить так - я положил все кольца в левельный список, но не 6 вместе, а 6 раз по одному. А этот левельный список бросил в сундук. В этот раз я попытался сделать тоже со шмоткой, положить её в отдельный левельный список, увы, в этот раз не помогло.

Добавлено (17 Декабря 2018, 06:37)
---------------------------------------------
Да, а от самоопределения шмотки
Armor NPCItem = (Self.GetBaseObject() as armor)
ты отказался потому, что не работал Self? Дело в том, что для шмотки на земле он работает! Значит, он не работает только для шмотки из инвентаря.


Dsion  Offline Сообщение №2897 написано: 17 Декабря 2018 в 21:20



1234
Цитата Myprism ()
ты отказался потому, что не работал Self?

Ага!

Myprism  Offline Сообщение №2898 написано: 18 Декабря 2018 в 10:40


Физик


1463
Dsion, тут получается очень интересная вещь. Пока скрипт висит только на одной шмотке без референс-id, то всё работает нормально. Но если повесить на 2 разные шмотки из тех, что есть у персонажа, то обе они запускают один и тот же скрипт с ОБЩИМИ локальными переменными. Т.е. скрипты на таких шмотках не являются разными объектами, а только одним.
Я усложнил скрипт и встроил туда защиту от случаев срабатывания, когда шмотка переодевается самим скриптом. В принципе, событие onEquip не вызывается в том случае, если надевание данного объекта произошло именно скриптом (или консолью). Но оно может произойти во время действия скрипта по другим причинам, например, скрипт трогает другую шмотку, которая уже вызывает переодевание нашей. Получилось так:
Код
Scriptname _DelayOnEquip extends ObjectReference

Armor  Property EmptyItem = none     Auto    ; Замещающая шмотка
int       Property ItemSlot = 53         Auto    ; Слот занимаемый задерживаемой шмоткой
float    Property Delay = 3.0         Auto    ; Задержка появления, с десятичной частью

Bool     SenderisScript = false

Event OnEquipped(Actor akActor)
    if !SenderisScript && (akActor != Game.GetPlayer()) && !(akActor.IsInInterior())
        SenderisScript = true
        Armor NPCItem = (akActor.GetWornForm(Armor.GetMaskForSlot(ItemSlot)) as armor)    
        If EmptyItem
            akActor.AddItem(EmptyItem)        ; Добавляем замещающую шмотку в инвентарь
            akActor.EquipItem(EmptyItem, true)    ; Надеваем шмотку
        else
            akActor.UnEquipItem(NPCItem, true)    
        endif
        Utility.Wait(Delay)
        If EmptyItem
            akActor.RemoveItem(EmptyItem)    ; Удаляем замещающую шмотку
        endif
        akActor.EquipItem(NPCItem)    
        Utility.Wait(0.2)
        SenderisScript = false
    endif
endEvent
Пока шмотка с таким скриптом у персонажа одна, всё работает отлично. Но если их две, то сработает только одна, так как у них окажется одна общая переменная SenderisScript. После того, как скрипт запустится один раз, код в событии не работает второй раз пока не закончится его выполнение. Т.е. пропадать на 3 секунды будет только одна шмотка из двух. В принципе, сегодня утром я придумал, как это обойти. У меня может быть только 4 разных слота, на которых может стоять проблемная физика. Тогда в скрипте должно быть 4 разных SenderisScript для каждого номера слота и 4 фрагмента кода, работающих для четырёх условий. Получается рекурсивное использование одного скрипта. Задача зацепила меня. Не важностью для моего мода, а просто как интересная задача :) Но пока отложу её. Я сейчас заканчиваю большой мод и у меня там уже есть скрипт, который более-менее спасает от такой проблемы с физикой. Так что, сначала выложу, а потом вернусь к этому орешку :)

miyo  Offline Сообщение №2899 написано: 06 Февраля 2019 в 20:53 | Отредактировано: miyo - Среда, 06 Февраля 2019, 20:59


Странник


4
Здравствуйте, сейчас делаю мод на торговца животными-спутниками и столкнулся с такой проблемой. Квестовый скрипт выглядит так:
Код
Scriptname FalmerNuadarSystemScript extends Quest  

GlobalVariable Property FrostSpiderCostF Auto
MiscObject Property Gold Auto
Quest Property pDialogueFollower Auto

Function BuyAnimal(Actor AnimalTrainer)

   Game.GetPlayer().RemoveItem(Gold, FrostSpiderCostF.value as int)   
   AnimalTrainer.GetLinkedRef().SetActorOwner(Game.GetPlayer().GetActorBase())
   ;AnimalTrainer.SetActorValue("Variable04", 1)
   (pDialogueFollower as DialogueFollowerScript).SetAnimal(AnimalTrainer.GetLinkedRef())

EndFunction


Когда Property были только  прописаны в Source без добавления в Properties, после покупки питомца c диалогом было всё в порядке, только не снимались деньги у главного героя, а как только добавил в Properties деньги стали сниматься при покупке, но перестал активироваться диалог у купленного питомца

Dsion  Offline Сообщение №2900 написано: 06 Февраля 2019 в 21:21 | Отредактировано: Dsion - Среда, 06 Февраля 2019, 21:32



1234
miyo, можешь глянуть вывод

Код
sqv DialogueFollower


до и после покупки питомца... Если REF Animal меняется с None на ID зверька, то скрипт нормально отрабатывает и проблема не в этом скрипте и не в проперти на нем...

Правда, там немного неправильно извлекается значение глобальной переменной и я вообще не понимаю, зачем там глобальная переменная, но черт с ним, если работает.
Если у тебя несколько торговцев и они продают разных питомцев, то скрипт правильнее будет сделать один на всех... Ну, то есть, никакого упоминания конкретных торговцев и конкретных питомцев в скрипте. Можешь вешать скрипт на самих торговцев, а питомец и его цена будут задаваться в проперти.

Добавлено (06 Февраля 2019, 21:23)
---------------------------------------------
С не заполненным проперти pDialogueFollower скрипт точно не мог нормально работать и делать питомца твоим спутником...

Добавлено (06 Февраля 2019, 21:29)
---------------------------------------------
Если всё проходит как надо и паучара попадает в алиас квеста DialogueFollower, то вряд ли ты сможешь сказать ему "стой тут" или "идем за мной", если не менял квест DialogueFollower. Там есть ответы только для человеческих голосов и для собачьего голоса. Для паучьего - нету :)

Как по мне, будет намного лучше вообще забить на квест DialogueFollower и сделать свой с нуля. Там не сложно.
Тогда не придется менять ванильный DialogueFollower, не придется ломать совместимость с другими модами на спутников итп.

miyo  Offline Сообщение №2901 написано: 06 Февраля 2019 в 23:31


Странник


4
Dsion, да, похоже проблема в этом скрипте тоже есть, результаты команды sqv DialogueFollower до покупки и после одинаковы 

Форум » TES V: Skyrim » Мастерская » Вопросы по скриптам Papyrus (О скриптах Papyrus (Skyrim). Скриптеры не проходите мимо!)
  • Страница 97 из 97
  • «
  • 1
  • 2
  • 95
  • 96
  • 97
Поиск: