gangrena1972, нужно еще галочку "Start Game Enabled" _убрать_ с первой страницы настроек квеста. Лично я немного другой скрипт использую, но пофиг... Вообще, подойдет любой вариант, при котором квест запускается не по галочке "Start Game Enabled", а каким-то другим способом. Хоть скриптом, хоть по ивенту, хоть из консоли.
gangrena1972, вариантов много, честно говоря... Самое простое, как чувак уже сказал, - это сделать твой квест запущенным *всегда*, но на диалоги повесить условие GetStageDone (завершена стадия другого квеста) или GetQuestCompleted. Тогда диалоги появятся только после завершения другого квеста (или его стадии).
По Change Location Event тоже можно. Но тогда важно не забыть про SM Event Node. Условия - те же.
Можно подпилить ванильный квест, чтоб он в своем конце запускал твой квест. Но так не делай! Лучше избежать редактирования ванильных записей, если это возможно. Ну я эту возможность только для того и упоминаю, чтоб убедиться, что ты так не сделаешь.
Ну и можно еще десяток вариантов со скриптами придумать, если описанные выше не подойдут.
Подведем итоги: после завершения какой-либо стадии какого-либо ванильного квеста должен становиться доступен диалог на определенное время? И желательно иметь возможность создавать таких диалогов побольше, не вынося каждый в отдельный квест? Убил босса - обсудил с компаньоном, стал вампиром - обсудил итп...? Уфф.. Надо почесать репу...
Добавлено (11 Января 2017, 12:40) --------------------------------------------- Да, чо-то идеями меня не засыпало... Не припоминаю, чтоб игра где-то сохраняла конкретное время завершения стадий квестов. И не припоминаю никакого ивента типа "игрок завершил стадию квеста". И кондишна "игрок завершил стадию квеста в последние 15 минут" тоже нифига не припоминаю. В ванильных квестах временные диалоги чаще всего делается условиями типа "игрок завершил стадию 1, но не завершил стадию 2". Но это не совсем то... На одной стадии ведь можно на недели застрять...
Единственное, что пока приходил в голову - это адский скрипт... Поскольку нормальных подходящих ивентов нету, скрипт должен выполняться каждые несколько секунд... Проверять по списку все указанные стадии всех указанных квестов. Если какая-то изменила состояние на завршенное, сохранить время и на 15 минут установить скриптовую conditional переменную, активировав этим диалог... Ну да, работать-то оно будет, но что-то я не в восторге от идеи выполнять ресурсоемкую функцию каждые несколько секунд.
Добавлено (11 Января 2017, 12:47) --------------------------------------------- Ну еще другой вариант. Можно сделать, чтоб по завершении какой-либо стадии ванильного квеста, компаньон сам начинал беседу. То есть, сам подходил и начинал диалог о произошедшем событии. Или просто произносил что-то типа "ух ты, мы его замочили", не вступая в диалог. Такое не сложно... Не подойдет?
Его id: t02 Вот в нем есть стадия 40. Задание на этой стадии: Talk to Calcelmo (поговорить с Кансельмо).
А на свой квест можешь повесить либо условие: GetStageDone t02 40 == 1 это будет означать, что игрок поговорил с Кансельмо. Либо GetStage t02 >= 40 Будет означать, что игрок либо на этой стадии, либо уже продвинулся дальше. Ну или что-то в таком духе...
Добавлено (11 Января 2017, 14:30) --------------------------------------------- Если никто не придумает, как сделать ограничение именно по времени, то я напишу подробнее, как сделать, чтоб НИП сами подходили. И чтоб только один раз говорили свой текст.
gangrena1972, ну ладно, есть вариант. Могу выложить маленький скриптик. Он запустит твой квест когда завершится какой-то другой. А через 15 минут игрового времени остановит твой квест. Все диалоги будут доступны только 15 минут (пока квест работает). Это то, чего ты хочешь? Уверена, что подойдет? Подумай вот о чем: 1. А если ты захочешь таких диалогов много сделать? Не создавать же для каждого отдельный квест. 2. А если захочешь сделать обсуждение не *завершения* квеста, а какого-то события в его процессе? Завершения какой-то стадии. Если тебя это всё не смущает, то без проблем... Выложу скрипт. Я придумал, к чему подцепиться, чтоб избежать повторения кода каждые пару секунд.
Добавлено (11 Января 2017, 17:20) --------------------------------------------- Посмотрел, как сделан ванильный квест Темного Братства. Брр. С самого начала и до конца игры каждые 5 секунд реального времени выполняется массивный блок кода. В нем каждые 5 секунд проверяется, завершил ли игрок квест на убийство Грелод и еще дофига условий. Если все выполняются, запускается квест на похищение игрока Астрид. Жуть... Ну, короче, это именно тот способ с "адским скриптом", который я назвал сомнительным. Но, справедливости ради, стоит сказать, что способ очень гибкий... Если захочешь, чтоб диалог был доступен ровно 15 минут после того, как игрок проедет возле какого-то дерева в глухом лесу именно 5 раз и только если в третий раз игрок проезжал мимо него без шлема, то скрипт позволяет такое сделать. Возможно, так и надо делать... В конце концов, чего стоит компьютеру выполнить десяток операций раз в 5 секунд, если он может выполнять их три миллиарда в секунду?
gangrena1972, ладно, сдаюсь, не знаю. Если ты действительно делаешь компаньона, то выполнять задачу в том виде, в котором ты её поставила, - не вариант. Во-первых, должна быть возможность реагировать на смену стадии, а не на завершение. Во-вторых, должна быть возможность объединять много диалогов в один квест. В третьих... Ну ты же понимаешь, что 15 минут игрового времени - это меньше минуты реального времени. А если игрок не догадается поговорить со спутником за эту минуту? Твой текст и озвучка навсегда пропадут? Такое вот...
Была идея очень-очень близкая, соответствующая всем требованиям. Но и от неё пришлось отказаться потому что всё идет крахом, если спутник не был рядом в момент завершения квеста/стадии. Отсчет 15 минут начинается только тогда, когда игрок и спутник встречаются... Не то, в общем. Но вариант был крутой. Можно было легко и быстро в одном квесте создавать реплики двух видов: 1. Свершается какое-то событие (любое) и компаньон его комментирует, не вступая в диалог. На этом всё. 2. Свершается какое-то событие, компаньон его комментирует и предлагает обсудить. Ну или просто говорит что-то типа "можно тебя на минутку?". После этого начинается отсчет времени. Если игрок подойдет к компаньону в течении 15 минут, можно будет обсудить что-то там.
Круто же? И легко... Вот только правильно оно работает только если компаньон рядом... А если он торчал дома, то скажет свою реплику аж тогда, когда игрок вернется домой. Даже если уже год прошел с момента свершения события. Но твоя изначальная идея тоже не учитывает возможность того, что компаньон остался дома.
Короче, сдаюсь. Надо как-то отлавливать изменение стадий разных квестов и сохранять время этого изменения. Да и еще и только тогда, когда компаньон был рядом (участвовал). Не знаю, как это сдеать без регулярно повторяющегось скрипта. Удачи коллегам.
PitrPokir, не видел ничего такого. По-моему, только через перк. Хотя перком можно управлять из скрипта в какой-то мере. Можно сделать, чтоб какая-то глобальная переменная указывала максимальное количество призванных существ. Из скриптов или из консоли переменную можно было бы менять, а в перке штук 10 энтри поинтов такого типа: 1. Установить макс. количество существ в 1, если значение переменной == 1 2. Установить макс. количество существ в 2, если значение переменной == 2 итп
gangrena1972, сказал же, что сдаюсь. Если кто-то придумает нормальный способ, будет круто. По поводу скрипта я там налажал чуток Я был уверен, что событие OnTrackedStatsEvent срабатывает при изменении числа пройденных квестов (должно бы), а оно не срабатывает... Не вышло к нему прицепиться.
Смекаешь, в чем проблема? Нет способа поймать момент, когда игрок завершает квест или какую-то его стадию. Нет подходяшего события. Вот событие "игрок сменил локацию" есть. Событие "игрок замочил кого-то" тоже есть. Даже событие "игрок надел предмет" есть. И еще дофига всего есть. А поймать завершение квеста - не знаю, как.
Остается только вариант с повторением кода каждые несколько секунд. Вот тогда можно поймать момент, когда квест переходит с состояния "не завершен" в состояние "завершен".
Есть еще диалоги типа Hello. Это то, что НИП говорят при заданных условиях когда игрок рядом с ними. И на таких диалогах можно поставить галочку Say Once - сказать только один раз. Представь, что ты делаешь такой диалог. Условие: завершен какой-то квест. Спутник рядом с тобой. Ты завершаешь квест, условие начинает выполняться, спутник говорит свою фразу и всё хорошо, да? Больше он её не повторит. А теперь представь, что игрок завершил этот квест давным давно. Когда еще мод с твоим спутником даже не был подключен. Ну а что? Условия-то выполняется. Он все-равно скажет эту фразу, когда вы встретитесь. Вот всё и разрушилось.
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №999
| Тема: Вопросы по скриптам Papyrus
написано: 13 января 2017, 05:10
| Отредактировано: Dsion - 13 января 2017, 05:14
PitrPokir, можешь оставить ванильные лимиты как есть, а свою нежить вызывать не магическим эффектом "summon creature", а скриптовой командой. И тогда извращайся как хочешь... Пока ты своих саммонов скриптовой же командой не удалишь, никуда они не денутся. Ну только придется с актором поработать: сделать им пакет для следования за игроком, сделать им скриптик для самоуничтожения по таймеру итп. Если будешь так делать, не забудь перепроверить трижды, что референсы правильно удаляются. Или можно заранее создать штук 30 референсов скелетов, а потом с ними работать. Когда надо призывать: reset, enable, moveto; а когда он умирает или истекает время: disable. Такой вариант чуть надежнее потому что с ним ты точно не налажаешь и сейвгейм не начнет забиваться неудаленными референсами.
Добавлено (13 Января 2017, 13:26) --------------------------------------------- Есть еще идея, но вряд ли ты захочешь снова читать пол страницы непонятных терминов.
gangrena1972, лично я про книгу вообще ничего не понял. Что именно, по твоей задумке, должно запустить квест2? Прочтение книги или еще что-то? Если прочтение книги и книга не ванильная, лучше на неё повесить скрипт для запуска квеста2. Вообще, раз ты таким занимаешься, нужно обязательно научиться пользоваться дебажными командами... В первую очередь: консольная команда sqv <имя квеста> показывает статус квеста (запущен ли, стадия) и переменные на нем. Проверь, запущен ли твой второй квест. Если запущен до прочтения книги - почему? и еше скриптовая команда Debug.MessageBox("Text") Debug.MessageBox(variable) выводит из скрипта на экран окошко с тектом или переменной. Полезно, чтоб узнать, сработал ли какой-то кусочек скрипта и какие там переменные.
Ну тогда в конец первого квеста - запуск второго. А на книгу - скрипт, который изменит стадию второго квеста, если тот запущен. А на диалоги и пакеты - проверку стадии.
Добавлено (14 Января 2017, 13:08) --------------------------------------------- Чертов CK... Уже ж всё круто было, всё работало. А тут вдруг оказалось, что "Say once" на диалогах сбрасывается после перезагрузки игры. Ну какого черта?!
Я не знаю, как тебе надо и откуда вообще берется книга. Думал что-то такого типа: 1. Игрок завершает квест1 и квест1 на последней стадии запускает квест2. 2. Квест2 запускается с, допустим, стадии 10. Появляется задание "прочтите книгу" (или ничего не появляется). 3. Если игрок читает книгу, квест2 переходит на стадию 20. Появляется задание "помедитируйте над прочитанным" (или, опять же, не появляется)
4. В квесте2 алиас. В алиасе - NPC. На алиасе пакет ForceGreet. На пакете условие типа GetStage quest2 == 20. На диалоге, возможно, такое же надо. Когда квест переходит на стадию 20, пакет включается, NPC подходит к игроку.
5. Когда NPC поговорит с игроком, квест переходит на стадию 30 (скрипт на диалоге). Появляется задание "к вам подошел мутный мужик и сказал, что вы ему не нравитесь". Всё, после этого пакет уже не актуален и NPC идет дальше по своим делам.
Вот в таком контексте скрипт на книге должен быть что-то типа (не проверял):
Код
Quest Property Quest2 Auto
Event OnRead() If (Quest2.GetStage() == 10) Quest2.SetStage(20); EndIf EndEvent
А что, ты от книги таки не отказалась? Ну сдвинуть стадию способ один стандартный: из скрипта через метод SetStage(10). Абсолютно из любого скрипта в любом месте. Можно из первого квеста сразу установить второй в стадию 10. А можно сделать, чтоб второй сам при запуске переходил в стадию 10. Можно еще попробовать на стадии 10 второго квеста поставить галочку start up stage - тогда она должна выполняться при старте квеста сама... Такое
Не забывай еще про консольные команды: startquest <имя квеста> stopquest <имя квеста> setstage <имя квеста> <стадия>
не обязательно реально выполнять задания, чтоб запустить второй квест или переключить стадию. Можешь зайти в игру и сразу установить стадию квеста в то значение, когда должен подойти NPC. И посмотреть, подойдет ли.
Не, вообще не так Уфф... Скрипт неправильный и понятие "пакет, привязанный к книге" тоже не правильное... И лично мне совсем не охота писать гайды по основам создания модов.. Бывает, накатаешь для кого-то объяснений на целую страницу, а они прочитают первые две строчки, испугаются сложности и всё. Не обижайся, в общем. Можем общаться где-то в интерактивном режиме... Так я хоть сразу почувствую, когда ты сдашься и забьешь. Или кто-то другой, может, напишет инструкцию... Ждем
Стандартная система спутников действительно завязана на стандартных голосах... Ну варианты такие: 1. Допиливать стандартный квест, управляющий спутниками. Добавлять новые топик инфо для уникального голоса. Вариант фиговый потому что редактируется важный ванильный квест. 2. Добавить твой уникальный голос в список (FormList) голосов спутников. Вроде, он называется VoicesFollowersNeutral. Недостаток тот же - редактируется ванильный список. Хотя вряд ли много модов его редактируют, но всё-равно... 3. Сделать отдельный квест, но зависящий от стандартного. То есть, надо будет создать квест, топики, инфо, озвучить их, но на этом всё. В остальном (скрипты, пакеты, алиасы) будет использоваться стандартный квест. Это не сложно. 4. Сделать полностью независимый новый квест. Вариант офигенно гибкий. Позволит не только голос добавить, но и переработать AI при желании. Вон Серана, к примеру, так отличается от остальных ванильных спутников потому, что у неё свой личный квест. Это всё тоже не сложно.. Ну ладно, для новичка, может, и сложно. Хотя не сильно.
gangrena1972, через ванильный квест не сложно делать. Надо просто из твоих топиков вызывать функции на скрипте ванильного квеста. Там по одной строчке в топики вставишь и будет работать... Если будешь в скайпе, я расскажу подробнее...
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1008
| Тема: Вопросы по скриптам Papyrus
написано: 16 января 2017, 16:35
| Отредактировано: Dsion - 16 января 2017, 16:36
Ой, это я такое написал? Жуть какая. Если надо отследить крафт, попробуй использовать Story Manager Event. Посмотри в SM Event Node. Ну или еще что-то. Но точно не такой скрипт
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1009
| Тема: Вопросы по скриптам Papyrus
написано: 16 января 2017, 16:46
| Отредактировано: Multigone - 23 апреля 2020, 09:38
Ага, можно-можно. Там можно и референс предмета получить, и референс "стола", на котором он создан. На референсе стола можно ключевые слова проверять.
Посмотрел. Там вообще-то скрипт не такой, как ты скопировал А я то думал "неужели я забыл сделать проверку того, на что именно садится игрок". Оказывается, не забыл)
Квест ты создал, да? Алиас игрок в квесте тоже создал? Скрипт на алиас повесил? И не работает? Добавь в Event OnSit строчку типа: Debug.MessageBox("sit") Сначала узнаем, срабатывает ли ивент, когда игрок садится за точильный камень. Можешь еще на обычный стул сесть - должно точно срабатывать.
Когда квест запускается таким ивентом, на скрипте квеста сработает Event OnStoryCraftItem(ObjectReference akBench, Location akLocation, Form akCreatedItem) ну да, базовый объект только, не референс...
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1011
| Тема: Вопросы по скриптам Papyrus
написано: 17 января 2017, 14:00
| Отредактировано: Dsion - 17 января 2017, 14:01
Если нужно, чтоб метался именно тот щит, что на игроке, то есть проблема с получением его id. Мне только два ваианта решения приходят на ум: 1. Сделать один уникальный щит и игрок сможет метать только его. 2. Помечать щит при взятии его из мира. Но щит должен именно валяться где-то. А если попал к игроку другим способом, то придется выбросить и взять заново. Не очень, да? Ну это единственная проблема. Остальное - легко.
А ты в курсе, что щит можно зафутболить куда-то и без прожектила, взрыва, активатора и прочей ерунды? Можно его "реально" бросить. Сначала разместить у игрока на уровне рук, а потом хорошенько пнуть в направлении взгляда игрока. Вот это было бы весело... А с прожектилом - так себе...
Ну есть еще вариант, при котором мы выбрасываем из инвентаря игрока такой же щит, какой на нем надет, и ловим референс выброшенного предмета. Но если у игрока в инвентаре есть еще один щит с таким же базовым объектом, может вылететь не тот.
Добавлено (18 Января 2017, 20:05) --------------------------------------------- Давай, лучше, зафигарим "Молот Тора". Уникальный. Который можно будет метать. И чтоб бандиты ВООЩЕ НАФИГ ОТЛЕТАЛИ при ударе. А после броска, чтоб он летел обратно к хозяину. Круто же? Я, правда, прямо так сходу не в курсе, как определить, в кого он попал...
PitrPokir, давай с начала: 1. Ты уверен, что второй эффект накладывается именно на труп? А первый - именно на игрока? 2. Если на первый эффект (реанимация) повесить условия типа "subject isdead", то на ком оно будут проверяться: на игроке или на цели? 3. Если на второй эффект повесить условия, на ком они будут проверяться?
Тебе ведь нельзя просто поднять трупак и удалить у него пыль. На эффекте поднятия должна быть проверка, что у трупа есть пыль. И если пыли нету, эффект не должен срабатывать, да? Как ты это сделал?
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1017
| Тема: Вопросы по скриптам Papyrus
написано: 20 января 2017, 12:31
| Отредактировано: Dsion - 20 января 2017, 12:37
- нельзя вызвать GetItemCount() без аргумента (объект) - нельзя вызвать HasKeyword() на типе "целое число" - нелогично выполнять >= 1 на булевой переменной
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1018
| Тема: Вопросы по скриптам Papyrus
написано: 20 января 2017, 12:47
| Отредактировано: Dsion - 20 января 2017, 12:49
AlexeyVN, Lexo тоже нормально придумал. GetItemCount, если верить creationkit.com, поддерживает и простые базовые объекты, и формлисты, и кейворды. Так что действительно можно было бы повесить на маски уникальный кейворд, а потом выполнять:
Код
GetItemCount(someKeyword) > 0
Ну и еще дофига вариантов было... А когда без длинной строки реально никак, её можно красиво разделить символом "\". Как-то так:
Код
If (\ True || \ True || \ True || \ True\ )
Debug.Notification("1"); EndIf
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1019
| Тема: Вопросы по скриптам Papyrus
написано: 20 января 2017, 13:07
| Отредактировано: Multigone - 23 апреля 2020, 09:28
По идее это событие должно срабатывать каждый раз, когда что-то попадает игроку в инвентарь, а akSourceContainer - откуда (из какого контейнера) оно попадает к игроку. Если akSourceContainer действительно работает, можно при помощи каста или кейворда проверить, что это NPC, что он жив и не является спутником игрока. Нет, это всё фигня, если подумать... Будет ложно срабатывает даже если игрок просто берет подарок у НИП... Можно добавить проверку, что игрок в режиме скрытности.. Но все-равно не надежно...
2. Сделать перк, перехватывающий активацию NPC в режиме скрытности, устанавливающий переменную типа "игрокГрабитТого-то", выполнять настоящую активацию, очищать переменную. А в ивенте OnItemAdded проверять эту переменную. В принципе, такое работало бы, но: 1) сложновато 2) будет ложное срабатываение, если игрок откроет воровство, а потом откроет консоль и добавит что-то себе...
А нормального варианта не знаю
Если объект уникальный или квестовый, то кражу легко отследить. Проблемы только с отслеживанием любой кражи.
Изменение репутации для пользователя Dsion
DsionOffline
Сообщение №1020
| Тема: Вопросы по скриптам Papyrus
написано: 20 января 2017, 16:09
| Отредактировано: Dsion - 20 января 2017, 16:31
Да что-то не стало намного проще Скрины не отображаются, а скрипты нет смысла читать, пока не будет ясно, на кого вешается эффект. Можешь временно заменить скрипты на первом и втором эффекте на вот такие:
только во втором "1 " заменить на "2 ". После этого хоть станет ясно, на кого накладываются эффекты. Вернее, с какими аргументами вызывается oneffectstart,
Добавлено (20 Января 2017, 19:09) --------------------------------------------- Ну если ты точно уверен (без предложенной проверки), что: 1. Скрипт первого эффекта срабатывает с taget=игрок и caster=игрок 2. Скрипт второго эффекта срабатывает с target=труп и caster=игрок 3. При проверке условий на всех эффектах subject=труп. то никаких проблем. Условия на эффектах нужны одинаковые. Проверка мертвости, проверка наличия пыли, проверки пригодности к реанимированию, проверка того, не реанимирован ли он уже. А скрипт только на второй эффект: akTarget.RemoveItem(NecroRiseIngr, 1) и всё... Просекаешь, да? Только тогда, когда цель реально валяется мертвая и без дела (и с пылью), тогда оба эффекта срабатывают (всегда только вместе). Один реанимирует, а втрой - удаляет пыль.