Jump to content

A 'Smeltdown' mod -- how to enable smelter 'recipe' only when input item not a favorite?


mattrk

Recommended Posts

 

 

It is currently flawed since GetNthForm() gets the form of the item whereas IsEquipped() requires the actual object (i.e. it is the difference between a class and an object in Java) -- if I understand correctly.

You don't understand correctly. :P

 

IsEquipped() as it is set up on the Actor Script

bool Function IsEquipped(Form akItem) native

 

As you can see it actually requires a form rather than a specific type of object.

Link to comment
Share on other sites

Ooops. :blush: Ok, I see now that the method takes an argument of type Form, as does GetNthForm()... if I'm getting the terminology correct.

 

Thank you again. It's going to make debugging a lot easier now that I don't keep trying to do the wrong thing.

--QC

Link to comment
Share on other sites

I have a working version. :laugh:

 

Script:

 

 

 

Scriptname FIP_FavoriteChestScript Extends Quest

; Initial script by mrpwn
; Modified by IsharaMeradin to prevent access to smelter whilst script is running
; IsEquipped checks added by quixoticynic, with help from the above

; Note: Use the following conditional rules:
; R     GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    OR
; PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    OR

Actor Property PlayerRef Auto
ObjectReference Property kFavoritesContainer Auto ;Points at the container in the isolated cell
Bool bUpdateFavorites

Event OnInit()
    RegisterForMenu("InventoryMenu")
    RegisterforCrosshairRef()
EndEvent

Event OnMenuOpen(String asMenuName)
    RegisterForKey(Input.GetMappedKey("Toggle POV"))
    RegisterForKey(Input.GetMappedKey("Activate"))
EndEvent

Event OnKeyDown(Int aiKey)
    bUpdateFavorites = True
EndEvent

Event OnMenuClose(String asMenuName)
        UnregisterForAllKeys()
    If(bUpdateFavorites)
        UpdateFavorites()
    EndIf
    Utility.Wait(1)
    bUpdateFavorites = False
EndEvent

Function UpdateFavorites()
    Int iSize = PlayerRef.GetNumItems()
    While(iSize >= 0)
        Form kForm = PlayerRef.GetNthForm(iSize)
        Int iCount = kFavoritesContainer.GetItemCount(kForm)
        Bool bEquipped = PlayerRef.IsEquipped(kForm)
        Bool bFavorited = Game.IsObjectFavorited(kForm)
        If(((bFavorited) || (bEquipped)) && (iCount == 0))
            kFavoritesContainer.AddItem(kForm)
            Debug.Notification("Item added to chest.")
            Debug.Notification("bEquipped = " + bEquipped)
            Debug.Notification("bFavorited = " + bFavorited)
        ElseIf((!bFavorited) && (!bEquipped) && (iCount > 0))
            kFavoritesContainer.RemoveItem(kForm, iCount)
            Debug.Notification("Item removed from chest.")
            Debug.Notification("bEquipped = " + bEquipped)
            Debug.Notification("bFavorited = " + bFavorited)
        EndIf
        iSize -= 1
    EndWhile
EndFunction

Keyword Property SmelterKYWD Auto
Form RefBase
Event OnCrosshairRefChange(ObjectReference ref)
    If ref
        RefBase = ref as form
        If RefBase.HasKeyword(SmelterKYWD) ;is a valid smelter
            While bUpdateFavorites == false
                ref.BlockActivation(false)
            EndWhile
            If bUpdateFavorites == true
                ref.BlockActivation(true)
            EndIf
        EndIf
    EndIf
EndEvent

 

 

 

The conditional rules required for the ArmorDwarvenBoots item:

R     GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    OR
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    OR

I have attached a rough working version as a zip for people interested. You can 'coc FIP_Cell' to get to the test area. Related objects are FIPChest and FIPQuest. It works for the Dwarven Cuirass and Dwarven Boots (0001394d and 0001394c). The 'F' key activates the update rule for the chest at the moment.

 

Has USKP as a dependency.

 

If anyone has any optimisation suggestions (?) I would be interested in hearing about them.

 

I will try and upload a proper .esp tomorrow night (GMT).

 

Edit: I have improved the solution quite a bit since I posted the above (so please don't take too much time commenting on the above code anymore) -- I will upload as soon as I can.

 

Thanks & regards, --QC

Link to comment
Share on other sites

I almost have a version suitable for release (I have checked every recipe works) but I have a bug that makes it stop working some times (so it is obviously unacceptable to release as it is).

 

The Papyrus log mentions the following message:

[05/24/2014 - 07:11:16PM] error: None is not a valid inventory item
stack:
	[ (0D0012D2)].ObjectReference.GetItemCount() - "<native>" Line ?
	[PRUFEIQuest (0D0012D3)].PRUFIScript.UpdateFavorites() - "PRUFIScript.psc" Line 40
	[PRUFEIQuest (0D0012D3)].PRUFIScript.OnInit() - "PRUFIScript.psc" Line 15

I think it may be something to do with the chest contents getting altered all the time. The bug prevents un-favorited items from being removed from the chest.

 

I am presently trying 3 variants of the script, that vary in their elegance with a complexity inversely related to their elegance. The most elegant version is basically that provided by mrpwn and modified by IsharaMeradin:

 

 

 

Scriptname PRUFIScript Extends Quest

; Initial script by 'mrpwn' (on Nexusmods)
; Modified by IsharaMeradin (on Nexusmods) to prevent access to smelter whilst script is running
; Altered/used by quixotic-cynic (quixoticynic on Nexusmods)

Actor Property PlayerRef Auto
ObjectReference Property prufeiChest Auto ;Points at the container in the isolated cell
Bool bUpdateFavorites

Event OnInit()
    RegisterForMenu("InventoryMenu")
    RegisterforCrosshairRef()
    Utility.Wait(1)
    UpdateFavorites()
EndEvent

Event OnMenuOpen(String asMenuName)
    Debug.Notification("A registered menu has opened.")
    RegisterForKey(Input.GetMappedKey("Toggle POV"))
EndEvent

Event OnKeyDown(Int aiKey)
    Debug.Notification("Key pressed.")
    bUpdateFavorites = True
EndEvent

Event OnMenuClose(String asMenuName)
        UnregisterForAllKeys()
    If(bUpdateFavorites)
        UpdateFavorites()
    EndIf
EndEvent

Function UpdateFavorites()
    Debug.Notification("Updating favorites.")
    Int iSize = PlayerRef.GetNumItems()
    While(iSize >= 0)
        Form kForm = PlayerRef.GetNthForm(iSize)
        Int iCount = prufeiChest.GetItemCount(kForm)
        Bool bFavorited = Game.IsObjectFavorited(kForm)
        If((bFavorited) && (iCount == 0))
            prufeiChest.AddItem(kForm)
        ElseIf((!bFavorited) && (iCount > 0))
            prufeiChest.RemoveItem(kForm, iCount)
        EndIf
        iSize -= 1
    EndWhile
    bUpdateFavorites = False
EndFunction

Keyword Property CraftingApparatus Auto
Form RefBase
Event OnCrosshairRefChange(ObjectReference ref)
    If ref
        RefBase = ref as form
        If RefBase.HasKeyword(CraftingApparatus) ;is a valid smelter
            While bUpdateFavorites == false
                ref.BlockActivation(false)
            EndWhile
            If bUpdateFavorites == true
                ref.BlockActivation(true)
            EndIf
        EndIf
    EndIf
EndEvent

 

 

 

Incidentally, I worked out the correct conditional rules to use (yes, I have been doing something myself :wink: ):

PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    OR
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     0.00    AND
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    OR
R     GetItemCount    Armor:'ArmorDwarvenBoots'    ==    0.00    AND
PL    GetItemCount    Armor:'ArmorDwarvenBoots'    >     1.00    OR
RL    GetEquipped     Armor:'ArmorDwarvenBoots'    ==    0.00    AND

...pretty complex, but anything less won't meet all of the requirements.

 

So, if anyone can provide me with any pointers regarding the bug it would be really helpful. I have Googled the error, but my search did not yield anything useful.

 

I'll release a proper version as soon as the issue is fixed, one way or the other. (I'll keep trying to fix it.)

 

Thanks & regards, --QC

Link to comment
Share on other sites

A small update to one of the functions on the script. It is basically a sanity check to ensure that the item in question is valid.

 

 

Function UpdateFavorites()
	Debug.Notification("Updating favorites.")
	Int iSize = PlayerRef.GetNumItems()
	While(iSize >= 0)
		Form kForm = PlayerRef.GetNthForm(iSize)
		If kForm ;<--------------------------------------ensure that the entry is valid
			Int iCount = prufeiChest.GetItemCount(kForm)
			Bool bFavorited = Game.IsObjectFavorited(kForm)
			If((bFavorited) && (iCount == 0))
				prufeiChest.AddItem(kForm)
			ElseIf((!bFavorited) && (iCount > 0))
				prufeiChest.RemoveItem(kForm, iCount)
			EndIf
		EndIf
		iSize -= 1
	EndWhile
	bUpdateFavorites = False
EndFunction 

 

 

Link to comment
Share on other sites

Thank you very much for the continued help -- the project may have stalled by now without it.

 

I was unaware you could use 'If' in that manner, so I have learned something new.

 

The script above fixes the problem (after moving 'iSize -= 1' outside the while loop). For some reason the (my) player inventory has a Form reference to None in it (just one) and this was breaking the whole script.

 

The full updated script is as follows:

 

 

 

Scriptname PRUFIScript Extends Quest

; Initial script by 'mrpwn' (on Nexusmods)
; Modified by IsharaMeradin (on Nexusmods) to prevent access to smelter whilst script is running (who also fixed an annoying bug)
; Used/modified by quixotic-cynic (quixoticynic on Nexusmods)

Actor Property PlayerRef Auto
ObjectReference Property prufeiChest Auto ;Points at the container in the isolated cell
Bool bUpdateFavorites

Event OnInit()
	RegisterForMenu("InventoryMenu")
	RegisterforCrosshairRef()
	Utility.Wait(1)
	UpdateFavorites()
EndEvent

Event OnMenuOpen(String asMenuName)
	RegisterForKey(33) ;Replaced Input.GetMappedKey("Toggle POV") with 33 (the DX Scan Code for 'F') since the F key is always used in the inventory even if the Toggle POF key is changed.
	Debug.Notification("A registered menu has opened.")
EndEvent

Event OnKeyDown(Int aiKey)
	Debug.Notification("Key pressed.")
	bUpdateFavorites = True
EndEvent

Event OnMenuClose(String asMenuName)
        UnregisterForAllKeys()
	If(bUpdateFavorites)
		UpdateFavorites()
	EndIf
	Utility.Wait(1)
	bUpdateFavorites = False
EndEvent

Function UpdateFavorites()
	Debug.Notification("Updating favorites.")
	Int iSize = PlayerRef.GetNumItems()
	Debug.Notification("iSize = " + iSize)
	While(iSize >= 0)
		Form kForm = PlayerRef.GetNthForm(iSize)
		;Debug.Notification("kForm " + iSize + "= " + kForm)
		If kForm
			Int iCount = prufeiChest.GetItemCount(kForm)
			Bool bFavorited = Game.IsObjectFavorited(kForm)
			If(bFavorited == True)
				Debug.Notification("bFavorited = " + bFavorited)
			EndIf
			If((bFavorited) && (iCount == 0))
				prufeiChest.AddItem(kForm)
				Debug.Notification("Added item.")
			ElseIf((!bFavorited) && (iCount > 0))
				prufeiChest.RemoveItem(kForm, iCount)
				Debug.Notification("Removed item.")
			EndIf
		EndIf
		iSize -= 1
	EndWhile
EndFunction

Keyword Property CraftingApparatus Auto
Form RefBase
Event OnCrosshairRefChange(ObjectReference ref)
	If ref
		RefBase = ref as form
		If RefBase.HasKeyword(CraftingApparatus) ;is a valid smelter
			While bUpdateFavorites == false
				ref.BlockActivation(false)
			EndWhile
			If bUpdateFavorites == true
				ref.BlockActivation(true)
			EndIf
		EndIf
	EndIf
EndEvent

 

 

 

The only problem remaining is that the key press on 'F' sometimes does not register correctly, thereby not updating the chest. Very puzzling. However, I'm not really asking for more help at this time. I'll try and work it out.

 

Edit: From some Googling it appears that if you coc to the test cell, and then experiment straight away, the OnKeyDown() function will not work properly. However, if you save and load in the cell and then test then it will work properly (though even after doing this I am experiencing inconsistent behaviour from OnKeyDown()).

 

Thanks again,

--QC

Link to comment
Share on other sites

I have improved the efficiency of the script (though it makes it more ugly):

 

 

 

Scriptname PRUFIScript Extends Quest

; Initial script by 'mrpwn' (on Nexusmods)
; Modified by IsharaMeradin (on Nexusmods) to prevent access to smelter whilst script is running (who also fixed an annoying bug)
; Used/modified by quixotic-cynic (quixoticynic on Nexusmods)

Actor Property PlayerRef Auto
ObjectReference Property prufeiChest Auto ;Points at the container in the isolated cell
Bool bUpdateFavorites

Event OnInit()
	RegisterForMenu("InventoryMenu")
	RegisterforCrosshairRef()
	Utility.Wait(1)
	UpdateFavorites()
EndEvent

Event OnMenuOpen(String asMenuName)
	RegisterForKey(33) ;Replaced Input.GetMappedKey("Toggle POV") with 33 (the DX Scan Code for 'F') since the F key is always used in the inventory even if the Toggle POF key is changed.
	;Debug.Notification("The inventory has been opened.")
EndEvent

Event OnKeyDown(Int aiKey)
	;Debug.Notification("The 'F' key has been pressed, so bUpdateFavorites = True.")
	bUpdateFavorites = True
EndEvent

Event OnMenuClose(String asMenuName)
    UnregisterForAllKeys()
	If(bUpdateFavorites)
		UpdateFavorites()
	EndIf
	;Utility.Wait(1)
EndEvent

Bool Function isEquippable(Form kForm)
	Return ((kForm as Armor) || (kForm as Weapon) || (kForm as Ammo) || (kForm as Ingredient) || (kForm as Potion) || (kForm as Scroll))
EndFunction

Bool Function isEquippableAndFav(Form kForm)
	Return (((kForm as Armor) || (kForm as Weapon) || (kForm as Ammo) || (kForm as Ingredient) || (kForm as Potion) || (kForm as Scroll)) && Game.IsObjectFavorited(kForm))
EndFunction

Function UpdateFavorites()
	If (PlayerRef.GetNumItems() < 36)
		UpdateFavoritesFine()
	Else
		UpdateFavoritesCoarse()
	EndIf
EndFunction

Function UpdateFavoritesFine()
	Float ufStart = Utility.GetCurrentRealTime()
	Int iSize = PlayerRef.GetNumItems()
	While(iSize >= 0)
		Form kForm = PlayerRef.GetNthForm(iSize)
		If isEquippable(kForm)
		; Idea for above line from http://forums.nexusmods.com/index.php?/topic/1115396-mod-script-issue-requesting-diagonstic-help/
		;Was 'If kForm' but the above seems to be slightly faster.
			Int iCount = prufeiChest.GetItemCount(kForm)
			Bool bFavorited = Game.IsObjectFavorited(kForm)
			If((bFavorited) && (iCount == 0))
				prufeiChest.AddItem(kForm)
			ElseIf((!bFavorited) && (iCount > 0))
				prufeiChest.RemoveItem(kForm, iCount)
			EndIf
		EndIf
		iSize -= 1
	EndWhile
	bUpdateFavorites = False
	Float ufEnd = Utility.GetCurrentRealTime()
	Debug.Notification("Updating favorites took " + (ufEnd - ufStart) +" seconds.")
EndFunction

Function UpdateFavoritesCoarse()
	prufeiChest.RemoveAllItems()
	Float ufStart = Utility.GetCurrentRealTime()
	Int iSize = PlayerRef.GetNumItems()
	While(iSize >= 0)
		Form kForm = PlayerRef.GetNthForm(iSize)
		If isEquippableAndFav(kForm)
		; Idea for above line from http://forums.nexusmods.com/index.php?/topic/1115396-mod-script-issue-requesting-diagonstic-help/
		;Was 'If kForm' but the above seems to be slightly faster.
			prufeiChest.AddItem(kForm)
		EndIf
		iSize -= 1
	EndWhile
	bUpdateFavorites = False
	Float ufEnd = Utility.GetCurrentRealTime()
	Debug.Notification("Updating favorites took " + (ufEnd - ufStart) +" seconds.")
EndFunction

Keyword Property CraftingApparatus Auto
Form RefBase
Event OnCrosshairRefChange(ObjectReference ref)
	If ref
		RefBase = ref as form
		If RefBase.HasKeyword(CraftingApparatus) ;is a valid smelter
			While bUpdateFavorites == false
				ref.BlockActivation(false)
			EndWhile
			If bUpdateFavorites == true
				ref.BlockActivation(true)
			EndIf
		EndIf
	EndIf
EndEvent

 

 

 

I'm still getting problems with the 'F' key not always working, so can't release yet.

Link to comment
Share on other sites

Instead of registering for the key when the menu opens and unregistering for the key when the menu closes, register for the key when the script initiates and leave it registered.

 

Modified events

 

 

Event OnInit()
	RegisterForMenu("InventoryMenu")
	RegisterforCrosshairRef()
	RegisterForKey(33) ;Replaced Input.GetMappedKey("Toggle POV") with 33 (the DX Scan Code for 'F') since the F key is always used in the inventory even if the Toggle POF key is changed.
	Utility.Wait(1)
	UpdateFavorites()
EndEvent

;Event OnMenuOpen(String asMenuName)
;	RegisterForKey(33) ;Replaced Input.GetMappedKey("Toggle POV") with 33 (the DX Scan Code for 'F') since the F key is always used in the inventory even if the Toggle POF key is changed.
;	;Debug.Notification("The inventory has been opened.")
;EndEvent

Event OnKeyDown(Int aiKey)
	If UI.IsMenuOpen("InventoryMenu")
		;Debug.Notification("The 'F' key has been pressed, so bUpdateFavorites = True.")
		bUpdateFavorites = True
	EndIf
EndEvent

Event OnMenuClose(String asMenuName)
;	UnregisterForAllKeys()
	If(bUpdateFavorites)
		UpdateFavorites()
	EndIf
	;Utility.Wait(1)
EndEvent 

 

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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