Jump to content

[LE] AddInventoryEventFilter


Recommended Posts

Hello everyone. I'm working on a script that gives the player a Blank Tome whenever they use a spell tome, to make tomes more immersive. The script currently looks like this:

Scriptname zzzBlankTomeScript extends ReferenceAlias 

Import Game

Book Property Book01 Auto
Keyword Property Keyword01 Auto

;---------------------------------------------

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If akBaseItem as Book
		Book Book02 = akBaseItem as Book
		If Book02.HasKeyword(Keyword01) && akItemReference.GetParentCell() != Game.GetPlayer().GetParentCell() && akDestContainer == None
			Game.GetPlayer().Additem(Book01, 1, true)
		EndIf
	EndIf
EndEvent

The creation kit page suggests that I add a 'AddInventoryEventFilter' but I'm not sure how to implement that or if I even need it. Does anyone know if I need to add a filter or how to add one.

Link to comment
Share on other sites

You already have a good optimization by checking if you can cast the base form to Book.

 

To use the inventory filter you would need to filter on every spell tome. Assuming you want this to work with books added by mods that would be too complicated to be worth the effort.

Link to comment
Share on other sites

As cdooley wrote, the use of AddInventoryFilter is not needed here. Nevertheless you could make your alias script a bit more comprehensive.

 

zzzBlankTomePlayerAliasScript

 

Scriptname zzzBlankTomePlayerAliasScript extends ReferenceAlias
; https://forums.nexusmods.com/index.php?/topic/5503987-addinventoryeventfilter/
; gives the player a Blank Tome whenever he used a spell tome

  Book    PROPERTY Book01    auto    ; Blank tome  // Are you sure a blank tome has a vanilla formID, not required DLC2?
  Keyword PROPERTY Keyword01 auto    ; keyword of spell tome

; -- FUNCTION --

FUNCTION myF_GiveBook(ObjectReference akItemReference)
;-----------------------------------------------------
cell c
    IF ( akItemReference )                                ; IF (akItemReference != None)
        c = akItemReference.GetParentCell()
    ENDIF

    objectReference playerRef = self.GetReference()       ; only valid for player alias script
    IF (c == playerRef.GetParentCell())
        ; spell tome and player share the same cell, that means player has dropped the spell book
    ELSE
        playerRef.AddItem(Book01 as Form, 1, TRUE)        ; give player a blank spell tome
    ENDIF
ENDFUNCTION


;-- EVENTs -- "Waiting" + "Busy"

;=============================
auto state Waiting
;=================
EVENT OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
IF ( akDestContainer )
    RETURN    ; - STOP - player is trading or moving the book into container
ENDIF
;---------------------
IF (aiItemCount > 1)
    RETURN    ; - STOP - more than one book, it should not be
ENDIF
;---------------------
IF (akBaseItem as Book)
ELSE
    RETURN    ; - STOP - no kind of book
ENDIF
;--------------------- from here: player could dropped a book to the ground /or/ has learnt a new spell
IF (akBaseItem as Book).HasKeyword(Keyword01)
    gotoState("Busy")            ; ### STATE ###
    myF_GiveBook(akItemReference)
    gotoState("Waiting")         ; ### STATE ### back to auto state
ENDIF
ENDEVENT
;=======
endState

;=============================
state Busy    ; nothing here
;=========
;EVENT OnItemRemoved(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
;ENDEVENT
;=======
endState

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

In case you find ReDragon2013's code hard to follow, it's approximately equivalent to this change to the OnItemRemoved event from the original script. (ReDragon2013 writes code based on the way the compiler works. That generates the very best code from the computer's perspective but can be hard to read for humans. This has the same logical structure and core optimizations but misses out on the low-level optimizations except for the very first one.)

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If akBaseItem as Book ; only books are interesting
		If akDestContainer == None && aiItemCount == 1  ; a single book not placed into a container
			If (akBaseItem as Book).HasKeyword(Keyword01)  ; a spellbook
				ObjectReference PlayerRef = GetReference()
				If akItemReference == None || akItemReference.GetParentCell() != PlayerRef.GetParentCell() ; not dropped
					PlayerRef.Additem(Book01, 1, true)
				EndIf
			EndIf
		Endif
	EndIf
EndEvent

The only thing I've left out is the use of a state change. Generally I would encourage using states to optimize inventory code but in this case the code is already optimized to the point where the state would provide no practical benefit.

 

The check to see if the item is a book remains as the first test since that's the most likely to fail and if it does the script will efficiently bypass the rest of the script. The second pair of checks to make sure it's a single book not placed into a container are next because they don't involve calling functions and so are very fast. The keyword check is next since it's the next most likely thing to fail which will skip the other checks. Explicitly checking to see if akItemReference is None simply avoids errors appearing in the log file while attempting a useless call to GetParentCell(). And finally using GetReference is faster for the system than calling Game.GetPlayer.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...