Script doesn't see WindowInventory. Sanderling V17.11.19


#1

Hello. I’am trying to make a script for looting. But when i open wreck, i can’t click on loot all button. I see all properties of WindowInventory in API explorer. But script doesn’t catch it.

while(true)
{
var Measurement = Sanderling?.MemoryMeasurementParsed?.Value;
var wreck_type = Measurement?.WindowOverview[0].ListView.Entry[0];
Sanderling.MotionExecute(wreck_type.MouseDoubleClick(MouseButtonIdEnum.Left));
Sanderling.InvalidateMeasurement();
Host.Log("before delay = "+Measurement?.WindowInventory?[0]?.ButtonText?.FirstOrDefault(text => text.Text.RegexMatchSuccessIgnoreCase("Loot All")));
Host.Delay(2250);
Host.Log("After delay = "+Measurement?.WindowInventory?[0]?.ButtonText?.FirstOrDefault(text => text.Text.RegexMatchSuccessIgnoreCase("Loot All")));

Host.Delay(40000);
}

"before delay = ", "After delay = " are empty.
When i run script again (with already opened inventory with wreck) its all OK.
before delay = Sanderling.Interface.MemoryStruct.UIElementText
After delay = Sanderling.Interface.MemoryStruct.UIElementText
What iam doing wrong?


#2

to print a variable with host log you need to print his value and you need one of this formats:

Host.Log(variable); if is already a string or text or int 
Host.Log("this is a text" +variable+ "");

That only if the variable is a string or int or date format . You cannot print an array’ for example. Or add at the end like that: variable?.ToString();

Host.Log(variable.ToString()); 
Host.Log("this is a text" +variable.ToString()+ "");

in your example , you have:

Host.Log("before delay = "+Measurement?.WindowInventory?[0]?.ButtonText?.FirstOrDefault(text =>
 text.Text.RegexMatchSuccessIgnoreCase("Loot All")));

and it should be

Host.Log("before delay = "+Measurement?.WindowInventory?[0]?.ButtonText?.FirstOrDefault(text => text.Text.RegexMatchSuccessIgnoreCase("Loot All"))+"");

if it is a string, but actually you ask him to print an button with the text “loot all”. it is not a string
if you change in

.RegexMatchSuccessIgnoreCase(“Loot All”)).ToString()+"");

it will print the value of … something… not printable( an array, most probable)

it is simpler to define the button , and then is he is not null ( this means the variable has a value) then you print something.
like I do in my script( I will adapt to understand better):

                        var LootButton = Measurement?.WindowInventory?[0]?.ButtonText?.FirstOrDefault(text => text.Text.RegexMatchSuccessIgnoreCase("Loot All"));

                    if (LootButton != null) // you can add that
                        {
                         Host.Log("               Teleporting some loot!");
                        Sanderling.MouseClickLeft(LootButton);
                        }

In the end the variable LootButton is a variable built ( identify)like that:

you say at bot to identify the place on:
Measurement => WindowInventory =>[0] =>ButtonText => first or default (where text is loot all ( you have here a bool true if is the text, if not then the button = null, => didn’t exist))
next, if the button exists, then you click on him
Actually, you are not interested in what value has lootbutton
more basics example you can find here:
http://zetcode.com/lang/csharp/basics/

going back at your code you use

var Measurement = Sanderling?.MemoryMeasurementParsed?.Value;
is something constant, you need to evaluate all the time the value from the right of =
so it should be ( better)


Sanderling.Parse.IMemoryMeasurement Measurement => 
Sanderling?.MemoryMeasurementParsed?.Value;

next

var wreck_type is the first item in the entry of listview. if somehow this first item is the sun, … can you loot him??

isn’t better to create a list with items from entry, sortedafter the wreck text from inside?

Parse.IOverviewEntry[] ListOverviewWreck =>
    WindowOverview?.ListView?.Entry
    ?.Where(entry => entry?.Name?.RegexMatchSuccessIgnoreCase("wreck") ?? true)
   ?.OrderBy(entry => entry?.DistanceMax ?? int.MaxValue)
.ToArray();

and then double click on first one?

Sanderling.MotionExecute(ListOverviewWreck?.FirstOfDefault().MouseDoubleClick(MouseButtonIdEnum.Left));

( if by double clicking on wreck in overview you open the cargo)
in this case you have an array with selected items ( wrecks) and not the sun, or a rat, or other player or a station and you doubleclick only on them
(finished to edit, I had copy-paste codes from my scripts and i had some errors, to adapt at your example/needs)


#3

Ty Kaboonus. I will try it out. Host.log was just some sort of debugging=). When i used moseclick or mousemove with:

Measurement?.WindowInventory?[0]?.ButtonText?.FirstOrDefault(text => text.Text.RegexMatchSuccessIgnoreCase("Loot All"))

The cursor didn’t move\click on “loot all” just after I opened wreck with

Sanderling.MotionExecute(wreck_type.MouseDoubleClick(MouseButtonIdEnum.Left));


#4

I know it was for debugging, and in fact it shows there is someting there ( Sanderling.Interface.MemoryStruct.UIElementText)

I tried to explain you the entire process, what you can use and how you can use all that


#5

you should not use index to accessing it as there should not be more then one inventory window anyway

try this

var LootButton = memoryMeasurement?.WindowInventory?.FirstOrDefault()?.ButtonText?.FirstOrDefault(text => text.Text.RegexMatchSuccessIgnoreCase("Loot"));

#6

except the case when you have active ship in a second windowinventory , the third when you have the fleet mate etc.

2°more than that, the adress on index is faster than " I have more than one, I take first or the default… index" in the context when you have to face the open cargo window and clicking on overview to open next cargo and have to be sure you clean up the button loot all
3° FirstOrDefault() count 16 characters [0] only 3 and number of characters in the file it determine the filesize. On A-bot you could make your application of 1000Gb, I have only 100 kilo( usable 98) for a script ( and is droping if you have to explain some things.

Overall speaking yes, is better to use firstordefault() , but sometimes you have to address directly


#7

Now i’m looking through C# basic syntax :smile:.