• Прежде, чем задать вопрос, пожалуйста, убедитесь, что такой вопрос не задавался раньше. Старайтесь описать суть вопроса как можно подробней. • Прежде, чем опубликовать ответ на вопрос, пожалуйста, убедитесь, что обладаете необходимыми для этого знаниями. Старайтесь cформулировать суть ответа как можно лаконичней. • При желании ответить в приватном порядке, пожалуйста, воспользуйтесь ЛС. • При желании поблагодарить ответившего, пожалуйста, воспользуйтесь кнопкой "+" полезного сообщения.
Сообщения, не относящиеся к вопросам по скриптам Papyrus, ответам на них или уточнениям, являются оффтопом и могут быть удалены.
Красное солнце Есть вопросы по скриптам Papyrus? Пиши не в ЛС, а в эту тему.
Dsion, забавно, сколько времени был уверен, что Dispel() не работает (сто раз проверял), сейчас завел СК - заработало, ***. Кое-что придется переписывать, избавляться от DispelSpell и Property.
Dsion, какое узкое применение у этого диспела, однако. Я уж обрадовался сколько пользы от него будет, а оно вот как... Как же тогда убрать один эффект, по завершении другого, если время заранее неизвестно? DispelSpell же сразу все эффекты рубит
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №2373
написано: 7 февраля 2017, 17:54
| Отредактировано: Dsion - 7 февраля 2017, 17:38
Многие не понимают один важный аспект скриптов, а я не знаю, как это описать без четырех страниц текста...
1. Все скрипты в Скайриме - это почти то же самое, что классы в С++. Создание папирусового скрипта с именем "SluttyActor" равноценно объявлению класса SluttyActor в С++.
2. Все классы(скрипты) могут быть типом переменной (или проперти), таким же как int и float. Но в С++ мы можем в любом месте создать экземпляр любого класса: SluttyActor a; , а в папирусе таким образом мы можем создать только простые переменные (int и float). Экземпляры всех остальных классов могут существовать только связанными с каким-то реальным объектом в мире игры.
3. Actor, ObjectReference, Spell итп - мы можем создавать проперти этих типов только потому, что в Data/Scripts/Source у нас лежат скрипты Actor.psc, ObjectReference.psc, Spell.psc итп.
4. Как в С++ классы могут наследовать друг друга, так и в папирусе скрипты могут наследовать друг друга. Например, класс Actor (живой объект в мире) наследует класс ObjectReference (любой объект в мире). Это означает, что любой Actor - это всегда и ObjectReference тоже. На Actor всегда можно вызвать любую функцию, которую можно вызвать на ObjectReference. Актора можно передать аргументом в функцию, которая просит ObjectReference итп. Но Actor еще и расширяет ObjectReference, добавляя новые функции. Актор - это всегда ObjectReference, но ObjectReference - не всегда Актор.
5. И самое главное. Это не совсем правильно, но так будет легче понять. Попробуйте не отделять в сознании скрипт от какой-то вазы, на которой он висит. Представьте, что скрипт - это есть ваза, а ваза - это есть скрипт. Не называйте скрипт "СкриптНаВазе", а назовите его "УлучшеннаяВаза". И с этого момента можете думать об "УлучшеннаяВаза" точно так же, как вы думаете об "Actor". А почему нет? Точно такой же класс. Точно так же, как и Actor, наследует и расширяет ObjectReference. Вы теперь можете создать проперти с типом УлучшеннаяВаза. Или написать функцию, которая будет принимать аргументом именно улучшенную вазу. Ну и еще всякое...
Multigone, если ты вдруг это всё читал... То (AAA as BBB) - это не обращение к скрипту BBB на объекте AAA... А это называется type cast или приведением типов... Мы как-бы говорим "Вот у меня есть объект типа AAA, но я точно знаю, что это объект типа BBB. Так что заглохни, компилятор, и дай мне работать с ним как с BBB.". В папирусе это безопасно, но в том же Си или С++ надо быть осторожным...
Добавлено (07 Февраля 2017, 20:54) --------------------------------------------- PitrPokir, а как получилось, что время действия не известно? Мало ты информации подогнал
Dsion, речь все о тех же призраках. При подчинении призрака игроку добавляется пустой эффект, который висит в активных эффектах и позволяет понять, что призрак еще на его стороне и сколько их вообще. И естественно, эффект должен спадать вместе с эффектом подчинения, а поскольку он длится 999 дней, то ориентироваться надо по смерти призрака. А когда это будет - неизвестно)
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №2375
написано: 7 февраля 2017, 20:03
| Отредактировано: Multigone - 7 февраля 2017, 21:00
Dsion, всегда думал, что self - это объект, а скрипт расширяет форму, а не является ей. Ну да ладно, я-то C++ не изучал. Про cast знаю - float as string всегда, а string as float иногда. В любом случае, спасибо за стену текста.)
PitrPokir, если эффект нужно снять извне (не из его скрипта), то DispelSpell. Или наложить другой эффект с флагом Dispel и ключ. словами. Первый снимает все копии всех эффектов этого заклинания, второй способ может снять копии только одного из эффектов заклинания, но требует ключ. слов.
Чтобы точно знать ID каждой копии эффекта (для применения Dispel()), можно использовать массив где-нибудь в квесте, который будет заполняться при старте каждого отдельного эффекта, при условии, что они накладываются только на одного актера и не строго одновременно.
А, в этом случае хватит и одной переменной. Скрипт на эффекте призрака будет примерно таким:
spell property mymenuspell auto myquestscript property s auto activemagiceffect x
event oneffectstart(actor t, actor c) mymenuspell.cast(game.getplayer()) int ic = 3000 while !s.q && ic utility.wait(0.001) ic -= 1 endwhile if s.q x = s.q s.q = none endif endevent
event oneffectfinish(actor t, actor c) ; x.dispel() endevent
PitrPokir, ну сам смотри... Лично я пока не вижу смысла вешать на игрока эффект... Через квест, на котором алиасы и основной скрипт, всегда можно узнать, сколько у игрока в подчинении призраков и их референсы. Вешать эффект на призрака (кроме abGhostAbility) тоже пока смысла не вижу... Но, может, он (смысл) и есть. Ты же не всё рассказываешь. Ладно-ладно, не моё дело.
Multigone, вот это танцы с бубнами Я даже не до конца понимаю что к чему. Но за код спасибо, попробую
Dsion, да нет, все так, как я сказал. Просто попытка сделать заклинание внешне похожим на дефолтные призыв и оживление. Что бы если у меня были оживленные трупы, то призраки были с ними наравне в списке эффектов и я мог сразу определить их наличие и количество. В общем косметический эффект, так сказать. Может в дальнейшем захочется как-то улучшить эффект, что бы он более ощутимую пользу или вред заклинателю приносил, но пока что так. Но меня больше удивило то, что диспел не работал, ведь были на него планы. Т.е. он работает, но в описании как-то коряво объяснили его принцип
Товарищи, такой вопрос. Как отследить событие, не могу сообразить... Надо отследить событие, когда применяется зелье и определить, является ли это ядом? Не надо же, наверно, на каждое зелье навешивать скрипт, должно быть какое-то общее решение.
kelamor, можно через OnMagicEffectApply, как подсказывает PitrPokir, или onhit. Но лучше через OnObjectEquipped(Form akBaseObject, ObjectReference akReference), он срабатывает один раз при использовании зелья, а не все свободное время, пока на игроке есть хоть один долговременный маг. эффект.
PitrPokir, так это же важно! Лучше об этом бы и подумал! Варианта, как минимум, два: 1. Вешаем скриптик на алиас с ивентом OnDeath. Когда ивент срабатывает, скрипт сразу отключает и удаляет референс. А потом еще и очищает алиас. Таким же способом можно сделать ограничение времени действия. При создании призрака - заказ OnUpdate. А в OnUpdate - отключение, удаление, очистка. 2. Не очищаем алиас сразу после смерти. Но для функции поиска пустого алиаса алиас с мертвым НИП будет считаться пустым. Опять же, надо не забыть отключить и удалить труп.
Ну и еще дофига вариантов можно придумать. Придумать нормальную систему работы с алиасами - это же самое важное для тебя.
AlexeyVN, ругается потому, GetEquippedWeapon() возвращает Weapon, а ты пытаешься к нему применить функцию, предназначенную для ObjectReference.
Используя SKSE:
Код
Scriptname _TESTTEST30 extends objectReference
bool function CheckTempering(bool rightHand = true, float hold = 1.6) actor a = Game.GetPlayer() if a.GetEquippedWeapon(!rightHand) return wornobject.GetItemHealthPercent(a, rightHand as int, 0) < hold endif endfunction
; rightHand: ; false - левая / обе ; true - правая / обе
; примеры: ; If CheckTempering(true, 1.5) == true ; проверяем оружие в правой на заточку 1.5. ; Debug.MessageBox("Оружие можно улучшить") ; Else ; Debug.MessageBox("Оружие максимально улучшено") ; или оружия нет в указанной руке. ; EndIf
; If CheckTempering()
Upd. 18:28
Изменение репутации для пользователя PitrPokir
PitrPokirOffline
Сообщение №2385
написано: 12 февраля 2017, 23:46
| Отредактировано: PitrPokir - 12 февраля 2017, 23:55
Dsion, а если вешать скрипт на алиас с ивентом OnDeath, то как сделать, что бы конкретно данный алиас очищал себя? "SELF.GetReference().Clear()"? Прост у меня не менее 20ти алиасов, для каждого делать индивидуальный скрипт как-то жирно получается. И не будет ли OnUpdate оказывать сильное влияние на производительность? Ну относительно сильное. Допустим, если засунуть в ивент цикл на проверку смерти и очищать. Хотя первый вариант получше, если его можно реализовать.
P.S. а почему важно отключать и удалять трупы? В игре же по дефолту они остаются после битв и прочего. Если речь о том, что бы именно призрак исчезал, то я добавил дефолтный скрипт по превращению в "остатки призрака", а если применять отключение и удаление, то остатки тоже исчезают.
Добавлено (13 Февраля 2017, 00:09) --------------------------------------------- Проверил вариант с OnDeath, вроде исправно работает при помощи "SELF.Clear()".
Добавлено (13 Февраля 2017, 02:46) --------------------------------------------- Что-то я немного застрял с заполнением алиаса. В чем может быть ошибка? (Оставил строчки имеющие отношение к циклу)
Alias[] Property AliasArray Auto ReferenceAlias Property NecroFollowerAlias Auto
Bool Slave = false Int Num Alias aElement
Event OnEffectStart(Actor Target, Actor Caster)
Num = AliasArray.Length While Num > 0 Num -= 1 aElement = AliasArray [Num]if (aElement.ForceRefIfEmpty(Ghost) == true) Slave = true Num = 0 endif EndWhile
(25,15): ForceRefIfEmpty is not a function or does not exist (25,38): cannot compare a none to a bool (cast missing or types unrelated)
P.S. Если переменную aElement объявить как ReferenceAlias или прописать её в свойствах, то ошибка:"type mismatch while assigning to a referencealias (cast missing or types unrelated)"
P.P.S. что странно, вне цикла на конкретном алиасе NecroFollowerAlias условие if работает как надо. Я так понял, дело в переменной aElement, но что именно с ней не так?
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №2386
написано: 13 февраля 2017, 10:56
| Отредактировано: Multigone - 13 февраля 2017, 10:58
Int Num = AliasArray.Length While Num > 0 Num -= 1 if AliasArray[Num].ForceRefIfEmpty(Ghost) CurrentFilled = AliasArray[Num]; Slave = true Num = 0 endif EndWhile
Изменение репутации для пользователя Хисимэль
ХисимэльOffline
Сообщение №2387
написано: 14 февраля 2017, 08:48
| Отредактировано: gangrena1972 - 14 февраля 2017, 08:50
Все получается, только он тормозит с переходом от пакета песочницы к пакету следования. Причина, думаю, в следующем:
У Сераны на пакете песочницы (DLC1NPCSandboxAroundPlayer600) стоит условие PlayerSettled_var. Соответственно, в скрипте на квесте - Bool property PlayerSettled auto conditional Dsion объяснил, что это что-то вроде постоянной перепроверки пакетов.
Подскажите, пожалуйста, откуда и как эта переменная запускается?
Я смотрел квест, из которого она меняется. Точно название не помню, но там в нем есть слова "monitoring" и "dlc1". Каждую секунду выполняется необоснованно сложная и длинная функция, определяющая, "осел" ли игрок... Если результат определения изменяется, то и переменная изменяется, и выполняется EvaluatePackage()... Я бы эту функцию не копировал, о чем и сообщил гангрене в приват... А вот EvaluatePackage() каждую секунду действительно могло бы помочь.
Dsion, тогда это DLC1NPCMonitoringPlayer. Ну, там каждую секунду проверяется, прошел ли игрок за 8 предыдущих секунд 150 юнитов. И да, есть лишние телодвижения, такие, как смещение всего массива на одну ячейку.
Всем привет нужно реализовать следующие задачи при помощи скриптов или чего то ещё, вопрос:
1. Нужен скрипт для книги который бы запрещал выкидывать книгу выбранную из инвентаря. книга квестовая не знаю как сделать при помощи алиосов что бы книга не выкидывалась, помогите.
2. Нужна смена стадий если в инвентаре появляется какой то определенной предмет, и если его нет в инвентаре что бы менялась стадия на исходную.
Multigone, я бы просто для интереса попробовал какой-то бред типа... Ну создать новый предмет с именем "Усил.", а потом делать String NewName = RefName1 + RefName2 Но у меня SKSE вообще нету.
Изменение репутации для пользователя AlexeyVN
AlexeyVNOffline
Сообщение №2398
написано: 24 февраля 2017, 05:57
| Отредактировано: AlexeyVN - 24 февраля 2017, 06:13
Здравствуйте, друзья! Не подскажите, каким образом можно отследить переход состояния объекта Enable\Disable? События на такое изменения я, увы, не нашел.