Форум » Записи участника [Multigone]

Результаты поиска
Multigone  Offline  Сообщение №931 | Тема: Вопросы по скриптам Papyrus написано: 30 июня 2020, 11:46



832
yakor77, в сохранении есть несколько переменных с именем Level, возможно, хранящих значения текущего и фактического уровней (например, CurrentLevel_var, LastLevel_var). Сам алгоритм повышения уровня, скорее всего, находится в недрах Skyrim.exe. Т.е., каких-то посредников в Settings / GlobalVariable, похоже, нет. Значит, узнавать и устанавливать значения этих переменных мы не можем - предотвратить появление меню повышения атрибутов тоже.
Копание в levelupmenu.swf тоже, скорее всего, ничего не даст, поскольку алгоритм ждет ответа от окна повышения атрибутов. Проверь, если знаешь как.
Управление кнопками вместо игрока, чтобы быстро прощелкивать меню, тоже не получится, т.к. выбор и активацию кнопок MessageBox'а нельзя производить клавиатурой, только мышью.

Multigone  Offline  Сообщение №932 | Тема: Вопросы по скриптам Papyrus написано: 6 июля 2020, 18:29 | Отредактировано: Multigone - 6 июля 2020, 18:46



832
frodo01, смотри перк VampireFeed - там фрагменты, запускающие этот процесс. Сами функции в скрипте PlayerVampireQuestScript квеста PlayerVampireQuest.

Если нужно просто поймать момент этой анимации, попробуй так (не точно так, это просто болванка для дальнейших экспериментов):
Код
RegisterForAnimationEvent(Game.GetPlayer(), "SoundPlay.NPCHumanVampireFeed")

Event OnAnimationEvent(ObjectReference akSource, string asEventName)
    IF asEventName == "SoundPlay.NPCHumanVampireFeed"
        Debug.MessageBox("SoundPlay.NPCHumanVampireFeed")
    ENDIF
EndEvent

Multigone  Offline  Сообщение №933 | Тема: Вопросы по скриптам Papyrus написано: 1 августа 2020, 18:00



832
nepewka, с вопросами платного создания модов добро пожаловать на Коммерческий форум.

Multigone  Offline  Сообщение №934 | Тема: Вопросы по скриптам Papyrus написано: 5 августа 2020, 21:43



832
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 ; На алиас предмета.

EVENT OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)
    IF akNewContainer == Game.GetPlayer()
        GoToState("Stopped")
        GetOwningQuest().CompleteAllObjectives()
    ENDIF
ENDEVENT

STATE Stopped
    EVENT OnContainerChanged(ObjectReference akNewContainer, ObjectReference akOldContainer)
    ENDEVENT
ENDSTATE

Multigone  Offline  Сообщение №935 | Тема: Вопросы по скриптам Papyrus написано: 6 августа 2020, 08:49 | Отредактировано: Multigone - 6 августа 2020, 09:03



832
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

Multigone  Offline  Сообщение №936 | Тема: Вопросы по скриптам Papyrus написано: 6 августа 2020, 15:54



832
Ezalor, добавь Debug.MessageBox("Текст") в нужные строки и посмотри результат.

myav,

1) Area < 15 в игре не работает.

2) Эффект Self с действием по площади работает только для других целей, но не для источника. Если нужно и для источника, в заклинании должно быть 2 эффекта: Self - Area и Self без Area.

3) Area в СК не всегда включается с первого раза (т.е. все вроде как сделано, но в игре нет). Попробуй так: после того, как эффект настроен и добавлен в заклинание, сними флаг AutoCalculate, сохрани, поставь, сохрани.

Multigone  Offline  Сообщение №937 | Тема: Вопросы по скриптам Papyrus написано: 6 августа 2020, 18:01



832
Ezalor, у тебя лишняя логика, плюс мб перед завершением задачи нужно ее показать:

Код
Debug.MessageBox(MyQuest)

int MyQuestStage1 = MyQuest.GetStage()
Debug.MessageBox(MyQuestStage1)

if MyQuest.GetStage() == 17
    MyQuest.SetObjectiveDisplayed(15)
    MyQuest.SetObjectiveCompleted(15)
elseif MyQuest.GetStage() == 26
    MyQuest.SetObjectiveDisplayed(25)
    MyQuest.SetObjectiveCompleted(25)
elseif MyQuest.GetStage() == 37
    MyQuest.SetObjectiveDisplayed(45)
    MyQuest.SetObjectiveCompleted(45)
else
    MyQuest.SetObjectiveDisplayed(MyQuestStage1)
    MyQuest.SetObjectiveCompleted(MyQuestStage1)
endif

myav,
Цитата myav

и цель заклинания (delivery) не "self" а "on target". Или ты про что-то другое говоришь ?

Там в русифицированной версии есть несколько "на цель", тогда как в англ. все четко и понятно. К тому же ты пишешь "кастует на себя спел". Ну ладно, неважно, в любом случае, п.2) относится не только к Self, а вообще к любому типу доставки, включая Target Actor (я прост подзабыл, ща проверил). Переделывай. Не забудь про п.3).

Multigone  Offline  Сообщение №938 | Тема: Вопросы по скриптам Papyrus написано: 25 августа 2020, 12:59 | Отредактировано: Multigone - 27 августа 2020, 11:37



832
nepewka, если это неизвестные эффекты, то никак. Если это твой эффект, при старте даешь актеру неигровой предмет, при финише удаляешь его. Кол-во предметов у актера в опред. момент времени равно кол-ву навешенных на него эффектов. Если несколько актеров в один промежуток времени не проверяются, вместо предмета использовать переменную.

Multigone  Offline  Сообщение №939 | Тема: Вопросы по скриптам Papyrus написано: 27 августа 2020, 18:56



832
nepewka,


Код
; Returns how many of the specified item is in this object reference's inventory
int Function GetItemCount(Form akItem) native

Multigone  Offline  Сообщение №940 | Тема: Вопросы по моделированию написано: 14 сентября 2020, 19:31



832
Hhammaath,

В разделе Character -> Headpart выбирается требуемая форма.
В выпадающем списке Valid Races выбирается форм-лист, в котором перечислены допустимые для нее расы.
Пол выбирается рядом.
Форм-листы в Miscellanious -> Formlist.
Добавление расы в форм-лист производится перетаскиванием.
Чтобы выбрать форм-лист из первого мода (с расой) в списке Headpart второго мода (с прическами), они оба должны быть загружены в СК и второй должен быть активным файлом (Set as active file). В этом случае первый мод выступает как мастер - второй всегда должен загружаться с первым, потому что использует его данные.
Либо же, в моде с расой, ручками создаются формы Headpart причесок, где указывается путь к моделям. Тогда модели и текстуры должны быть выдраны из изначального мода (путь для моделей произвольный; для текстур только ванильный, чтобы не создавать себе проблем) и сопровождать .esp, находясь либо в открытом доступе (Data/Meshes/..., Data/Textures/...), либо в составе .bsa мода с расой.

Multigone  Offline  Сообщение №941 | Тема: Вопросы по моделированию написано: 15 сентября 2020, 07:44



832
Hhammaath, ну, в нифскопе можно ее смещать по осям или изменить размер (Scale). Я тут вообще мимоходом). Подождем экпертов.

Multigone  Offline  Сообщение №942 | Тема: Вопросы по скриптам Papyrus написано: 2 октября 2020, 22:56



832
VictorCorvin,


Код
Scriptname _TESTTEST62 Extends ActiveMagicEffect

    ; нужен тест
    ; на эффект зелья (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

Если не лень разбирать скрипты, вот мод с примерно тем же.

Multigone  Offline  Сообщение №943 | Тема: Вопросы по скриптам Papyrus написано: 3 октября 2020, 07:12



832
mka_n,

Без SKSE - есть Conditions (WornApparelHasKeywordCount, см. PerkMatchingSet).
Со SKSE - проверяются и считаются предметы, надетые в соотв. слоты актера (GetWornForm(int slotMask), применение см. в Armor.psc).

Multigone  Offline  Сообщение №944 | Тема: Вопросы по скриптам Papyrus написано: 3 октября 2020, 17:50



832
VictorCorvin, никак. Нужно разобраться, почему вылетает, это не нормальное поведение СК. В общем случае:

Для изменения Property ванильных скриптов (.pex), они должны быть распакованы из Skyrim - Misc.bsa в Data/Scripts (туда же скрипты из DLC).
Для просмотра текста скриптов и компиляции, их исходники (.psc) должны находиться в Data/Scripts/Source (исходники не поставляются с игрой с какой-то версии, их нужно качать отдельно, где именно - без понятия, у меня нет лиц. Скайрима).
Если подключенный мод использует SKSE, но SKSE не установлено в файлы игры, возможны вылеты из нее (насчет СК - без понятия).
В SE версии Скайрима, возможно, есть какие-то фундаментальные отличия в работе скриптов (не в курсе, вот соотв. раздел).

Тут обучение (что есть).

Multigone  Offline  Сообщение №945 | Тема: Вопросы по скриптам Papyrus написано: 22 октября 2020, 08:57



832
mka_n, потому что проверяемый объект уже содержит в сохранении свою, предыдущую версию (Property) скрипта. Нужно: 1) подключить мод; 2) загрузить сохранение, где локация с этим объектом еще ни разу не посещалась; 3) идти и проверять. Еще можно попробовать сделать ему Reset(), но не уверен.

Multigone  Offline  Сообщение №946 | Тема: Вопросы по скриптам Papyrus написано: 24 октября 2020, 21:20



832
DOOM2004, для SSE есть отдельный раздел. В скриптах LE и SE, SKSE32 и SKSE64 наверняка есть какие-то отличия (не в курсе). SE мне неинтересен, т.к. нет игры, инструментов, а значит, и возможности тестирования. Могу написать для LE, но не гарантирую работу на SE.
Во-вторых, в описании мода указано, что он влияет на большинство нпс, значит, для твоих именных в нем должны быть созданы исключения. Иначе создается конфликт, когда 2 независимых мода берут управление сменой одежды у конкретного нпс. Поэтому, либо Dynamic Outfits должен быть мастером для твоего мода (второй - патч для первого), либо вносить изменения непосредственно в Dynamic Outfits, либо отказаться от Dynamic Outfits в пользу собственного. Работать с Dynamic Outfits я не могу по вышеописанной причине.

Multigone  Offline  Сообщение №947 | Тема: Вопросы по скриптам Papyrus написано: 25 октября 2020, 11:10 | Отредактировано: Multigone - 25 октября 2020, 23:29



832
mka_n, тебе уже ответили, как накладывать заклинание при атаке - дать атакующему перк и настроить его условиями и прочим.
Отдельной функции в папирусе для этого, конечно же, нет. Есть событие OnHit(), с помощью которого определяется факт / момент атаки, RefID атакующего, его оружие и т.д. Но событие должно находиться в скрипте, запущенном на жертве. Значит, скрипт через заклинание / референс алиас должен быть повешен на нее ДО атаки. Там все сложно, тебе проще через перк.

DOOM2004,

Код
Scriptname _TESTTEST63 Extends ReferenceAlias ; Multigone

    ; На 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 ; Автозаполнение.
    
Outfit VanillaDailyOutfit ; Ваниль.
Outfit VanillaSleepOutfit

Float fMorningRandom ; Рандомайзеры (колебание значений времени смены в пределах +- 1 игр. час)
Float fEveningRandom

Int iCurrentOutfit
Int iAllowChange

EVENT OnInit()
    RegisterForSingleUpdate(3.0)
ENDEVENT

EVENT OnUpdate()
    Update()
ENDEVENT

EVENT OnUpdateGameTime()
    UpdateGameTime()
ENDEVENT

FUNCTION Update()
    ActorBase xB = (GetReference() as Actor).GetBaseObject() AS ActorBase
    VanillaDailyOutfit = xB.GetOutfit()
    VanillaSleepOutfit = xB.GetOutfit(true)
    IF MyPersonalOutfit || MySleepOutfit
        fMorningRandom = pfMorningTreshold + 1.0 - Utility.RandomFloat(0.0, 2.0)
        fEveningRandom = pfEveningTreshold + 1.0 - Utility.RandomFloat(0.0, 2.0)
        GoToState("Main")
        OnLoad()
    ELSE
        GoToState("Simple")
        OnLoad()
    ENDIF
ENDFUNCTION

FUNCTION UpdateGameTime()
ENDFUNCTION

STATE Main
    EVENT OnLoad()
        IF MySleepOutfit
            (GetReference() as Actor).SetOutfit(none, true)
        ENDIF
        iAllowChange = 1
        iCurrentOutfit = 0
        UpdateGameTime()
    ENDEVENT
    
    EVENT OnUnload()
        UnregisterForUpdate()
        UnregisterForUpdateGameTime()
    ENDEVENT

    EVENT OnSit(ObjectReference akFurniture)
        UpdateGameTime()
    ENDEVENT

    EVENT OnGetUp(ObjectReference akFurniture)
        UpdateGameTime()
    ENDEVENT
    
    FUNCTION Update()
        IF iAllowChange < 0
            iAllowChange = 1
            UpdateGameTime()
        ELSE
            iAllowChange = 1
        ENDIF
    ENDFUNCTION

    FUNCTION UpdateGameTime()
        Actor xA = GetReference() AS Actor
        Float fT = fMod(GameDaysPassed.Value) * 24.0
        IF CurrentFollowerFaction && (xA.IsInFaction(CurrentFollowerFaction) || xA.IsPlayerTeammate())
            iAllowChange = -1
            RegisterForSingleUpdate(30.0)
        ELSEIF MySleepOutfit && xA.GetSleepState() > 0
            IF iCurrentOutfit != 3
                iCurrentOutfit = 3
                iAllowChange = 0
                xA.SetOutfit(MySleepOutfit)
                IF fT < fMorningRandom || fT >= fEveningRandom
                    fMorningRandom = pfMorningTreshold + 1.0 - Utility.RandomFloat(0.0, 2.0)
                    RegisterForSingleUpdateGameTime(fMod(24.0 + fMorningRandom - fT, 24.0) + 0.1)
                ELSE
                    fEveningRandom = pfEveningTreshold + 1.0 - Utility.RandomFloat(0.0, 2.0)
                    RegisterForSingleUpdateGameTime(fMod(24.0 + fEveningRandom - fT, 24.0) + 0.1)
                ENDIF
                RegisterForSingleUpdate(pfBlockTimeScale)
            ENDIF
        ELSEIF iAllowChange < 1
            iAllowChange = -1
        ELSEIF MyPersonalOutfit && (fT < fMorningRandom || fT >= fEveningRandom)
            IF iCurrentOutfit != 2
                iCurrentOutfit = 2
                iAllowChange = 0
                xA.SetOutfit(MyPersonalOutfit)
                fMorningRandom = pfMorningTreshold + 1.0 - Utility.RandomFloat(0.0, 2.0)
                RegisterForSingleUpdateGameTime(fMod(24.0 + fMorningRandom - fT, 24.0) + 0.1)
                RegisterForSingleUpdate(pfBlockTimeScale)
            ENDIF
        ELSEIF iCurrentOutfit != 1
            iCurrentOutfit = 1
            iAllowChange = 0
            xA.SetOutfit(MyDailyOutfit)
            fEveningRandom = pfEveningTreshold + 1.0 - Utility.RandomFloat(0.0, 2.0)
            RegisterForSingleUpdateGameTime(fMod(24.0 + fEveningRandom - fT, 24.0) + 0.1)
            RegisterForSingleUpdate(pfBlockTimeScale)
        ENDIF
    ENDFUNCTION
ENDSTATE

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

Multigone  Offline  Сообщение №948 | Тема: Вопросы по скриптам Papyrus написано: 26 октября 2020, 21:48



832
DOOM2004, для каждого актера создается отдельный референс алиас квеста. Квест должен быть запущен. На все алиасы цепляется этот скрипт, заполняются необходимые проперти. Скрипт будет управлять сменой указанных в проперти аутфитов согласно времени суток и использованию нпс кровати (если указан аутфит для сна). Ванильные аутфиты не играют роли (только если у нпс есть ванильный сонный аутфит, а модный для сна не указан, тогда при впадании в сон нпс будет (предположительно) менять обычный аутфит на сонный, т.к. скрипт в этом случае не управляет этим). Первая смена аутфитов сразу в момент запуска мода в игре. Остановка скриптов и возврат ванильных аутфитов с помощью функции Stop(). Если удалить мод, не отключив, возможна (нужен тест) потеря аутфитов.
Разбираться с Dynamic Outfits и распределением одежды по нпс желания никакого не имею, т.к. там работы явно не на одну неделю, куча подводных камней и долгое тестирование. Авторы таких модов пилят их долгое время, внося правки по отзывам.

Multigone  Offline  Сообщение №949 | Тема: Вопросы по скриптам Papyrus написано: 7 декабря 2020, 19:10 | Отредактировано: Multigone - 7 декабря 2020, 19:30



832
frodo01, вроде в Better Vampires это уже реализовано (заражение).

CYNIC78, есть моды, где здоровье добавляется скриптами (SomeActor.RestoreAV("Health", 10.0)). С этим-то что будешь делать? Еще здоровье меняется, если надевается шмот с бустом максимума здоровья (в этот момент к текущему здоровью прибавляется величина, равная бусту. То же самое происходит, если менять макс. здоровья командой ModAV). И с этим?
Я к тому, что, если озаботиться вопросами совместимости, то надо предусмотреть как можно больше вещей, касающихся твой идеи.

Multigone  Offline  Сообщение №950 | Тема: Вопросы по скриптам Papyrus написано: 8 декабря 2020, 16:05 | Отредактировано: Multigone - 11 февраля 2021, 13:21



832
Myprism, потому что предмет, находящийся в инвентаре, но не (находящийся в алиасе / попавший в инвентарь из мира), не имеет собственного RefID? Т.к. твой Self - это ObjectReference.
В таких случаях, если скрипт планируется добавлять к нескольким разным предметам (т.е. использовать как шаблон), создают несколько Property, но заполняют только какой-то один, и заполняют именно тем предметом, которому этот скрипт добавлен:
Код
Armor Property MyARMO Auto
Weapon Property MyWEAP Auto
MiscObject Property MyMISC Auto
...

Event OnEquipped(Actor akActor)
   IF MyARMO
      Debug.MessageBox(MyARMO)
   ELSEIF MyWEAP
      Debug.MessageBox(MyWEAP)
   ELSEIF MyMISC
      Debug.MessageBox(MyMISC)
   ...

endEvent

Еще можно поместить актера в алиас, и узнавать экипированный предмет через OnObjectEuipped().

Multigone  Offline  Сообщение №951 | Тема: Вопросы по скриптам Papyrus написано: 3 января 2021, 08:49 | Отредактировано: Multigone - 8 февраля 2021, 20:18



832
grumpos,

Код
; В скрипт, управляющий анимацией.

MiscObject Property MyItem Auto ; Мыло.
ObjectReference Property MyMarker Auto ; Референс Х-маркера (Static), заранее размещенный в положенном месте.

Event ???
   Game.GetPlayer().RemoveItem(MyItem, 999)
   MyMarker.PlaceAtMe(MyItem)
EndEvent

Multigone  Offline  Сообщение №952 | Тема: Вопросы по скриптам Papyrus написано: 12 января 2021, 17:10 | Отредактировано: Multigone - 12 января 2021, 19:17



832
emelya8307,
Получение дня недели:
Код
X = (GameDaysPassed.Value As Int + 6) % 7 + 1
Или: X = (Utility.GetCurrentGameTime() AS Int + 6) % 7 + 1

Где X - целое число от 1 до 7, соответствующее текущему дню недели, начиная с понедельника.

Если нужно задать время, когда должно происходить событие, можно использовать апдейт:

Код
Float fSomeDay = 3.25 ; Среда, 6 утра

FUNCTION Start()
   RegisterForSingleUpdateGameTime(fMod(fMod(fSomeDay, 7.0) - Utility.GetCurrentGameTime(), 7.0) * 168.0)
ENDFUNCTION

EVENT OnUpdateGameTime()
   Float fDaysWait = fMod(fMod(fSomeDay, 7.0) - Utility.GetCurrentGameTime(), 7.0) * 7.0
   IF fDaysWait < 0.01
      RegisterForSingleUpdateGameTime(168.0)
   ELSE
      RegisterForSingleUpdateGameTime(fDaysWait * 24.0)
   ENDIF
   ; Далее желаемые действия.
ENDEVENT

Float FUNCTION fMod(Float A, Float B = 1.0) ; Модуло.
    IF B
      RETURN A - Math.Floor(A / B) * B
    ENDIF
ENDFUNCTION

Multigone  Offline  Сообщение №953 | Тема: Вопросы по Creation Kit (продолжение старой темы) написано: 17 января 2021, 14:19 | Отредактировано: Multigone - 17 января 2021, 15:51



832
UnlimitedCloud, на самом деле это легко сделать скриптами, нужно только иметь модель куска льда (лучше пару-тройку). Для теста можно заменить на бочки xD.
Например, создание глыб льда заклинанием FF-Aimed: выбираем для снаряда заклинания взрыв, у взрыва указываем Object To Place - вспомогательный Static, который скриптом будет спавнить PlaceAtMe() один или несколько кусков (тоже Static) льда у точки своего появления, смещать их координаты SetPositions(), SetAngle() на небольшую случайную величину Utility.RandomFloat(). У кусков льда событием OnHit() определяем попавшее по ним заклинание с кейвордом MagicDamageFire, после нескольких попаданий удаляем кусок Delete(), либо удаляем по времени OnUpdate().
А вот с чем я вижу сложности, так это с системой ограничения общего количества кусков, и с определением положения кусков относительно поверхностей, чтобы они не висели в воздухе.
Если делать только лед, который не взаимодействует с огнем, но исчезает по времени, можно использовать Hazard с соотв. моделями (? уточнить).

UPD: Предустановленные модом Static'и льда точно так же распознают хит, и отключаются Disable(). При удалении / отключении объекта можно проиграть к.-л. эффект.

Multigone  Offline  Сообщение №954 | Тема: Вопросы по Creation Kit (продолжение старой темы) написано: 2 февраля 2021, 10:14



832
Цитата Myprism

Как отыскать виновника?


Можно посмотреть список форм, которые используют Hazard морозной руны и соотв. Explosion. Если специально задаться целью сделать взрыв, не определяемый через СК, его надо размещать скриптом через PlaceAtMe(GetForm()), когда игрок находится в пределах заданных координат на этой местности (проверка координат каждые 0.1с, к примеру). Прямого пользователя взрыва нет, триггера нет, если не заглядывать в исходник скрипта, никто никогда не догадается (только методом исключения). Я, бывало, забывал что-нибудь откуда-нибудь убрать, потом часы уходили на поиск, где это возникает.

Multigone  Offline  Сообщение №955 | Тема: Вопросы по скриптам Papyrus написано: 4 февраля 2021, 17:43



832
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  Offline  Сообщение №956 | Тема: Вопросы по скриптам Papyrus написано: 5 февраля 2021, 23:33 | Отредактировано: Multigone - 11 февраля 2021, 13:33



832
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

Multigone  Offline  Сообщение №957 | Тема: Вопросы по скриптам Papyrus написано: 7 февраля 2021, 12:08



832
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  Offline  Сообщение №958 | Тема: Вопросы по скриптам Papyrus написано: 7 февраля 2021, 19:44 | Отредактировано: Multigone - 11 февраля 2021, 13:26



832
emelya8307, лол, это условие точно не может ничего починить. Оно просто пропускает события, активируемые объектами-не-актерами, например, если кинуть в триггер кружку, или сквозь него пролетит фаербол.
Код
Событие ПриПопадании(Объект Попаданец = кружка)
    Актер МойАктер = Попаданец Как Актер ; (= кружка Как Актер = пусто)
    Если (МойАктер == пусто)
        Отменить дальнейшие действия

PS: Подводя итоги - пол-страницы темы потрачено без смысла, потеряно время - все по причине, что вопрос не был расписан, как следует.

Multigone  Offline  Сообщение №959 | Тема: Вопросы по Creation Kit (продолжение старой темы) написано: 8 февраля 2021, 20:10



832
letawka, СК делает бэкапы .esp в папку Skyrim\Backup.

Multigone  Offline  Сообщение №960 | Тема: Вопросы по Creation Kit (продолжение старой темы) написано: 9 февраля 2021, 12:12



832
Цитата Lissenok

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

Дать игроку перк с Entry Point -> Mod Spell Magnitude (Mult 1 + Actor Value "Destruction" * 0.01) (или другая функция), в условиях Spell проверить GetIsID или HasKeyword (или др. признаки владельца перка, заклинания или цели). Можно не давать перк через СК (меняя запись Player), а добавить Entry в уже существующий ванильный перк, который есть у игрока изначально (совместимость+-). Еще лучше - дать скриптом (совместимость++).

Скрипт на квест. Дальнейшая работа квеста необязательна - однажды добавленный перк запоминается в сохранении, пока скриптом не будет удален при необходимости. Скриптом можно добавлять перки только игроку, всем остальным актерам - через СК.
Код
Scriptname _TESTTEST67 Extends Quest
    ; Добавление перка автоматически при инициализации квеста.

Perk Property MyPerk Auto ; Заполнить

EVENT OnInit()
    RegisterForSingleUpdate(3.0)
ENDEVENT

EVENT OnUpdate()
    Game.GetPlayer().AddPerk(MyPerk)
ENDEVENT

Форум » Записи участника [Multigone]
Поиск:





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