Перейти к содержанию

Как работает функция IsSneaking?


Dandie

Рекомендуемые сообщения

Пытаюсь я тут освоиться чуть-чуть в Papyrus (а я-то и со скриптами предыдущих игр не очень ладил). И вот нужна помощь - прошу откликнуться если не затруднит.

Есть вот такой скрипт:

 

Armor Property Knapsack_Armor auto

bool Function IsSneaking() native

Actor property holder auto

Event OnActivate(ObjectReference akActionRef)

if !holder.isSneaking ()

holder.AddItem( Knapsack_Armor, 1)

removeallitems ( Holder, 1 )

self.Disable()

endIf

EndEvent

 

 

Моя цель - чтоб при взаимодействии с контейнером, когда ГГ крадется, ему добавлялся кусок брони (и все содержимое контейнера), а сам контейнер благополучно после этого дисейблился. Однако, все происходит наоборот - когда ГГ крадется, то контейнер открывается как обычно, а вот если стоит - то срабатывает все остальное. Я неправильно истолковал смысл IsSneaking? Что не так?

PS: Что характерно, если изменить строки после условия на Return, а все добавления и disable поставить в блок else, то работает как я и хотел. Но я все равно не понимаю, почему.

PPS: Если уж совсем обнаглеть - никто не знает как правильно прописывать IsKeyPressed?

Изменено пользователем Dandie
Ссылка на комментарий
Поделиться на другие сайты

  • 1 месяц спустя...

Припозднился я, но все же - автор, ты нашел способ решения данного вопроса?

Насколько помню, так и не нашел - просто довольствовался тем, что скрипт работает хоть как-то.

Ссылка на комментарий
Поделиться на другие сайты

Если скрипт рассчитан только на игрока, то можно вместо назначаемого свойства Actor property holder auto использовать GetPlayer, и индекс 1 поставить:

 

If (Game.GetPlayer().IsSneaking() == 1)

 

PPS: Если уж совсем обнаглеть - никто не знает как правильно прописывать IsKeyPressed?

Функцию SKSE? Ну например так:

 

 

Scriptname ......


Import Input
Import Game
Import Debug

Bool sdHKeyPress

Int property iPressKey Auto; указать скан-код для клавиши


Event OnInit()
  RegisterForSingleUpdate(0.5)  ; интекс .5 взял произвольно, возможно потребуется его изменить
EndEvent

Event OnUpdate()

  If sdHKeyPress  != IsKeyPressed(iPressKey)
  sdHKeyPress = !sdHKeyPress
  If sdHKeyPress
	   ; делаем то, что требуется при нажатии клавиши
  endif
  endif
  RegisterForSingleUpdate(0.5)	
EndEvent

Но нет гарантий, что эта функция будет стабильно работать в режиме MenuMode, а если даже и будет то только в течении 1 фрейма после ее активации.

Изменено пользователем Quazar
Ссылка на комментарий
Поделиться на другие сайты

Если скрипт рассчитан только на игрока, то можно вместо назначаемого свойства Actor property holder auto использовать GetPlayer, и индекс 1 поставить:

 

If (Game.GetPlayer().IsSneaking() == 1)

 

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

 

Функцию SKSE? Ну например так:

 

Кстати, ее я тоже худо-бедно реализовал. Опять же, из-за неграмотности, старался как можно меньше отсебятины дописывать, потому у меня как был так и остался Onactivate в качестве эвента. В итоге получалось, что при активации предмета стандартным способом и при зажатой кастомной клавише фича срабатывала. Не очень изящно, но как вариант.

Ссылка на комментарий
Поделиться на другие сайты

Я вот, кстати. думал насчет этого... можно еще через условия решить. Что то типа такого:

 

if !holder.isSneaking ()

# при выполненом условии ничего

else

# при невыполненом даем награду

holder.AddItem( Knapsack_Armor, 1)

removeallitems ( Holder, 1 )

 

 

То есть, если персонаж крадется - скорипт срабатывает, не крадется - не срабатывает.

Изменено пользователем Antrix
Ссылка на комментарий
Поделиться на другие сайты

То есть, если персонаж крадется - скорипт срабатывает, не крадется - не срабатывает.

В событии OnActivate использовать else нет смысла, активация контейнера вхолостую и так произойдет.

 

-----

 

Что еще можно добавить по скрипту:

- вместо self я лучше бы использовал ссылку на копию контейнера ObjectReference Property, ведь таким способом скриптуются не все копии в игре, а лишь "избранные". Вот и укажите их в свойствах.

- если дисейбленный контейнер нужно удалить окончательно, то можно использовать так же функцию Delete(). Disable() - лишь отключает копию объекта, но не удаляет его из игры.

- можно добавить дополнительную проверку на то, что именно игрок активирует контейнер, а не кто-либо еще (бывают и такие ситуации). А то у меня был случай, когда мне "с неба" периодически падало 100 септимов, хотя я и близко не подходил к заскриптованному объекту))

 

Собственно, вот так будет выглядеть переделанный скрипт:

 

Scriptname DandieScript extends ObjectReference

Import Game

ObjectReference Property Barrel Auto

Armor Property Knapsack_Armor auto

Event OnActivate(ObjectReference akActionRef)

if (akActionRef == GetPlayer())
if (GetPlayer().isSneaking() == 1)
	akActionRef.AddItem(Knapsack_Armor, 1)  ; вместо akActionRef можно ставить и GetPlayer(), скрипт работает одинаково
	Barrel.removeallitems (akActionRef, 1)
	Barrel.Disable()
	Barrel.Delete()
endIf
endif
EndEvent

Изменено пользователем Quazar
Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...