yakor77, в сохранении есть несколько переменных с именем Level, возможно, хранящих значения текущего и фактического уровней (например, CurrentLevel_var, LastLevel_var). Сам алгоритм повышения уровня, скорее всего, находится в недрах Skyrim.exe. Т.е., каких-то посредников в Settings / GlobalVariable, похоже, нет. Значит, узнавать и устанавливать значения этих переменных мы не можем - предотвратить появление меню повышения атрибутов тоже. Копание в levelupmenu.swf тоже, скорее всего, ничего не даст, поскольку алгоритм ждет ответа от окна повышения атрибутов. Проверь, если знаешь как. Управление кнопками вместо игрока, чтобы быстро прощелкивать меню, тоже не получится, т.к. выбор и активацию кнопок MessageBox'а нельзя производить клавиатурой, только мышью.
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №932
| Тема: Вопросы по скриптам Papyrus
написано: 6 июля 2020, 18:29
| Отредактировано: Multigone - 6 июля 2020, 18:46
Ezalor, ну, если при перемещении предмета в инвентарь игрока текущая задача квеста должна быть завершена, и при условии, что CompleteAllObjectives() завершает только отображенные сейчас задачи (эт я не знаю), то вот:
Код
Scriptname _TESTTEST61 Extends ObjectReference ; На базовую форму или референс предмета.
Quest Property MyQuest Auto ; Заполнить своим квестом.
EVENT OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer) IF akNewContainer == Game.GetPlayer() GoToState("Stopped") ; Для базовой формы перевод в пустое состояние, предотвращающее повторные срабатывания события, может не работать. MyQuest.CompleteAllObjectives() ENDIF ENDEVENT
STATE Stopped EVENT OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer) ENDEVENT ENDSTATE
Вариант, если это квестовый предмет и он принадлежит этому же квесту:
Код
Scriptname _TESTTEST61 Extends ReferenceAlias ; На алиас предмета.
Ezalor, STATE дает возможность создавать несколько версий событий или функций. В одном скрипте может быть множество STATE с произвольными именами. GoToState() переводит скрипт в указанное. По умолчанию любой скрипт стартует в пустом STATE (объявлять это состояние не нужно, перевод в него осуществляется так: GoToState(""), события и функции в пустом состоянии являются основными и работают всегда, если в текущем-не-пустом состоянии нет их версий). Чтобы исключить к.-л. событие из работы, нужно в текущем-не-пустом состоянии указать такое же событие, в котором ничего нет). Без команды скрипт состояние не меняет. Состояние записывается в сохранении.
Пример:
Код
; Пустое состояние по умолчанию.
EVENT MyEvent_1() ; Код 1. ENDEVENT
EVENT MyEvent_2() ; Код 2. ENDEVENT
FUNCTION MyFun_1() ; Код 3. ENDFUNCTION
FUNCTION MyFun_2() ; Код 4. ENDFUNCTION
; В этом состоянии будут работать MyEvent_2 (Код 2), MyFun_1 (Код 3), MyFun_2 (Код 4), MyEvent_1 (Код 10) STATE MyState_1 EVENT MyEvent_1() ; Код 10. ENDEVENT ENDSTATE
; В этом состоянии будут работать MyEvent_2 (Код 2), MyFun_2 (Код 4), MyEvent_1 (пусто), MyFun_1 (пусто) STATE MyState_2 EVENT MyEvent_1() ENDEVENT
FUNCTION MyFun_1() ENDFUNCTION ENDSTATE
; В этом состоянии будут работать MyEvent_1 (Код 1), MyEvent_2 (Код 2), MyEvent_3 (Код 5), MyFun_1 (Код 3), MyFun_2 (Код 4) STATE MyState_3 EVENT MyEvent_3() ; Код 5. ENDEVENT ENDSTATE
; В этом состоянии будет работать все из пустого, при входе в это состояние сработает код 6, при выходе из него сработает код 7. STATE MyState_4 EVENT OnBeginState() ; Код 6. ENDEVENT
EVENT OnEndState() ; Код 7. ENDEVENT ENDSTATE
; Auto переводит скрипт в это состояние при старте скрипта. STATE MyState_5 Auto ENDSTATE
Событие OnUpdate() имеет баг, поэтому его можно использовать только в пустом состоянии. Если его надо использовать в нескольких состояниях, делать так:
Код
EVENT OnUpdate() MyFun_3() ENDEVENT
FUNCTION MyFun_3() ; Код 100. ENDFUNCTION
STATE MyState_101 FUNCTION MyFun_3() ; Код 101. ENDFUNCTION ENDSTATE
STATE MyState_102 FUNCTION MyFun_3() ; Код 102. ENDFUNCTION ENDSTATE
Функции, объявляемые в скрипте, прежде всего должны иметь версию в пустом состоянии, и опционально - в других, но не наоборот.
Вместо состояний можно пользоваться переменными, чтобы определять пути выполнения кода, это более гибкий способ, но и более громоздкий / ресурсоемкий.
Код
Int iSwitch = 0
EVENT OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer) IF iSwitch == 0 iSwitch = 1 ; Код 1 ELSEIF iSwitch == 1 iSwitch = 2 ; Код 2 ELSEIF iSwitch == 2 iSwitch = 3 ; Код 3 ELSE iSwitch = 0 ; Код 4 ENDIF ENDEVENT
Ezalor, добавь Debug.MessageBox("Текст") в нужные строки и посмотри результат.
myav,
1) Area < 15 в игре не работает.
2) Эффект Self с действием по площади работает только для других целей, но не для источника. Если нужно и для источника, в заклинании должно быть 2 эффекта: Self - Area и Self без Area.
3) Area в СК не всегда включается с первого раза (т.е. все вроде как сделано, но в игре нет). Попробуй так: после того, как эффект настроен и добавлен в заклинание, сними флаг AutoCalculate, сохрани, поставь, сохрани.
и цель заклинания (delivery) не "self" а "on target". Или ты про что-то другое говоришь ?
Там в русифицированной версии есть несколько "на цель", тогда как в англ. все четко и понятно. К тому же ты пишешь "кастует на себя спел". Ну ладно, неважно, в любом случае, п.2) относится не только к Self, а вообще к любому типу доставки, включая Target Actor (я прост подзабыл, ща проверил). Переделывай. Не забудь про п.3).
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №938
| Тема: Вопросы по скриптам Papyrus
написано: 25 августа 2020, 12:59
| Отредактировано: Multigone - 27 августа 2020, 11:37
nepewka, если это неизвестные эффекты, то никак. Если это твой эффект, при старте даешь актеру неигровой предмет, при финише удаляешь его. Кол-во предметов у актера в опред. момент времени равно кол-ву навешенных на него эффектов. Если несколько актеров в один промежуток времени не проверяются, вместо предмета использовать переменную.
В разделе Character -> Headpart выбирается требуемая форма. В выпадающем списке Valid Races выбирается форм-лист, в котором перечислены допустимые для нее расы. Пол выбирается рядом. Форм-листы в Miscellanious -> Formlist. Добавление расы в форм-лист производится перетаскиванием. Чтобы выбрать форм-лист из первого мода (с расой) в списке Headpart второго мода (с прическами), они оба должны быть загружены в СК и второй должен быть активным файлом (Set as active file). В этом случае первый мод выступает как мастер - второй всегда должен загружаться с первым, потому что использует его данные. Либо же, в моде с расой, ручками создаются формы Headpart причесок, где указывается путь к моделям. Тогда модели и текстуры должны быть выдраны из изначального мода (путь для моделей произвольный; для текстур только ванильный, чтобы не создавать себе проблем) и сопровождать .esp, находясь либо в открытом доступе (Data/Meshes/..., Data/Textures/...), либо в составе .bsa мода с расой.
; нужен тест ; на эффект зелья (FF-Self, какая-то длительность действия) ; заполнить Property
HeadPart Property MyHeadPart Auto ; модные глаза, доступные всем расам
Spell Property MySpell_1 Auto Spell Property MySpell_2 Auto Spell Property MySpell_3 Auto ; пассивные эффекты - заклинания Ability-Constant-Self
HeadPart CurrentHeadPart
EVENT OnEffectStart(Actor xT, Actor xC) IF xT != Game.GetPlayer() || xT.IsOnMount() Dispel() RETURN ENDIF GoToState("Work") ActorBase xB = xT.GetBaseObject() AS ActorBase Int iC = xB.GetNumHeadParts() - 1 WHILE iC >= 0 && xB.GetNthHeadPart(iC).GetType() != 2 iC -= 1 ENDWHILE CurrentHeadPart = xB.GetNthHeadPart(iC) xT.ReplaceHeadPart(CurrentHeadPart, MyHeadPart) xT.QueueNiNodeUpdate() xT.AddSpell(MySpell_1, false) xT.AddSpell(MySpell_2, false) xT.AddSpell(MySpell_3, false) ENDEVENT
STATE Work EVENT OnEffectFinish(Actor xT, Actor xC) xT.RemoveSpell(MySpell_1) xT.RemoveSpell(MySpell_2) xT.RemoveSpell(MySpell_3) xT.ReplaceHeadPart(MyHeadPart, CurrentHeadPart) WHILE xT.IsOnMount() Utility.Wait(1.0) ENDWHILE xT.QueueNiNodeUpdate() ENDEVENT ENDSTATE
Если не лень разбирать скрипты, вот мод с примерно тем же.
Без SKSE - есть Conditions (WornApparelHasKeywordCount, см. PerkMatchingSet). Со SKSE - проверяются и считаются предметы, надетые в соотв. слоты актера (GetWornForm(int slotMask), применение см. в Armor.psc).
VictorCorvin, никак. Нужно разобраться, почему вылетает, это не нормальное поведение СК. В общем случае:
Для изменения Property ванильных скриптов (.pex), они должны быть распакованы из Skyrim - Misc.bsa в Data/Scripts (туда же скрипты из DLC). Для просмотра текста скриптов и компиляции, их исходники (.psc) должны находиться в Data/Scripts/Source (исходники не поставляются с игрой с какой-то версии, их нужно качать отдельно, где именно - без понятия, у меня нет лиц. Скайрима). Если подключенный мод использует SKSE, но SKSE не установлено в файлы игры, возможны вылеты из нее (насчет СК - без понятия). В SE версии Скайрима, возможно, есть какие-то фундаментальные отличия в работе скриптов (не в курсе, вот соотв. раздел).
mka_n, потому что проверяемый объект уже содержит в сохранении свою, предыдущую версию (Property) скрипта. Нужно: 1) подключить мод; 2) загрузить сохранение, где локация с этим объектом еще ни разу не посещалась; 3) идти и проверять. Еще можно попробовать сделать ему Reset(), но не уверен.
DOOM2004, для SSE есть отдельный раздел. В скриптах LE и SE, SKSE32 и SKSE64 наверняка есть какие-то отличия (не в курсе). SE мне неинтересен, т.к. нет игры, инструментов, а значит, и возможности тестирования. Могу написать для LE, но не гарантирую работу на SE. Во-вторых, в описании мода указано, что он влияет на большинство нпс, значит, для твоих именных в нем должны быть созданы исключения. Иначе создается конфликт, когда 2 независимых мода берут управление сменой одежды у конкретного нпс. Поэтому, либо Dynamic Outfits должен быть мастером для твоего мода (второй - патч для первого), либо вносить изменения непосредственно в Dynamic Outfits, либо отказаться от Dynamic Outfits в пользу собственного. Работать с Dynamic Outfits я не могу по вышеописанной причине.
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №947
| Тема: Вопросы по скриптам Papyrus
написано: 25 октября 2020, 11:10
| Отредактировано: Multigone - 25 октября 2020, 23:29
mka_n, тебе уже ответили, как накладывать заклинание при атаке - дать атакующему перк и настроить его условиями и прочим. Отдельной функции в папирусе для этого, конечно же, нет. Есть событие OnHit(), с помощью которого определяется факт / момент атаки, RefID атакующего, его оружие и т.д. Но событие должно находиться в скрипте, запущенном на жертве. Значит, скрипт через заклинание / референс алиас должен быть повешен на нее ДО атаки. Там все сложно, тебе проще через перк.
; На ReferenceAlias конкретного актера (актеров). ; Все Property должны быть изучены и настроены перед первым запуском мода. ; Нужно больше тестов.
Outfit Property MyDailyOutfit Auto ; Модный дневной аутфит. Outfit Property MyPersonalOutfit Auto ; Модный ночной аутфит (если нет, оставить none). Outfit Property MySleepOutfit Auto ; Модный аутфит для сна (если нет, оставить none).
Float Property pfMorningTreshold = 7.00 Auto ; Время утренней смены одежды. Допустимые значения: 1.0 < pfMorningTreshold < 11.0 Float Property pfEveningTreshold = 22.00 Auto ; Время вечерней смены одежды. Допустимые значения: 13.0 < pfEveningTreshold < 23.0
Float Property pfBlockTimeScale = 300.0 Auto ; Актер не может менять одежду чаще, чем раз в (pfBlockTimeScale) реал. сек. Допустимые значения: pfBlockTimeScale >= 1.0 ; Надевание одежды для сна игнорирует это правило. Загрузка модели игнорирует это правило.
Faction Property CurrentFollowerFaction Auto ; Автозаполнение. ; Если заполнено: актер, находящийся в этой фракции, либо являющийся IsPlayerTeammate(), исключается из алгоритма смены одежды, пока проходит эти проверки.
GlobalVariable Property GameDaysPassed Auto ; Автозаполнение.
STATE Main EVENT OnLoad() IF MySleepOutfit (GetReference() as Actor).SetOutfit(none, true) ENDIF iAllowChange = 1 iCurrentOutfit = 0 UpdateGameTime() ENDEVENT
STATE Simple EVENT OnLoad() Actor xA = GetReference() AS Actor IF !CurrentFollowerFaction || (!xA.IsInFaction(CurrentFollowerFaction) && !xA.IsPlayerTeammate()) xA.SetOutfit(MyDailyOutfit) ENDIF ENDEVENT ENDSTATE
Float FUNCTION fMod(Float A, Float B = 1.0) IF B RETURN A - Math.Floor(A / B) * B ENDIF ENDFUNCTION
; Эта функция служит для остановки скрипта. ; Повторный запуск после остановки производится функцией: Update() ; Первый запуск при подключении мода происходит автомат.
FUNCTION Stop() GoToState("") UnregisterForUpdate() UnregisterForUpdateGameTime() Actor xA = GetReference() AS Actor xA.SetOutfit(VanillaDailyOutfit) xA.SetOutfit(VanillaSleepOutfit, true) ENDFUNCTION
DOOM2004, для каждого актера создается отдельный референс алиас квеста. Квест должен быть запущен. На все алиасы цепляется этот скрипт, заполняются необходимые проперти. Скрипт будет управлять сменой указанных в проперти аутфитов согласно времени суток и использованию нпс кровати (если указан аутфит для сна). Ванильные аутфиты не играют роли (только если у нпс есть ванильный сонный аутфит, а модный для сна не указан, тогда при впадании в сон нпс будет (предположительно) менять обычный аутфит на сонный, т.к. скрипт в этом случае не управляет этим). Первая смена аутфитов сразу в момент запуска мода в игре. Остановка скриптов и возврат ванильных аутфитов с помощью функции Stop(). Если удалить мод, не отключив, возможна (нужен тест) потеря аутфитов. Разбираться с Dynamic Outfits и распределением одежды по нпс желания никакого не имею, т.к. там работы явно не на одну неделю, куча подводных камней и долгое тестирование. Авторы таких модов пилят их долгое время, внося правки по отзывам.
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №949
| Тема: Вопросы по скриптам Papyrus
написано: 7 декабря 2020, 19:10
| Отредактировано: Multigone - 7 декабря 2020, 19:30
frodo01, вроде в Better Vampires это уже реализовано (заражение).
CYNIC78, есть моды, где здоровье добавляется скриптами (SomeActor.RestoreAV("Health", 10.0)). С этим-то что будешь делать? Еще здоровье меняется, если надевается шмот с бустом максимума здоровья (в этот момент к текущему здоровью прибавляется величина, равная бусту. То же самое происходит, если менять макс. здоровья командой ModAV). И с этим? Я к тому, что, если озаботиться вопросами совместимости, то надо предусмотреть как можно больше вещей, касающихся твой идеи.
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №950
| Тема: Вопросы по скриптам Papyrus
написано: 8 декабря 2020, 16:05
| Отредактировано: Multigone - 11 февраля 2021, 13:21
Myprism, потому что предмет, находящийся в инвентаре, но не (находящийся в алиасе / попавший в инвентарь из мира), не имеет собственного RefID? Т.к. твой Self - это ObjectReference. В таких случаях, если скрипт планируется добавлять к нескольким разным предметам (т.е. использовать как шаблон), создают несколько Property, но заполняют только какой-то один, и заполняют именно тем предметом, которому этот скрипт добавлен:
Код
Armor Property MyARMO Auto Weapon Property MyWEAP Auto MiscObject Property MyMISC Auto ...
UnlimitedCloud, на самом деле это легко сделать скриптами, нужно только иметь модель куска льда (лучше пару-тройку). Для теста можно заменить на бочки xD. Например, создание глыб льда заклинанием FF-Aimed: выбираем для снаряда заклинания взрыв, у взрыва указываем Object To Place - вспомогательный Static, который скриптом будет спавнить PlaceAtMe() один или несколько кусков (тоже Static) льда у точки своего появления, смещать их координаты SetPositions(), SetAngle() на небольшую случайную величину Utility.RandomFloat(). У кусков льда событием OnHit() определяем попавшее по ним заклинание с кейвордом MagicDamageFire, после нескольких попаданий удаляем кусок Delete(), либо удаляем по времени OnUpdate(). А вот с чем я вижу сложности, так это с системой ограничения общего количества кусков, и с определением положения кусков относительно поверхностей, чтобы они не висели в воздухе. Если делать только лед, который не взаимодействует с огнем, но исчезает по времени, можно использовать Hazard с соотв. моделями (? уточнить).
UPD: Предустановленные модом Static'и льда точно так же распознают хит, и отключаются Disable(). При удалении / отключении объекта можно проиграть к.-л. эффект.
Можно посмотреть список форм, которые используют Hazard морозной руны и соотв. Explosion. Если специально задаться целью сделать взрыв, не определяемый через СК, его надо размещать скриптом через PlaceAtMe(GetForm()), когда игрок находится в пределах заданных координат на этой местности (проверка координат каждые 0.1с, к примеру). Прямого пользователя взрыва нет, триггера нет, если не заглядывать в исходник скрипта, никто никогда не догадается (только методом исключения). Я, бывало, забывал что-нибудь откуда-нибудь убрать, потом часы уходили на поиск, где это возникает.
Kayo_Mara, тут необходимые (но не достаточные) основы. Тут СК википедия.
По вопросу: После создания нового квеста необходимо его сперва сохранить, чтобы получить возможность добавлять скрипты. Для одного квеста существует один автоматически создаваемый скрипт / исходник, в котором собраны все фрагменты его диалогов и стадий. В пустом поле фрагмента TopicInfo написать:
Код
;
Сохранить TopicInfo. Скрипт с названием, соотв. FormID квеста, скомпилируется и появится возможность добавления переменных и дальнейшего редактирования текста фрагмента (в окнах Begin / End). Если ранее какие-то др. фрагменты в этом квесте уже компилировались, в скрипт / исходник будет добавлена только новая функция с названием Function Fragment_X() и текстом, соотв. тексту в поле фрагмента. Добавить переменные (ПКМ меню скрипта). Сохранить квест.
Насчет использования переменных для проведения проверок в Conditions. Можно использовать глобальные переменные (GlobalVariable), можно через GetVMQuestVariable. Во втором случае скрипт должен иметь флаги Conditional в имени скрипта и имени переменной. Для такого лучше создать отдельный скрипт на квесте (с произвольным именем, например, MyQuestnameScript). Обращение к (Int) переменной MyVar скрипта MyQuestnameScript квеста MyQuestname из фрагмента, принадлежащего этому же квесту, производится способами:
Код
MyInt = (GetOwningQuest() AS MyQuestnameScript).MyVar ... (GetOwningQuest() AS MyQuestnameScript).MyVar = 1; (GetOwningQuest() AS MyQuestnameScript).MyVar += 1; IF (GetOwningQuest() AS MyQuestnameScript).MyVar > 0 ... MyQuestnameScript MyTempScript = (GetOwningQuest() AS MyQuestnameScript) ; переменная с типом MyQuestnameScript и произвольным именем MyTempScript MyTempScript.MyVar += 1
Если фрагмент не принадлежит квесту, переменной скрипта которого требуется управлять, то:
Код
Quest Property OtherQuest Auto
... (OtherQuest AS OtherQuestnameScript).OtherVar += 1 ... OtherQuestnameScript MyTempScript = OtherQuest AS OtherQuestnameScript MyTempScript.MyVar += 1
PS: Это уже раз 10 тут писалось (в той или иной форме).
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №956
| Тема: Вопросы по скриптам Papyrus
написано: 5 февраля 2021, 23:33
| Отредактировано: Multigone - 11 февраля 2021, 13:33
emelya8307, я бы сделал 2 сундука, первый на входе в локацию, в нем лежит куча разных полотенцев, второй около бассейна, пустой. Когда НПС входит в локацию, он берет случайный полотенец из первого, когда входит в триггер, полотенец из его инвентаря перемещается во второй. Когда покидает триггер, берет случайный полотенец из второго. Если игрок крадет полотенцы из второго, идет к первому и берет оттуда. Так хоть можно объяснить, почему у голого актера в инвентаре ничего нет (а не лежат не-экипированные вещи). Ну, или пусть это будет один сундук недалеко от триггера - разницы особо нет.
Если надо именно запоминать, кто что экипирует, то в скрипте триггера можно сделать 2 таблицы, в их ячейки с одинаковыми номерами заносить актеров и экипированные ими формы. Но это реально муторно и не так просто (+ куча защит от попыток доступа к одной и той же ячейке при строго одновременном срабатывании нескольких копий OnTriggerEnter). Запоминать можно и в скрипте, прицепленном к актеру или к алиасу, в котором находится актер (второе сложнее, зато актеры могут быть любыми, а не только предустановленные в СК). Но у тебя же для бани спец. НПС, да? Иначе пришлось бы менять им Outfit.
Можно запоминать аналогиями: создать столько же форм спец. неигровых Misc, сколько разных форм полотенцев, поместить все Misc в другой форм-лист. Когда удаляется полотенце, находящееся в форм-листе под индексом (i), актеру взамен выдается Misc под таким же индексом из второго листа. Поскольку Misc неигровой с весом 0, он вообще никак не может быть обнаружен или взят игроком из инвентаря актера (даже кнопкой Взять все). Когда актер покидает триггер, проверяется наличие в его инвентаре всех Misc (перебором 2 форм-листа). Первый найденный под индексом (i) Misc удаляется, и актеру взамен выдается / экипируется полотенце с индексом (i) из первого листа. Впрочем, можно кодировать (i) полотенца количеством выдаваемых Misc минус 1. Тогда и форма Misc только одна потребуется.
Можно попробовать удалить или уменьшить Wait(0.15).
Можно попробовать так (не в курсе, работает ли abPreventEquip вообще):
Код
akActionRef.UnequipItem(MyForm, true)
Вот способ с аналогиями (нужен тест):
Код
MiscObject Property pxNonplayMISC Auto ; Спец. неигровой предмет (флаг Playable снять, вес 0, модель любая). FormList Property aaaBathTowel Auto
Bool bL
Event OnTriggerEnter(ObjectReference akActionRef) Actor MyActor = akActionRef as Actor IF !MyActor RETURN ENDIF bL = true Form xF Bool bD Int iC = aaaBathTowel.GetSize() While iC && !bD iC -=1 xF = aaaBathTowel.GetAt(iC) IF MyActor.GetItemCount(xF) bD = true ENDIF EndWhile IF bD MyActor.UnequipItem(xF) MyActor.RemoveItem(xF, 999) IF !MyActor.GetItemCount(pxNonplayMISC) MyActor.AddItem(pxNonplayMISC, iC + 1) ENDIF ENDIF bL = false EndEvent
Event OnTriggerLeave(ObjectReference akActionRef) Actor MyActor = akActionRef as Actor IF MyActor WHILE bL Utility.Wait(0.01) ENDWHILE MyActor.RemoveItem(pxNonplayMISC, 999) ENDIF EndEvent
Код
; На алиасы, заполняемые актерами в бане.
MiscObject Property pxNonplayMISC Auto FormList Property aaaBathTowel Auto
Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) IF akBaseItem == pxNonplayMISC akBaseItem = aaaBathTowel.GetAt(aiItemCount - 1) (GetReference() AS Actor).AddItem(akBaseItem) (GetReference() AS Actor).EquipItem(akBaseItem) ENDIF EndEvent
emelya8307, не говорю, что это самый совершенный способ, или что он вообще уместен в данном случае, но, по крайней мере, его ядро работает как полагается, в чем я почти не сомневался. Сейчас проверил это на игроке, эмулировав события триггера стартом и финишем маг. эффекта. Схема будет работать и у тебя, если: - НПС находятся в алиасах квеста, а не абы где. - НПС мгновенно не экипируют другой предмет после экипирования полотенца, потому что хотят. - спец. Misc преждевременно не удаляется из инвентаря НПС к.-л. другим образом (например, скриптами RemoveAllItems() или Reset()). - OnTriggerLeave срабатывает для объектов как полагается, если при загрузке локации они уже находились внутри пространства триггера. - Property скриптов правильно настроены.
Вот тебе другой способ (повнимательней с комментариями внутри, нужен тест):
Код
Quest Property MyQuest Auto
Int Property piFirstNumAlias Auto ; номер первого алиаса, отведенного для НПС (смотреть в СК). ; номера должны идти строго по порядку, т.е. нельзя удалять алиасы после их создания. Int Property piLastNumAlias Auto ; номер последнего алиаса, отведенного для НПС
Bool bL
Event OnTriggerEnter(ObjectReference akActionRef) Actor MyActor = akActionRef as Actor IF !MyActor || MyActor == Game.GetPlayer() RETURN ENDIF bL = true ReferenceAlias xR = GetAliasByActor(MyActor) IF xR Armor xP = (xR AS MyAliasScriptName).MyPolotentze ; Вместо MyAliasScriptName указать реальное название скрипта, прицепленного к алиасам НПС. IF xP MyActor.UnequipItem(xP) MyActor.RemoveItem(xP, 999) ENDIF ENDIF bL = false EndEvent
Event OnTriggerLeave(ObjectReference akActionRef) Actor MyActor = akActionRef as Actor IF !MyActor || MyActor == Game.GetPlayer() RETURN ENDIF Int iC = 50 WHILE bL && iC Utility.Wait(0.01) iC -= 1 ENDWHILE ReferenceAlias xR = GetAliasByActor(MyActor) IF xR Armor xP = (xR AS MyAliasScriptName).MyPolotentze ; Вместо MyAliasScriptName указать реальное название скрипта, прицепленного к алиасам НПС. IF xP MyActor.AddItem(xP) MyActor.EquipItem(xP) ENDIF ENDIF EndEvent
ReferenceAlias FUNCTION GetAliasByActor(Actor xA) Int iC = piFirstNumAlias WHILE iC <= piLastNumAlias ReferenceAlias xR = MyQuest.GetAlias(iC) AS ReferenceAlias IF xR.GetReference() AS Actor == xA RETURN xR ENDIF iC += 1 ENDWHILE ENDFUNCTION
Код
; На алиасы НПС.
FormList Property aaaBathTowel Auto Armor Property MyPolotentze Auto Hidden
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference) IF aaaBathTowel.HasForm(akBaseObject) MyPolotentze = akBaseObject AS Armor ENDIF EndEvent
Изменение репутации для пользователя Multigone
MultigoneOffline
Сообщение №958
| Тема: Вопросы по скриптам Papyrus
написано: 7 февраля 2021, 19:44
| Отредактировано: Multigone - 11 февраля 2021, 13:26
emelya8307, лол, это условие точно не может ничего починить. Оно просто пропускает события, активируемые объектами-не-актерами, например, если кинуть в триггер кружку, или сквозь него пролетит фаербол.
Код
Событие ПриПопадании(Объект Попаданец = кружка) Актер МойАктер = Попаданец Как Актер ; (= кружка Как Актер = пусто) Если (МойАктер == пусто) Отменить дальнейшие действия
PS: Подводя итоги - пол-страницы темы потрачено без смысла, потеряно время - все по причине, что вопрос не был расписан, как следует.
Так вот, что и где мне изменить, чтобы урон с прокачкой тоже повышался?
Дать игроку перк с Entry Point -> Mod Spell Magnitude (Mult 1 + Actor Value "Destruction" * 0.01) (или другая функция), в условиях Spell проверить GetIsID или HasKeyword (или др. признаки владельца перка, заклинания или цели). Можно не давать перк через СК (меняя запись Player), а добавить Entry в уже существующий ванильный перк, который есть у игрока изначально (совместимость+-). Еще лучше - дать скриптом (совместимость++).
Скрипт на квест. Дальнейшая работа квеста необязательна - однажды добавленный перк запоминается в сохранении, пока скриптом не будет удален при необходимости. Скриптом можно добавлять перки только игроку, всем остальным актерам - через СК.
Код
Scriptname _TESTTEST67 Extends Quest ; Добавление перка автоматически при инициализации квеста.