IsharaMeradin Posted May 19, 2014 Share Posted May 19, 2014 Quote 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 Scriptbool 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 More sharing options...
mattrk Posted May 20, 2014 Author Share Posted May 20, 2014 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 More sharing options...
mattrk Posted May 20, 2014 Author Share Posted May 20, 2014 I have a working version. :laugh: Script: Reveal hidden contents 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 ORI 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 More sharing options...
mattrk Posted May 24, 2014 Author Share Posted May 24, 2014 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 15I 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: Reveal hidden contents 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 More sharing options...
IsharaMeradin Posted May 24, 2014 Share Posted May 24, 2014 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. Reveal hidden contents 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 More sharing options...
mattrk Posted May 25, 2014 Author Share Posted May 25, 2014 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: Reveal hidden contents 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 More sharing options...
mattrk Posted May 25, 2014 Author Share Posted May 25, 2014 I have improved the efficiency of the script (though it makes it more ugly): Reveal hidden contents 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 More sharing options...
IsharaMeradin Posted May 25, 2014 Share Posted May 25, 2014 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 Reveal hidden contents 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 More sharing options...
mattrk Posted May 26, 2014 Author Share Posted May 26, 2014 OK. Thank you very much to everyone who helped, especially 'mrpwn' and 'IsharaMeradin'. It is now published here along with Elementary Smelting. Hopefully the mods are useful. Regards, --QC Link to comment Share on other sites More sharing options...
Recommended Posts