Journal window interaction question

mistahmikey

Active Member
I am trying to automatically add a collectible to a collection. The following code snippet is how I am trying to accomplish this:

Code:
	if ${EQ2UIPage[Journals,JournalsQuest](exists)}
	{
		echo Quest journal is open! 
		
		if ${EQ2UIPage[Journals,JournalsQuest].Child[button,TabPages.Collection.CollectionTemplate.AddButton](exists)}
		{
			echo Need to add a collectible!

			EQ2UIPage[Journals,JournalsQuest].Child[button,TabPages.Collection.CollectionTemplate.AddButton]:LeftClick
		}
	}
I see the "Need to add a collectible!" output, but alas, the LeftClick method does nothing. After looking closely at the Eq2UIElement datatype description on the wiki, I noticed the following:

NOTE: There are some "clone" windows that require their own Top-Level Object and ISXEQ2 Data Type. Those windows will be unresponsive through the EQ2UIPage Top-Level Object.
Am I running up against this issue? If so, can you point me to some information about how to create the required abstractions? Or is that something only Amadeus can do?
 

uiyice

Active Member
I do it possibly the dumbest, most pedantic way possible, but it works for me... Note that this solution is UI dependent, depends on the UI mod in use, and will break any time the UI panel changes.

Code:
; BLIND CLICK Add button.  Sensitive to UI changes, phase of the moon, etc...
; THIS IS FOR FLUFFY
;EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages].Child[Page,2].Child[Page,6].Child[Composite,2].Child[Page,1].Child[Button,4]:LeftClick
; THIS IS FOR DRUMS (Maybe Default)
EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages].Child[Page,2].Child[Page,6].Child[Composite,2].Child[Page,1].Child[Button,3]:LeftClick
I'm sure someone will come by with a better way...
 

Amadeus

The Maestro
Staff member
Yes, I never took the time to add this feature from directly with EQ2UI** related TLOs/etc.

Similarly to the post above, this is the script I used to use for adding items to collections:

Code:
variable(script) int ToClickX
variable(script) int ToClickY

function main(... Args)
{
    variable filepath ConfigPath="${LavishScript.HomeDirectory}/Scripts/"
    variable settingsetref Collections
    variable settingsetref Options
    variable bool checkcollection
    variable bool ResetClickLoc = FALSE
    variable string configfile
     variable int i = 1
     variable int Timer = 0
     
    configfile:Set[${ConfigPath}${Me.Name}_Collections.xml]
 
    LavishSettings:AddSet[Config File]
    LavishSettings[Config File]:Clear
    LavishSettings[Config File]:AddSet[${Me.Name}]
    LavishSettings[Config File]:AddSet[Options]
    LavishSettings[Config File]:Import[${configfile}]
 
    Collections:Set[${LavishSettings[Config File].FindSet[${Me.Name}]}]
    Collections:AddComment["Items set to TRUE will be considered 'junk' and destroyed"]
    Options:Set[${LavishSettings[Config File].FindSet[Options]}]
    
    if ${Args.Size} > 0
    {
        do
        {
            if (${Args[${Iterator}].Equal[ResetClickLoc]})
            {
                ResetClickLoc:Set[TRUE]
                echo "EQ2Collection.Init:: Resetting Mouse Click Location"
            }
        }
        while ${Iterator:Inc} <= ${Args.Size}
    }
    

    
    ;;;;;;;;;
    ;; Set Mouse Click Location
    ToClickX:Set[${Options.FindSetting[ToClickX,0]}]
    ToClickY:Set[${Options.FindSetting[ToClickY,0]}]
    if (${ToClickX} == 0 || ${ToClickY} == 0 || ${ResetClickLoc})
    {
        if (!${EQ2UIPage[Journals,JournalsQuest].IsMouseOver})
        {
            echo "EQ2Collection.Debug::  Please make sure that the journal window is open and the mouse is hovering over it."
            echo "EQ2Collection.Info::  End Script"
            return
        }
        echo "EQ2Collection.Init::  Examine a collection item in your inventory and then hover the mouse over the 'Add' button in the journal window."
        echo "EQ2Collection.Init::  After the snapshot is complete, please 'lock' your journal window so that it is always in the same location."
        echo "EQ2Collection.Init::  Taking a snapshot of the mouse location on 10..."
        do
        {
            wait 15
            echo "EQ2Collection.Init::  ${i}..."
        }
        while ${i:Inc} <= 10
        
        ToClickX:Set[${Mouse.X}]
        ToClickY:Set[${Mouse.Y}]    
        
        Options:AddSetting[ToClickX,${ToClickX}]
        Options:AddSetting[ToClickY,${ToClickY}]
        LavishSettings[Config File]:Export[${configfile}]
    }
    echo "EQ2Collection.Init::  'Add' button set at ${ToClickX}, ${ToClickY} on the screen."
    ;;
    ;;;;;;;;;
    
    
    Me:CreateCustomInventoryArray[nonbankonly]    
    do
    {
    if (!${Me.CustomInventory[${i}].IsInitialized})
    {
        Timer:Set[0]
        Me.CustomInventory[${i}]:Initialize
           ;do
           ;{
           ;    waitframe
           ;    Timer:Inc
           ;}
           ;while (!${Me.CustomInventory[${i}].IsInitialized} || ${Timer} < 300)
      }
        
        if ${Me.CustomInventory[${i}].IsCollectible}
        {
            checkcollection:Set[${Collections.FindSetting["${Me.CustomInventory[${i}].Name}",FALSE]}]
            LavishSettings[Config File]:Export[${configfile}]

            if !${Me.CustomInventory[${i}].AlreadyCollected}
            {
              echo "EQ2Collection.Info::  [${Me.CustomInventory[${i}].Name}] not yet collected.  Adding..."
                Me.CustomInventory[${i}]:Examine
                wait 5
                Mouse:SetPosition[${ToClickX},${ToClickY}]
                wait 5
                Mouse:LeftClick
              wait 5
              continue
            }
            else
            {
                if ${checkcollection}
                {
                    ; Destroy Item
                    echo "EQ2Collection.Info::  [${Me.CustomInventory[${i}].Name}] is Junk -- Destroying..."
                    Me.CustomInventory[${i}]:Destroy
                    wait 3
                }
                else
                {
                    echo "EQ2Collection.Info::  [${Me.CustomInventory[${i}].Name}] set to FALSE in xml file and will *not* be destroyed."
                }
            }
        }
    }
    while ${i:Inc}<=${Me.CustomInventoryArraySize}
    
    echo "EQ2Collection.Info::  End Script" 
}
I haven't used this in ages and don't currently play EQ2, so I don't know if it works or not. Someone reported a crash on examining collectable items, so I may need to update something in ISXEQ2 as well. But, you can give it a shot.
 

mistahmikey

Active Member
Thanks very much for the responses.

I am still a confused, however, about how the Eq2UIElement hierarchy works vis a vis the ui xml file structure. Looking at the Drums version of eq2ui_jounals_quest.xml, the statement I created:

EQ2UIPage[Journals,JournalsQuest].Child[button,TabPages.Collection.CollectionTemplate.AddButton]

seems to correctly retrieve the add button (the Label member returns "Add" as expected), but the LeftClick method does nothing.

However, the statement provided by uiyice:

EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages].Child[Page,2].Child[Page,6].Child[Composite,2].Child[Page,1].Child[Button,3]

also seems to correctly retrieve the add button (again, the Label member returns "Add"), but by doing it this way, the LeftClick method now works.

I have no idea what the difference is between these two approaches. Even more confusing is the fact I cannot "map" the widget hierarchy provided by uiyice to the structure defined by the xml file - based on the information in this file, it looks to me like the statement should be:

EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages].Child[Page,2].Child[Page,3].Child[Button,3]

but this does not work at all.

So, I have the following questions:

1) There is more hierarchy in uiyice's statement than appears in the xml file - how was that additional hierarchy derived?

2) Why does retrieving the button the way I did and the way uiyice did cause the LeftClick method to operate differently?

3) It appears that the mouse cursor must be over the Eq2UIPage in order for any of this to work - is this correct? If so, is there some way to retrieve the screen coordinates/dimensions of a Eq2UIPage so the mouse can be automatically moved over it?

4) I notice in the Amadeus's script, the appropriate mouse coordinates are manually determined by having the user place the mouse cursor over the "Add" button to record the position. Subsequently, the Lavishscript Mouse object is used to move the cursor to the recorded position and perform the click. Is there some reason the EQ2UIPage/EQ2UIElement objects were not used instead?
 

uiyice

Active Member
I am still a confused, however, about how the Eq2UIElement hierarchy works vis a vis the ui xml file structure. Looking at the Drums version of eq2ui_jounals_quest.xml...
It's legitimately confusing. Some of the UI structures are only divined via black magic and chicken entrails on a good day. (And UI modding experience, and lots of trial and error) It's been a long time since I trudged through that, so this post may or may not make any sense...

EQ2UIPage[Journals,JournalsQuest].Child[button,TabPages.Collection.CollectionTemplate.AddButton]

seems to correctly retrieve the add button (the Label member returns "Add" as expected), but the LeftClick method does nothing.
I think you've got your hands on the invisible Template used for each collection displayed in the Composite panel. Its add button in the template isn't wired to anything.

I have no idea what the difference is between these two approaches. Even more confusing is the fact I cannot "map" the widget hierarchy provided by uiyice to the structure defined by the xml file - based on the information in this file, it looks to me like the statement should be:
...
EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages].Child[Page,2].Child[Page,3].Child[Button,3]
vs
EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages].Child[Page,2].Child[Page,6].Child[Composite,2].Child[Page,1].Child[Button,3]

Your element #3 is the invisible CollectionTemplate
On the same page, Elemet #6 is the main Frame, that contains a Composite (Collection of pages, one for each collection), Page 1 of which is the first element (which is of type CollectionTemplate), where you find Button #3.

And I fully admit that I don't remember what the hell binds the Composite named CollectionComposite within the CollectionFrame, to the page named CollectionTemplate.

Also, when two collections match a filter (such as an Enchanted Gnoll Bone), I don't think I ever managed to get my hands on the second Add button.


1) There is more hierarchy in uiyice's statement than appears in the xml file - how was that additional hierarchy derived?
Composites and Templates (and chicken entrails). Also, don't overlook the NumChildren and ChildType elements of any page. They can be used to crudely 'browse' a page, figure out how many children it has, what type they are, and how they might line up with the XML file. Once you know a page has 3 children, Text/Composite/Scrollbar - it's easy to skim the UI file to figure out what you might have stumbled upon. (And if you touch a page the wrong way, you'll crash the client. It'll happen, you'll get used to it.)

2) Why does retrieving the button the way I did and the way uiyice did cause the LeftClick method to operate differently?
You found the CollectionTemplate. You need where it's embedded into a Composite.

3) It appears that the mouse cursor must be over the Eq2UIPage in order for any of this to work - is this correct? If so, is there some way to retrieve the screen coordinates/dimensions of a Eq2UIPage so the mouse can be automatically moved over it?
Hmm... I can't reproduce this. May futz later. How do you bring up the quest journal in the first place? (I use Item:Examine, and have Open on Loot checked).

4) I notice in the Amadeus's script, the appropriate mouse coordinates are manually determined by having the user place the mouse cursor over the "Add" button to record the position. Subsequently, the Lavishscript Mouse object is used to move the cursor to the recorded position and perform the click. Is there some reason the EQ2UIPage/EQ2UIElement objects were not used instead?
Possibly just different folks attacking problems different ways. Personally, I really hate to resort to coordinate based mouse clicking, but I've got a few scripts where I just couldn't figure out any other reliable way to get a job done... Amadeus might personally hate the EQ2Page hierarchy. ;)
 

mistahmikey

Active Member
I have written a little function that will search the Page/Element hierarchy to find the Nth element type and label.

Code:
function FindElement(string startElement,string searchType,string searchLabel,int whichOne,int foundSoFar=0)
{
	variable int childIndex
	variable int childCount

	childIndex:Set[0]
	childCount:Set[${${startElement}.NumChildren}]

	while ${childIndex:Inc} <= ${childCount}
	{
		variable string elementType

		elementType:Set[${${startElement}.ChildType[${childIndex}]}]

		if ${elementType.Equal[${searchType}]}
		{
			if (${searchLabel.Length} == 0 && !${${startElement}.Child[${searchType},${childIndex}].Label(exists)}) || ${${startElement}.Child[${searchType},${childIndex}].Label.Equal[${searchLabel}]}
			{
				foundSoFar:Inc

				if ${foundSoFar} == ${whichOne}
				{
					return "${startElement}.Child[${elementType},${childIndex}]"
				}
			}
		}

		variable string nextElement

		nextElement:Set["${startElement}.Child[${elementType},${childIndex}]"]

		call FindElement "${nextElement}" "${searchType}" "${searchLabel}" "${whichOne}" "${foundSoFar}"

		if ${Return.Length} > 0
		{
			return ${Return}
		}
	}

	return ""
}
A usage example to find the first "Add" Button encountered in the Journals page hierarchy:

Code:
if ${EQ2UIPage[Journals,JournalsQuest](exists)}
{
	while !${EQ2UIPage[Journals,JournalsQuest].IsVisible}
	{
		waitframe
	}

	echo Quest journal is open!

	call FindElement "EQ2UIPage[Journals,JournalsQuest].Child[Page,TabPages]" "Button" "Add" 1

	if ${Return.Length} > 0
	{
		echo Click ${Return} to consume a collectible!

		${Return}:LeftClick
	}
}
Note the the above example will "click" the button even when it is not actually displayed on the page. I was unable to find any way to determine the visibility of a Eq2UIElement. If someone knows how to do this, please advise.
 
Last edited:
Top Bottom