Jump to content

Papyrus Pre-Hooks?


minekip

Recommended Posts

Hi guys! I wonder if we can make "pre-hooks" in Papyrus. Certain programming languages have something like "EventHookMode_Pre" parameter when hooking an event, which is very convenient. Anyway, how can I prevent player from adding a certain item to the inventory BEFORE he tries to add it? At the moment, my script has something like that:

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
Actor ak = Game.GetPlayer()
if akBaseItem as Armor ;not exactly this, but some condition
	int Count = ak.GetItemCount(Keyword.GetKeyword("ArmorHelmet")) + ak.GetItemCount(Keyword.GetKeyword("ClothingHead"))
	int nCount = Count - 1
	if Count > 1
		ak.RemoveItem(akBaseItem, nCount, true)
		akSourceContainer.AddItem(akBaseItem, nCount, true)
	endIf
endIf
endEvent

 

So the item goes to the player's inventory and THEN if goes back to the source container (and if the container is a dead body that was equipping a cuirass, cuirass won't equip back on that body), but I want to make the script check if the item suits a condition and only THEN allow or disallow player to take it.

 

Sorry for bad english if it's bad :)

Edited by minekip
Link to comment
Share on other sites

For your specific needs, there's an event you can put on your 'certain item'

 

http://www.creationkit.com/OnContainerChanged_-_ObjectReference

 

OnContainerchange should set you up with what you need for that. It's basically high level access to the hook you're talking about. It pops when the item you set up the event on, changes containers. You're given links to the old and the new container, so you can just make it stay in the old one. I forget if this will interrupt the little text thing saying you looted it or not, but that may actually be something you can work with to get your point across :D

 

Your particular example of "Your hands are bound" is from a particular function that disables that. The hook itself is at a lower level than papyrus for that at least. You could edit the global container script, but that's incredibly messy since, no need to do that for this at least. You may be able to get the same global effect from something with SKSE, I haven't caught up with that yet, since last I was modding it was too poorly upkept. It's great now though, so don't hesitate to browse the same site for an SKSE solution if you need more and are you're still looking for that.

 

I'm still warming my papyrus scripting back up after a several month absence from modding, but if I remember correctly, you can also add this effect easily if you know the container in question. It doesn't sound like that's the idea here though.

 

Happy modding :D

Link to comment
Share on other sites

The basic idea is that this script is attached to player (NOT to the item) and filters EVERY item that player tries to pick up/loot/etc.

For example, if player is looting a dead body and takes a cuirass (when he already had one), the script should prevent him from taking that cuirass.

Link to comment
Share on other sites

"Your hands are bound" is the GameSetting string "sCharGenControlsDisabled" and is set by completely disabling player activation control:

 

Game.DisablePlayerControls(false, false, false, false, false, false, true, false, 0)

You cannot pre-filter a player-activated item before it is moved into your inventory. You could possibly pre-emptively call BlockActivation() on an object before it is activated by the player, but the catch is that you have to anticipate that the player might try to activate that object, and you need to know the object's reference beforehand. In most cases that will not be practical.

 

However, if you only wanted to filter a few specific objects, you could put a script on them and apply BlockActivation() from their OnInit() event, then carry out any further filtering using the OnActivate() event (which will still fire).

 

But if you want to filter everything, then your player script example using the OnItemAdded() event is the best way, but maybe you should use the AddInventoryEventFilter function for better efficiency.

 

You could also replace this code:

 

ak.RemoveItem(akBaseItem, nCount, true)
akSourceContainer.AddItem(akBaseItem, nCount, true)

with this:

 

ak.RemoveItem(akBaseItem, nCount, true, akSourceContainer)

 

for a little more efficiency.

Link to comment
Share on other sites

Thank you for tips. I thought about using OnStoryDiscoverDeadBody() event to block activation of items when looting, but not really understood how can I work with this. As far as I'm concerned, I need to make a quest with a script extending it and use OnStoryDiscoverDeadBody event there. But this just not works for me, likely because I don't know how to set a quest in CK properly. Here's the approximate code of the script:

Scriptname QuestScript extends Quest Hidden

;some properties

Event OnStoryDiscoverDeadBody(ObjectReference akActor, ObjectReference akDeadActor, Location akLocation)
       Debug.MessageBox("Dead body discovered")
Actor ak = Game.GetPlayer()
if (akActor as Actor) == ak
	int iFormIndex = akDeadActor.GetNumItems()
	while iFormIndex > 0
		iFormIndex -= 1
		Form kForm = akDeadActor.GetNthForm(iFormIndex)
		
		if (SomeCondition)
			(kForm as ObjectReference).BlockActivation(true)				
		else
			(kForm as ObjectReference).BlockActivation(false)
		endIf
	endWhile
endIf
endEvent

 

So Debug.MessageBox not appears ingame. I really think that I just haven't set proper quest parameters in the CK. Can anyone help me with this? What parameters should I set for a quest?

 

Well, that's just the first part. Next thing is containers which are not dead bodies and no container (World). It's a shame that we haven't got an event like OnContainerOpen(ObjectReference akContainer) because with that event we could simply work with any container (not World) and its items.

 

And I also thought about an event which may allow us to work with any item in the currently loaded world cell (where player is). I was searching for that event, but haven't found it.

 

Imagine how convenient it would be if we could simply Pre-Hook any event :)

Edited by minekip
Link to comment
Share on other sites

I've tried to make a discover dead body quest with and without Actor and Dead Actor event refs. Still can't get it to work. Can someone show me how to use that OnStoryDiscoverDeadBody? Edited by minekip
Link to comment
Share on other sites

  • Recently Browsing   0 members

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