Generic "Get selected item ID in inventory menu" scr

Post » Wed Dec 07, 2011 2:36 am

Anybody know how to build a script that gets the ID for a selected item in the Inventory menu upon mouse click and can work with most UIs? This is the only thing I need for a script I'm building that clones items into the save data so that plugins aren't required for certain items therefore freeing space that's used by simple armor and weapon mods for other, more intensive mods.
User avatar
Kevan Olson
 
Posts: 3402
Joined: Tue Oct 16, 2007 1:09 am

Post » Tue Dec 06, 2011 7:47 pm

This is my monitor script for Keychain. It would disable the clicker when the player hovered the button over the Keychain, so they couldn't equip it. However, I could still tell if they tried to click the Keychain, and if so run the Keychain functions.
;{{{--Click functionsbegin MenuMode	if DisabledLMB		set DisabledLMB to 0		EnableKey 256	endif	if (MenuMode 1002) ;|| (MenuMode 1008) ;Don't allow in 1008 - not sure of need for it, would require shift-click to move and code to refresh container menu		if (GetActiveMenuSelection == P1DkeyChain) && ((IsKeyPressed3 42) == 0) && ((IsKeyPressed3 54) == 0) ;, 			set DisabledLMB to 1			DisableKey 256			if (OnKeyDown 256)					if Clicks					set Clicks to 2					set ClickTimer to -1				else					set Clicks to 1					set ClickTimer to .5				endif			endif		endif		if Clicks			if (ClickTimer > 0) && (GetActiveMenuSelection == P1DkeyChain)				set ClickTimer to (ClickTimer - GetSecondsPassed)			else				if (Clicks == 1) ;Hook/unhook keys					if P1Dkey.Hooked						P1DkeyUnhook.Activate2 P1DkeyActRef, 1						message "Unhooked keys from keychain"					else						P1DkeyHook.Activate2 P1DkeyActRef, 1						message "Hooked keys to keychain"					endif				else ;if (Clicks == 2) ;Open up the options menu					P1DkeyOptions.Activate2 P1DkeyActRef, 1				endif				set Clicks to 0			endif		endif	elseif Clicks		set Clicks to 0	endifendbegin GameMode	if DisabledLMB		set DisabledLMB to 0		EnableKey 256	endif	if Clicks		set Clicks to 0	endifend;}}}

User avatar
Hearts
 
Posts: 3306
Joined: Sat Oct 20, 2007 1:26 am

Post » Wed Dec 07, 2011 5:41 am

Seems a little complicated for what I want to do... Here's the script, the loop isn't working properly anyways despite being on the inventory menu...

scn CloneItemScriptref OldObjectref NewObject;short inMenuModeshort RMouseButtonbegin OnEquip	if MenuMode 1002 == 1		MessageBox "Please select the item you wish to modify. Note that this is meant for non-vanilla items!";		while MenuMode 1002			if GetButtonPressed 256	&& RMouseButton == 0				let OldObject := GetActiveMenuSelection;				let RMouseButton := 1			endif;			if OldObject.IsClonedForm && RMouseButton == 1				Message "This is already cloned, no need to move it to save data again!"				break			elseif OldObject.IsActor && RMouseButton == 1				Message "Invalid choice. Aborting...";				break			elseif OldObject.IsArmor || OldObject.IsWeapon || OldObject.IsClothing || OldObject.IsAmmo || OldObject.IsIngredient && RMouseButton == 1				set NewObject to CloneForm OldObject 				player.addItem NewObject 1				player.removeItem OldObject 1				Message "Move to save data complete!";				break			else 				let RMouseButton := 0;			endif;			Print "Loop finished"		Loop;	else		MessageBox "The Rune of Nothing requires you to be on the inventory screen.";	endif;end;


EDIT: Updated the script, hasn't been tested yet...
User avatar
Guinevere Wood
 
Posts: 3368
Joined: Mon Dec 04, 2006 3:06 pm

Post » Tue Dec 06, 2011 5:11 pm

I think you're misunderstanding script timing. Scripts run once per frame (there are exceptions, but this holds for items on the player), from start to finish. The way your script is set up, it will run the onEquip block once when it's equipped. Every frame following that, the script won't do anything because it's not being equipped.

The loop that you've added only runs during that single frame of the onEquip block. It will run an infinite number of times because MenuMode 1002 never changes, but all within that single frame of onEquip. (If it's not crashing, then I assume scruggsy added a sanity check that ignores the entire While loop if you give MenuMode as a test.)

What you want is
begin OnEquip        if MenuMode 1002 == 1                set Equipped to 1                MessageBox "Please select the item you wish to modify. Note that this is meant for non-vanilla items!";        else                MessageBox "The Rune of Nothing requires you to be on the inventory screen.";        endifendbegin MenuMode 1002        if Equipped                        if GetButtonPressed 256 && RMouseButton == 0                                let OldObject := GetActiveMenuSelection;                                let RMouseButton := 1                        endif;                        if OldObject.IsClonedForm && RMouseButton == 1                                Message "This is already cloned, no need to move it to save data again!"                        elseif OldObject.IsActor && RMouseButton == 1                                Message "Invalid choice. Aborting...";                        elseif OldObject.IsArmor || OldObject.IsWeapon || OldObject.IsClothing || OldObject.IsAmmo || OldObject.IsIngredient && RMouseButton == 1                                set NewObject to CloneForm OldObject                                 player.addItem NewObject 1                                player.removeItem OldObject 1                                Message "Move to save data complete!";                        else                                 let RMouseButton := 0;                        endif;        endif;end


Some notes for the next steps - you'll want to remove all of the old items. Each time you use CloneForm it will create an entirely new form that, while it'll have the same name, will be treated by the game engine as a completely different item. You'll also want to disable the clicker, because when the player presses on the item they will use it (equip it or eat it).
User avatar
saharen beauty
 
Posts: 3456
Joined: Wed Nov 22, 2006 12:54 am

Post » Wed Dec 07, 2011 2:49 am

So now it works, sort of... it refuses to recognize the key even though if disabled GetKeyPress should still register when the left mouse button is pressed... Even the right-click to cancel doesn't work, which is strange.


scn CloneItemScriptref OldObjectref NewObjectshort Equippedshort RMouseButtonshort Qtybegin OnEquip        if MenuMode 1002 == 1		set Equipped to 1		set RMouseButton to 0;            MessageBox "Please select the item you wish to modify. Note that this is meant for non-vanilla items! Right-click to cancel the operation.";        else            MessageBox "The Rune of Nothing requires you to be in the inventory menu.";        endifend;begin MenuMode 1002        if Equipped				DisableKey 256;                        if IsKeyPressed 256 && RMouseButton == 0                              let OldObject := GetActiveMenuSelection;                              let RMouseButton := 1                        endif;			if IsKeyPressed 257				Message "Aborted by user"				EnableKey 256				set Equipped to 0			endif;                        if OldObject.IsClonedForm && RMouseButton == 1                              MessageBox "This is already cloned, no need to move it to save data again!"					EnableKey 256					set Equipped to 0                        elseif OldObject.IsActor && RMouseButton == 1                              MessageBox "Invalid choice. Aborting...";					EnableKey 256					set Equipped to 0                        elseif OldObject.IsArmor || OldObject.IsWeapon || OldObject.IsClothing || OldObject.IsAmmo || OldObject.IsIngredient && RMouseButton == 1                              set NewObject to CloneForm OldObject					set Qty to Player.GetItemCount OldObject                              player.AddItemNS NewObject Qty                              player.RemoveItemNS OldObject Qty                              MessageBox "Move to save data complete!";					EnableKey 256					set Equipped to 0                        else                               let RMouseButton := 0;                        endif;	endif;end;

User avatar
Donatus Uwasomba
 
Posts: 3361
Joined: Sun May 27, 2007 7:22 pm

Post » Tue Dec 06, 2011 8:52 pm

I'd guess your script is failing on the last line here
                        if IsKeyPressed 256 && RMouseButton == 0                              let OldObject := GetActiveMenuSelection;                              ...                        if OldObject.IsClonedForm && RMouseButton == 1

The first time through, OldObject won't be set so the last line will be if 0.IsClonedForm.... The function balks at this and.... I'm not exactly sure. I know with vanilla functions the entire script would stop running and would never run again (until you exit the game and restart). As this is an OBSE function... I'd guess it acts as a return.

Anyway, you can fix it by placing the OldObject checks within a RMouseButton check
begin MenuMode 1002        if Equipped                                DisableKey 256;                        if IsKeyPressed 256 && RMouseButton == 0                              let OldObject := GetActiveMenuSelection;                              let RMouseButton := 1                        endif;                        if IsKeyPressed 257                                Message "Aborted by user"                                EnableKey 256                                set Equipped to 0                        endif;                        if RMouseButton == 1                                if OldObject.IsClonedForm                                        MessageBox "This is already cloned, no need to move it to save data again!"                                        EnableKey 256                                        set Equipped to 0                                elseif OldObject.IsActor                                      MessageBox "Invalid choice. Aborting...";                                      EnableKey 256                                      set Equipped to 0                                elseif OldObject.IsArmor || OldObject.IsWeapon || OldObject.IsClothing || OldObject.IsAmmo || OldObject.IsIngredient                                      set NewObject to CloneForm OldObject                                      set Qty to Player.GetItemCount OldObject                                      player.AddItemNS NewObject Qty                                      player.RemoveItemNS OldObject Qty                                      MessageBox "Move to save data complete!";                                      EnableKey 256                                      set Equipped to 0                                else                                       let RMouseButton := 0;                                endif                        endif;        endif;end;

User avatar
Hannah Whitlock
 
Posts: 3485
Joined: Sat Oct 07, 2006 12:21 am

Post » Tue Dec 06, 2011 10:13 pm

Just threw in some debug print lines... Seems that it isn't getting out of the pre-click loop.
So the current problem code is this:

				if RMouseButton == 0	                                PrintToConsole "In click Mode"					if IsKeyPressed 256						set OldObject to GetActiveMenuSelection;                                        	set RMouseButton to 1                                	endif;					if IsKeyPressed 257						Message "Aborted by user"						EnableKey 256						set Equipped to 0					endif;				endif;				if RMouseButton == 1


Now I have been compiling this in CSE and have been using OBSE v0020... so I might have found a bug in either the CSE compiler or the OBSE beta.
User avatar
Rude Gurl
 
Posts: 3425
Joined: Wed Aug 08, 2007 9:17 am

Post » Tue Dec 06, 2011 4:21 pm

Oh, you have your scancodes jumbled. For http://cs.elderscrolls.com/constwiki/index.php/IsKeyPressed you want 1 for LMB, not 256.
User avatar
Reven Lord
 
Posts: 3452
Joined: Mon May 21, 2007 9:56 pm

Post » Tue Dec 06, 2011 4:39 pm

Yep, that loop's solved, such feisty keykodes! :P Now, to figure out why the other loop fails to complete once a qualified item is selected... the "oops" part works but not the specific conditions!

Speaking of which... Why isn't there a IsItem boolean in OBSE? You have actors, so why not items?
User avatar
Farrah Barry
 
Posts: 3523
Joined: Mon Dec 04, 2006 4:00 pm

Post » Wed Dec 07, 2011 4:08 am

Well, the second loop still isn't working. I have a feeling the conditional statements are to blame, although it prints the first debug line but then seems to skip the statements altogether, even the "oops" catchall at the end...

scn CloneItemScriptref OldObjectref NewObjectshort Equippedshort LMouseButtonshort Qtybegin OnEquip	if MenuMode 1002 == 1		set Equipped to 1		set LMouseButton to 0;		MessageBox "Please select the item you wish to modify. Note that this is meant for non-vanilla items! Right-click to cancel the operation.";	else		MessageBox "The Rune of Independence requires you to be in the inventory menu.";	endifend;begin MenuMode 1002	if Equipped == 1		DisableKey 256;		if LMouseButton == 0			PrintToConsole "RoI:In click Mode"			if IsKeyPressed 1				set OldObject to GetActiveMenuSelection;				PrintToConsole "RoI: Player has chosen %n", OldObject				set LMouseButton to 1			endif;			if IsKeyPressed 2				Message "Aborted by user"				EnableKey 256				set Equipped to 0			endif;		endif;		if LMouseButton == 1			PrintToConsole "RoI:Processing Item";			if OldObject.IsClonedForm                 	      set Equipped to 0				EnableKey 256				Message "This is already cloned, no need to move it to save data again!"			elseif OldObject.IsActor				set Equipped to 0				EnableKey 256				Message "Invalid choice. Aborting...";			elseif OldObject.IsArmor || OldObject.IsWeapon || OldObject.IsClothing || OldObject.IsAmmo || OldObject.IsIngredient				PrintToConsole "Acceptable item..."				set NewObject to CloneForm OldObject				PrintToConsole "RoI: %n cloned", OldObject				set Qty to Player.GetItemCount OldObject				player.AddItemNS NewObject Qty				player.RemoveItemNS OldObject Qty				PrintToConsole "RoI: %n swapped", NewObject				set Equipped to 0				EnableKey 256				Message "Move to save data complete!";			else				Message "Oops! Try again"				set LMouseButton to 0;			endif;		endif;	endif;end;


Here's the whole code again, and sorry for the double post. Hopefully this problem is fixed so I can package it up and get this uploaded today...
User avatar
OTTO
 
Posts: 3367
Joined: Thu May 17, 2007 6:22 pm

Post » Tue Dec 06, 2011 5:46 pm

The good old base object vs. reference problem. EditorIDs and variables prepended before the . can only be references - objects out in the world. Using a base object there stalls the script. So you want IsClonedForm OldObject
User avatar
FABIAN RUIZ
 
Posts: 3495
Joined: Mon Oct 15, 2007 11:13 am

Post » Tue Dec 06, 2011 4:57 pm

Finally got it working! :D I actually had one more problem but the culprit was the IsActor check, so I just removed it - I was worried that someone would try to select the player, causing a possible CTD, but the script and menu setup prevents that from happening anyways. Now to do some preventive code such as aborting the process when exiting the menu...

Thank you so much!
User avatar
K J S
 
Posts: 3326
Joined: Thu Apr 05, 2007 11:50 am


Return to IV - Oblivion