Scriptname PlayerBookShelfContainerScript extends ObjectReference;;;;;;;;;;;;;;;;;; Properties ;;;;;;;;;;;;;;;;;;Message Property BookShelfFirstActivateMESSAGE Auto{Display message when the player activates a bookshelf for the first time. Only displays once.}Message Property BookShelfNoMoreRoomMESSAGE Auto{Displayed message for when the amount of books the player is placing excedes the shelf limit.}Message Property BookShelfNotABookMESSAGE Auto{Message displayed when the player places a non book form in the container.}Message Property BookShelfRoomLeftMESSAGE Auto{Notification that tells the player how much room is left on the shelf upon first activating it.}GlobalVariable Property BookShelfGlobal Auto{Global showing whether or not the player has ever activated a bookshelf}FormList Property MarkerKeywords Auto{Formlist containing all the bookmarker keywords}FormList Property TriggerKeywords Auto{Formlist containing all the booktrigger keywords}Form[] Property StoredBooks Auto{Array containing exactly which types of books are in the container}ObjectReference[] Property StoredRefs Auto{Array containing the references to the books on the book shelf}ObjectReference[] Property Markers Auto{Array containing the references to the book markers}ObjectReference[] Property Triggers Auto{Array containing the references to the book shelf triggers}Int Property MaximumBookAmount AutoInt Property CurrentBookAmount Auto;;;;;;;;;;;;;;;;; Functions ;;;;;;;;;;;;;;;;;Function AddBooks(Form BookBase, Int BookAmount) int i while (BookAmount) if !(StoredBooks[i]) StoredBooks[i] = BookBase BookAmount -= 1 endif i += 1 endwhileEndFunctionFunction RemoveBooks(Form BookBase, Int BookAmount) int i = MaximumBookAmount while (BookAmount) i -= 1 if (StoredBooks[i] == BookBase) StoredBooks[i] = None BookAmount -= 1 endif endwhileEndFunction;;;;;;;;;;;;;;;;;;;;; Events/States ;;;;;;;;;;;;;;;;;;;;;Auto State SettingUp Event OnCellAttach() RegisterForSingleUpdate(Utility.RandomFloat(3, 7)) ;this will hopefully make for less conflicts with other scripts starting up EndEvent Event OnUpdate() BlockActivation() StoredBooks = new Form[18] StoredRefs = new ObjectReference[18] Markers = new ObjectReference[18] Triggers = new ObjectReference[4] ObjectReference TempRef int i while (i < MarkerKeywords.GetSize()) Markers[i] = GetLinkedRef(MarkerKeywords.GetAt(i) as Keyword) if (Markers[i]) i += 1 MaximumBookAmount = i else i = MarkerKeywords.GetSize() endif endwhile i = 0 while (i < TriggerKeywords.GetSize()) Triggers[i] = GetLinkedRef(TriggerKeywords.GetAt(i) as Keyword) if (Triggers[i]) i += 1 else i = TriggerKeywords.GetSize() endif endwhile GoToState("Closed") EndEventEndStateState Closed Event OnActivate(ObjectReference akActionRef) BookShelfRoomLeftMESSAGE.Show((MaximumBookAmount - CurrentBookAmount)) if (BookShelfGlobal.GetValue() == 0) BookShelfFirstActivateMESSAGE.Show() BookShelfGlobal.SetValue(1) endif int i while (Triggers[i]) (Triggers[i] as PlayerBookShelfTriggerSCRIPT).GoToState("IgnoreBooks") i += 1 endwhile GoToState("Opened") Activate(akActionRef, True) EndEvent EndStateState Opened ;hope that this event works on containers, otherwise will need an update loop to check for menu mode Event OnClose(ObjectReference akActionRef) int i = MaximumBookAmount while (i > 0) i -= 1 if (StoredRefs[i]) StoredRefs[i].Disable() StoredRefs[i].Delete() StoredRefs[i] = None endif endwhile while (i < CurrentBookAmount) StoredRefs[i] = Markers[i].PlaceAtMe(StoredBooks[i]) i += 1 endwhile i = 0 while (Triggers[i]) (Triggers[i] as PlayerBookShelfTriggerSCRIPT).GoToState("WaitForBooks") i += 1 endwhile GoToState("Closed") EndEvent Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) if !(akBaseItem as Book) GoToState("IgnoreAll") RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer) BookShelfNotABookMESSAGE.Show() GoToState("Opened") Return elseif (CurrentBookAmount == MaximumBookAmount) GoToState("IgnoreAll") RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer) BookShelfNoMoreRoomMESSAGE.Show() GoToState("Opened") Return endif if (CurrentBookAmount + aiItemCount > MaximumBookAmount) GoToState("IgnoreAll") RemoveItem(akBaseItem, CurrentBookAmount + aiItemCount - MaximumBookAmount, True, akSourceContainer) aiItemCount = MaximumBookAmount - CurrentBookAmount GoToState("Opened") endif CurrentBookAmount += aiItemCount AddBooks(akBaseItem, aiItemCount) EndEvent Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) CurrentBookAmount -= aiItemCount RemoveBooks(akBaseItem, aiItemCount) EndEventEndStateState IgnoreAllEndState
Scriptname fg109_Bookshelf_Container_Script extends ObjectReference Keyword Property BookShelfFirstBook AutoKeyword Property BookShelfLastBook AutoForm[] StoredBooksFloat ShelfLengthFloat CalcLengthInt CurrentBooksBool FullShelfEvent OnInit() BlockActivation() ShelfLength = GetLinkedRef(BookShelfFirstBook).GetDistance(GetLinkedRef(BookShelfLastBook)) + (GetLinkedRef(BookShelfFirstBook).GetHeight())EndEventAuto State Active Event OnActivate(ObjectReference akActionRef) GoToState("Inactive") CurrentBooks = (GetLinkedRef() as fg109_Bookshelf_Trigger_Script).MoveIntoContainer() StoredBooks = (GetLinkedRef() as fg109_Bookshelf_Trigger_Script).StoredBooks CalcLength = 0.0 FullShelf = False GoToState("Active") Activate(akActionRef, True) Utility.Wait(0.5) GoToState("Inactive") PlaceOnShelf() GoToState("Active") EndEvent Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer) if !(akBaseItem as Book) RemoveItemSilent(akBaseItem, aiItemCount, akSourceContainer) Debug.MessageBox("The bookshelf only accepts books.") elseif (FullShelf) RemoveItemSilent(akBaseItem, aiItemCount, akSourceContainer) Debug.MessageBox("The bookshelf is full.") else int BookCount = CheckShelfSpace(akBaseItem, aiItemCount) if (BookCount < aiItemCount) FullShelf = True RemoveItemSilent(akBaseItem, aiItemCount - BookCount, akSourceContainer) endif AddBooks(akBaseItem, BookCount) endif EndEvent Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) if (akBaseItem as Book) RemoveBooks(akBaseItem, aiItemCount) FullShelf = False endif EndEventEndStateFunction RemoveItemSilent(Form akItem, Int aiCount, ObjectReference akContainer) GoToState("Inactive") RemoveItem(akItem, aiCount, True, akContainer) GoToState("Active")EndFunctionInt Function CheckShelfSpace(Form MyBook, Int Count) ObjectReference TempRef = PlaceAtMe(MyBook, 1, False, True) Float BookWidth = TempRef.GetHeight() + 0.5 TempRef.Delete() int i = 0 while (i < Count) && (CurrentBooks + i < 128) && (CalcLength <= ShelfLength) CalcLength += BookWidth i += 1 endwhile Return iEndFunctionFunction AddBooks(Form MyBook, Int Count) int i = 0 CurrentBooks += Count while (Count) while (StoredBooks[i]) i += 1 endwhile StoredBooks[i] = MyBook Count -= 1 endwhileEndFunctionFunction RemoveBooks(Form MyBook, Int Count) int i = 0 CurrentBooks -= Count while (Count) if (StoredBooks[i] == MyBook) StoredBooks[i] = None Count -= 1 endif i += 1 endwhileEndFunctionFunction PlaceOnShelf() ObjectReference[] PlacedBooks = new ObjectReference[128] ObjectReference First = GetLinkedRef(BookShelfFirstBook) ObjectReference Last = GetLinkedRef(BookShelfLastBook) Float AngX = First.GetAngleX() Float AngY = First.GetAngleY() Float AngZ = First.GetAngleZ() Float PosX = First.X Float PosY = First.Y Float PosZ = First.Z Float UnitVectorX = (Last.X - PosX) / ShelfLength Float UnitVectorY = (Last.Y - PosY) / ShelfLength Float UnitVectorZ = (Last.Z - PosZ) / ShelfLength Bool PlacedFirst = False Float OldHeight Float NewHeight Float Offset = 0.0 int i = 0 int j = 0 while (CurrentBooks) if (StoredBooks[i]) PlacedBooks[j] = DropObject(StoredBooks[i]) if (PlacedFirst) NewHeight = PlacedBooks[j].GetHeight() Offset += 0.5 * OldHeight + 0.5 * NewHeight + 0.5 OldHeight = NewHeight else PlacedFirst = True OldHeight = PlacedBooks[j].GetHeight() endif while !(PlacedBooks[j].Is3DLoaded()) ;do nothing endwhile PlacedBooks[j].SetMotionType(4) PlacedBooks[j].TranslateTo(PosX + UnitVectorX * Offset, PosY + UnitVectorY * Offset, PosZ + UnitVectorZ * Offset, AngX, AngY, AngZ, 100000.0) j += 1 CurrentBooks -= 1 endif i += 1 endwhile while (j) j -= 1 PlacedBooks[j].SetMotionType(1, True) endwhileEndFunction
Scriptname fg109_Bookshelf_Trigger_Script extends ObjectReference Form[] Property StoredBooks AutoObjectReference MyContainerInt CurrentBooksBool LoopingEvent OnTriggerEnter(ObjectReference akTriggerRef) if (akTriggerRef.GetBaseObject() as Book) StoredBooks[CurrentBooks] = akTriggerRef.GetBaseObject() CurrentBooks += 1 MyContainer.AddItem(akTriggerRef) endif RegisterForSingleUpdate(0.2)EndEventEvent OnUpdate() Looping = False Disable()EndEventInt Function MoveIntoContainer() MyContainer = GetLinkedRef() StoredBooks = new Form[128] CurrentBooks = 0 Looping = True RegisterForSingleUpdate(0.2) Enable() while (Looping) Utility.Wait(0.1) endwhile Return CurrentBooksEndFunction
Scriptname DCVR_AH_BookshelfContainerScript extends ObjectReference ObjectReference[] Property PlacedBooks Auto HiddenForm[] Property Library Auto HiddenFormList Property BookMarkerList AutoMessage Property BookWarning AutoMessage Property CountWarning AutoMessage Property DupeWarning AutoInt Property MaxBooks AutoBool Property Blocked = False Auto HiddenBool Property Bypass = False Auto HiddenEvent OnInit()PlacedBooks = New ObjectReference[33]Library = New Form[33]EndEventEvent OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)Actor PlayerRef = Game.GetPlayer()If (akBaseItem as Book) If (IsDuplicate(akBaseItem)) || (aiItemCount > 1) If (akSourceContainer == PlayerRef) Bypass = True RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer) DupeWarning.Show() Else Bypass = True RemoveItem(akBaseItem, aiItemCount) EndIf Else AddToLibrary(akBaseItem, aiItemCount, akSourceContainer) EndIfElse RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer) BookWarning.Show()EndIfIf (akSourceContainer == PlayerRef) RegisterForSingleUpdate(0.1)EndIfEndEventEvent OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)If (akBaseItem as Book) && (!Bypass) RemoveFromLibrary(akBaseItem)EndIfBypass = FalseIf (akDestContainer == Game.GetPlayer()) RegisterForSingleUpdate(0.1)EndIfEndEventEvent OnUpdate()SyncBooks()EndEventBool Function IsDuplicate(Form akBaseItem)Int i = 0While (i < MaxBooks) If (Library[i] == akBaseItem) Return True EndIf i += 1EndWhileReturn FalseEndFunctionFunction AddToLibrary(Form akBaseItem, Int aiItemCount, ObjectReference akSourceContainer)Int i = 0Bool FoundEmptySlot = FalseWhile (i < MaxBooks) && (!FoundEmptySlot) If (!Library[i]) Library[i] = akBaseItem FoundEmptySlot = True EndIf i += 1EndWhileIf (!FoundEmptySlot) If (akSourceContainer == Game.GetPlayer()) Bypass = True CountWarning.Show() RemoveItem(akBaseItem, aiItemCount, True, akSourceContainer) Else Bypass = True RemoveItem(akBaseItem, aiItemCount) EndIfEndIfEndFunctionFunction RemoveFromLibrary(Form akBaseItem)Int i = 0Bool FoundMatchingSlot = FalseWhile (i < MaxBooks) && (!FoundMatchingSlot) If (Library[i] == akBaseItem) Library[i] = None FoundMatchingSlot = True EndIf i += 1EndWhileEndFunctionFunction SyncBooks()ObjectReference BookMarkerInt i = 0While (i < MaxBooks) Int n = 0 Bool FoundEmptySlot = False If (Library[i]) While (n < MaxBooks) && (!FoundEmptySlot) If (!PlacedBooks[n]) BookMarker = Game.FindClosestReferenceOfTypeFromRef(BookMarkerList.GetAt(n), Self, 800) PlacedBooks[n] = BookMarker.PlaceAtMe(Library[i]) RemoveItem(Library[i]) FoundEmptySlot = True EndIf n += 1 EndWhile EndIf i += 1EndWhileBlocked = FalseEndFunctionFunction ReturnBooks()Blocked = TrueInt i = 0While (i < MaxBooks) PlacedBooks[i].BlockActivation() Library[i] = None i += 1EndWhilei = 0While (i < MaxBooks) If (PlacedBooks[i]) If (PlacedBooks[i].Is3DLoaded()) AddItem(PlacedBooks[i].GetBaseObject()) PlacedBooks[i].Delete() EndIf PlacedBooks[i] = None EndIf i += 1EndWhileActivate(Game.GetPlayer())RegisterForSingleUpdate(0.1)EndFunction
Scriptname DCVR_AH_BookshelfActivatorScript extends ObjectReference ObjectReference Property BookContainer AutoEvent OnActivate(ObjectReference akActionRef)If (akActionRef == Game.GetPlayer()) If (!(BookContainer as DCVR_AH_BookshelfContainerScript).Blocked) (BookContainer as DCVR_AH_BookshelfContainerScript).ReturnBooks() EndIfEndIfEndEvent