Перейти к содержанию
  • записей
    14
  • комментариев
    0
  • просмотра
    17 022

Репозитории II: разработка, часть 2


Umbakano Jr

750 просмотров

Начало здесь.

Приступим к "прикручиванию" скриптов к репозиториям для придания им функциональности. Иначе говоря, заставим их делать то, для чего они предназначены - открывать хранилища!
Из предыдущего опыта я знаю, что скрипты можно повесить прямиком на репозитории и они будут замечательно работать, но... Поскольку это объекты инвентаря, которые мы "одеваем", возникнет необходимость "снять", и эта процедура из самого объекта не работает и придется прикручивать ее к "игроку". А раз так, то логичнее все сразу "расписать" в одном скрипте, а не "распылять" по множеству объектов!


В окне Object Window выбираем пункт Quest, в таблице справа находим наш квест CB_Player и открываем его для редактирования. Переключаемся на закладку Quest Aliases, где у нас уже есть один псевдоним - Player.

Snap_2013.06.01 16.57.54_002.png


Открываем его редактирования и в секторе Scripts жмем кнопку Add, чтобы добавить новый скрипт. В следующем окне выбираем пункт New script, а дальше заполняем название и жмем ОК.
 

Snap_2013.06.01 16.31.36_001.png


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

Скрипт
Scriptname CB_PlayerAlias_Script extends ReferenceAlias  
{Следим за игроком}
Import Game

ObjectReference Property BoxWeapon Auto	; хранилище в ячейке CB_Cell
Weapon Property CB_Weapon Auto	; репозиторий

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
	If akBaseObject == CB_Weapon
		GetPlayer().UnEquipItem(CB_Weapon, False, True)	; снять одетый репозиторий
	
		DisablePlayerControls(abMenu = True)	; запретить и скрыть меню
		EnablePlayerControls(abMenu = True)		; разрешить меню
	
		BoxWeapon.Activate(GetPlayer())		; открыть хранилище
	EndIf
EndEvent


 

После сохранения и компиляции скрипта, открываем и заполняем его свойства. Для хранилища вручную указываем нашу ячейку и хранилище. А для репозитория можно воспользоваться авто-заполнением - жмем кнопку Auto-Fill.



Snap_2013.06.01 17.16.03_003.png



Жмем ОК чтобы закрыть свойства, потом закрываем окно псевдонима и окно квеста. Везде используем кнопку ОК, чтобы сохранить изменения.



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

... Все работает как планировалось! А значит можно расширить этот скрипт, включив в него все репозитории и хранилища.

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


Вот полностью готовый скрипт. Как видите он однообразен, проверяет что одето и снимает этот объект, потом закрывает меню и открывает соответствующее хранилище. Исключение составляют репозитории, при "одевании" расходующиеся, такие как еда, зелье или ингредиенты. В этих случаях следует "пополнить" инвентарь, использовав функцию добавления.

Скрипт
Scriptname CB_PlayerAlias_Script extends ReferenceAlias  
{Следим за игроком}
Import Game

ObjectReference Property BoxWeapon Auto	; хранилище в ячейке CB_Cell
ObjectReference Property BoxArmor Auto
ObjectReference Property BoxPotion Auto
ObjectReference Property BoxScroll Auto
ObjectReference Property BoxFood Auto
ObjectReference Property BoxIngr Auto
ObjectReference Property BoxBook Auto
ObjectReference Property BoxMisc Auto

Weapon Property CB_Weapon Auto	; репозиторий
Armor Property CB_Armor Auto
Potion Property CB_Potion Auto
Scroll Property CB_Scroll Auto
Potion Property CB_Food Auto
Ingredient Property CB_Ingredient Auto
Book Property CB_Book Auto
MiscObject Property CB_Misc Auto

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
	If akBaseObject == CB_Weapon
		GetPlayer().UnEquipItem(CB_Weapon, False, True)	; снять одетый репозиторий
	
		DisablePlayerControls(abMenu = True)	; запретить и скрыть меню
		EnablePlayerControls(abMenu = True)		; разрешить меню
	
		BoxWeapon.Activate(GetPlayer())		; открыть хранилище
		
	ElseIf akBaseObject == CB_Armor
		GetPlayer().UnEquipItem(CB_Armor, False, True)	
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
	
		BoxArmor.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Potion
		; мы съели репозиторий,  вместо снятия надо добавить новый репозиторий
	GetPlayer().AddItem(CB_Potion, 1, True)

		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxPotion.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Scroll
		GetPlayer().UnEquipItem(CB_Scroll, False, True)
		
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxScroll.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Food
		; мы съели репозиторий, вместо снятия надо добавить новый репозиторий
	GetPlayer().AddItem(CB_Food, 1, True)

		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxFood.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Ingredient
		; мы съели репозиторий, вместо снятия надо добавить новый репозиторий
	GetPlayer().AddItem(CB_Ingredient, 1, True)
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxIngr.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Book
		GetPlayer().UnEquipItem(CB_Book, False, True)	
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxBook.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Misc
		GetPlayer().UnEquipItem(CB_Misc, False, True)	
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxMisc.Activate(GetPlayer())
		
	EndIf
EndEvent

Заполненные свойства скрипта.
 

Snap_2013.06.01 21.00.03_004.png



Зайдя в игру, убеждаемся что все работает - хранилища открываются, принимают только определенные для них типы объектов и вообще все замечательно, кроме одного. Репозитории перемещаются и "принимаются" хранилищами, а мы этого не хотим! В наших планах чтобы репозитории невозможно было переместить из инвентаря или выбросить в мир!
Помните, при создании фильтров для хранилищ, мы упоминали спец. объекты, которые не должны попадать в хранилище. Тогда эти свойства остались не заполнены, пора их заполнить, ведь спец. объекты (репозитории) уже созданы.

<...здесь пауза длиной в сутки...>

Как я выяснил, использование скриптов на каждом отдельном хранилище, для возврата попавшего туда репозитория, не эффективно! Наилучший способ - обработать эту ситуацию в уже имеющемся скрипте псевдонима Player.
Значит, скрипты на хранилищах надо "почистить" от неиспользуемых свойств. И изменить скрипт CB_PlayerAlias_Script так чтобы репозитории всегда "возвращались" в инвентарь.


Сначала чистим. Это не сложно, ведь основной скрипт у нас на "родительском" объекте CB_Container.
Отправляемся редактировать скрипт висящий на контейнере. Выбираем в окне Object Window раздел Container, находим наш объект CB_Container и открываем для редактирования. Чтобы удалить ненужное свойство (Property), нужно отредактировать сам скрипт. Открываем его, находим строку и удаляем ее.
Form Property CB_Object Auto
{специальный объект для активации этого контейнера}
Scriptname CB_Box_FilterType_Script extends ObjectReference  
{Фильтр по типу объекта для контейнера}

Int Property TypeObject Auto
{тип объекта по списку SKSE
41 - Weapon
26 - Armor
46 - Potion
23 - Scroll
   - Food
30 - Ingredient
27 - Book
32 - Misc
   - Gem
52 - Soul
   - Ore
   - Anim}

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
	If akBaseItem.GetType() == TypeObject
	Else
		Self.RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer)
	EndIf
EndEvent

 

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

 

 

Snap_2013.06.03 15.16.16_001.png

 


 

Тоже самое делаем для хранилища CB_Box_Food, редактируем его скрипт CB_Box_FilterFood_Script, избавляясь от свойства CB_FOOD. Вот измененный скрипт.

Измененный скрипт
Scriptname CB_Box_FilterFood_Script extends ObjectReference  
{Фильтр по ключевым словам для контейнера}

Keyword Property VendorItemFood Auto
{ключевое слово}

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
	If akBaseItem.HasKeyword(VendorItemFood) || (akBaseItem as Potion).IsFood()
	Else
		Self.RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer)
	EndIf
EndEvent

 

Сохраняем промежуточные результаты работы и переходим к скрипту CB_PlayerAlias_Script.

 

Выделяем в окне Object Window категорию Quest, и в таблице справа, находим наш квест CB_Player. Открываем и переключаемся на закладку Quest Aliases. Открываем псевдоним Player и редактируем его скрипт.

Я добавил обработку события OnItemRemoved(), чтобы когда удаляется один из репозиториев, восстанавливать его количество в инвентаре. Дабы не "раздувать" скрипт однотипными командами, добавил функцию - она нужна только для компактности кода.

 

Измененный скрипт
Scriptname CB_PlayerAlias_Script extends ReferenceAlias  
{Следим за игроком}
Import Game

ObjectReference Property BoxWeapon Auto	; хранилище в ячейке CB_Cell
ObjectReference Property BoxArmor Auto
ObjectReference Property BoxPotion Auto
ObjectReference Property BoxScroll Auto
ObjectReference Property BoxFood Auto
ObjectReference Property BoxIngr Auto
ObjectReference Property BoxBook Auto
ObjectReference Property BoxMisc Auto

Weapon Property CB_Weapon Auto	; репозиторий
Armor Property CB_Armor Auto
Potion Property CB_Potion Auto
Scroll Property CB_Scroll Auto
Potion Property CB_Food Auto
Ingredient Property CB_Ingredient Auto
Book Property CB_Book Auto
MiscObject Property CB_Misc Auto

Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
	If akBaseObject == CB_Weapon
		GetPlayer().UnEquipItem(CB_Weapon, False, True)	; снять одетый репозиторий
	
		DisablePlayerControls(abMenu = True)	; запретить и скрыть меню
		EnablePlayerControls(abMenu = True)		; разрешить меню
	
		BoxWeapon.Activate(GetPlayer())		; открыть хранилище
		
	ElseIf akBaseObject == CB_Armor
		GetPlayer().UnEquipItem(CB_Armor, False, True)	
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
	
		BoxArmor.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Potion
	;	GetPlayer().AddItem(CB_Potion, 1, True)
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxPotion.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Scroll
		GetPlayer().UnEquipItem(CB_Scroll, False, True)
		
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxScroll.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Food
	;	GetPlayer().AddItem(CB_Food, 1, True)
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxFood.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Ingredient
	;	GetPlayer().AddItem(CB_Ingredient, 1, True)
		
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxIngr.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Book
		GetPlayer().UnEquipItem(CB_Book, False, True)	
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxBook.Activate(GetPlayer())
		
	ElseIf akBaseObject == CB_Misc
		GetPlayer().UnEquipItem(CB_Misc, False, True)	
	
		DisablePlayerControls(abMenu = True)
		EnablePlayerControls(abMenu = True)
		
		BoxMisc.Activate(GetPlayer())
		
	EndIf
EndEvent

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	
	If akBaseItem == CB_Weapon
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Armor
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Potion
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Scroll
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Food
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Ingredient
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Book
		ReturnItem(akBaseItem, akDestContainer)
	ElseIf akBaseItem == CB_Misc
		ReturnItem(akBaseItem, akDestContainer)
	EndIf
EndEvent

Function ReturnItem(Form _BaseItem, ObjectReference _DestContainer)
	If !_DestContainer
		If GetPlayer().GetItemCount(_BaseItem) == 0
			GetPlayer().AddItem(_BaseItem, 1, True)
		EndIf
	Else
		If GetPlayer().GetItemCount(_BaseItem) == 0
			_DestContainer.RemoveItem(_BaseItem, 1, True, GetPlayer())
		EndIf
	EndIf
EndFunction
 

 

 

На этом этапе мы получили полноценный рабочий мод! Бездонные хранилища для каждой категории отдельно! И хотя на этом останавливаться я не собираюсь, но уже можно гордиться результатом...

 

Продолжение здесь.

  • Нравится 2

0 Комментариев


Рекомендуемые комментарии

Комментариев нет

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

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

Создать аккаунт

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

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

Войти

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

Войти
×
×
  • Создать...