Generic "Get selected item ID in inventory menu" scr

Post » Tue Feb 15, 2011 9:03 pm

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
Adriana Lenzo
 
Posts: 3446
Joined: Tue Apr 03, 2007 1:32 am

Post » Wed Feb 16, 2011 12:03 am

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
jessica breen
 
Posts: 3524
Joined: Thu Aug 03, 2006 1:04 am

Post » Tue Feb 15, 2011 11:30 pm

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
mishionary
 
Posts: 3414
Joined: Tue Feb 20, 2007 6:19 am

Post » Tue Feb 15, 2011 8:58 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
Taylah Haines
 
Posts: 3439
Joined: Tue Feb 13, 2007 3:10 am

Post » Wed Feb 16, 2011 2:21 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
Racheal Robertson
 
Posts: 3370
Joined: Thu Aug 16, 2007 6:03 pm

Post » Wed Feb 16, 2011 12:32 am

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
bimsy
 
Posts: 3541
Joined: Wed Oct 11, 2006 3:04 pm

Post » Wed Feb 16, 2011 1:25 am

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
Danger Mouse
 
Posts: 3393
Joined: Sat Oct 07, 2006 9:55 am

Post » Wed Feb 16, 2011 6:34 am

Oh, you have your scancodes jumbled. For http://cs.elderscrolls.com/constwiki/index.php/IsKeyPressed you want 1 for LMB, not 256.
User avatar
Flash
 
Posts: 3541
Joined: Fri Oct 13, 2006 3:24 pm

Post » Wed Feb 16, 2011 9:12 am

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
Claire Vaux
 
Posts: 3485
Joined: Sun Aug 06, 2006 6:56 am

Post » Tue Feb 15, 2011 6:14 pm

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
Ashley Campos
 
Posts: 3415
Joined: Fri Sep 22, 2006 9:03 pm

Post » Wed Feb 16, 2011 4:53 am

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
renee Duhamel
 
Posts: 3371
Joined: Thu Dec 14, 2006 9:12 am

Post » Wed Feb 16, 2011 9:23 am

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
Everardo Montano
 
Posts: 3373
Joined: Mon Dec 03, 2007 4:23 am


Return to IV - Oblivion