SRL Archive - SRL Archives

ChooseOptionMultiEx


Tim0suprem0

2010-06-15 17:07:10

Hi guys,

When the Optionbox is as big as the screen (top to bottom), I get
[Runtime Error] : Exception: Access violation at address 041AAE36 in module 'WizzyPlugin.dll'. Read of address 00000000 in line 558 in script C:\Program Files\SCAR 3.23 Beta\includes\SRL\SRL\Core\Text.scar
which is super annoying when my players are on a busy world and trying to find the fishing spot because it instantly kills the script.

Here is ChooseOptionMultiEx (where the problem is)
{*******************************************************************************
function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean;
By: Wizzup?, Nava2, and N1ke!
Description: Finds Popup menu, then clicks on it.
Will look for the first string first and so on.
It will search for the Text Type you input valid arguments are
'action', 'player': The white text
'npc': The yellow text
'object': The cyan text
'all': Searches for all colors of text.
Will default to 'all'.
*******************************************************************************}
function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean;
var
B,OptionBox: TBox;
TPA, TextTPA: TPointArray;
aTPA: T2DPointArray;
I, H, HH, ii, L: Integer;
Colors,SearchCols: TIntegerArray;
begin
Result := False;
GetClientDimensions(B.X2, B.Y2);
B.X1 := 0;
B.Y1 := 0;
Dec(B.X2);
Dec(B.Y2);
FindColorsTolerance(TPA, 4016722, B.X1, B.Y1, B.X2, B.Y2, 0);
If Length(TPA) < 10 Then
Exit;
B.X2 := 0;
B.Y2 := 0;
aTPA := SplitTPAEx(TPA, 20, 20);
SortATPASize(aTPA, True);
B := GetTPABounds(aTPA[0]);
Colors := [13034990, 4231423, 2070783, 65535, 16776960, 9812166];
TextType := LowerCase(TextType);
case TextType of
'action', 'player': SearchCols := [0,5];
'item' : SearchCols := [1,2];
'npc' : SearchCols := [3];
'object': SearchCols := [4];
else
SearchCols := [0,1,2,3,4,5];
end;
L := High(SearchCols);
SetLength(aTPA,l+1);
for i := 0 to l do
FindColorsTolerance(aTPA[I], Colors[SearchCols[I]], B.X1, B.Y1, B.X2, B.Y2, 3);
TPA := MergeATPA(aTPA);
aTPA := SplitTPAEx(TPA, 7, 1);
L := High(aTPA);
H := High(Texts);
SortATPAFromFirstPoint(ATPA, Point(OptionBox.X1, optionbox.y1));
for I :=0 To H do
begin
TextTPA := LoadTextTPA(Texts[i], UpChars, HH);
for ii := 0 to L do
If FindTextTPAInTPA(HH, TextTPA, aTPA[ii], TPA) Then
begin
Result := True;
case Action of
ClickLeft: MouseBoxEx(B.x1 + 5, TPA[0].Y, B.x2 - 5, TPA[0].Y + 5,5, 1);
Move: MouseBoxEx(B.x1 + 5, TPA[0].Y, B.x2 - 5, TPA[0].Y + 5,5, 3);
Nothing: begin end;
else
srl_warn('ChooseOptionMultiEx', 'ClickRight not a valid click for RS menus!', warn_AllVersions);
end;
Exit;
end;
end;
MMouse(B.X1 - 50, B.Y1 - 50, 40, B.Y2 - B.Y1);
Wait(200 + Random(100));
end;


The error on line 558 is SortATPAFromFirstPoint(ATPA, Point(OptionBox.X1, optionbox.y1)), but the problem is that when the optionbox is that big,

aTPA := SplitTPAEx(TPA, 20, 20);
SortATPASize(aTPA, True);
B := GetTPABounds(aTPA[0]);

splits the colors on each side of the optionbox into to two TPA's, and then only uses the one on the left side (atpa[0]) for the TBox of where to look for the text.

So FindColorsTolerance(aTPA, Colors[SearchCols], B.X1, B.Y1, B.X2, B.Y2, 3) is basically just looking at a vertical line, because B.X1 and B.X2 are equal.

That means that aTPA doesn't get filled with any of the text color it's looking for, so when SortATPAFromFirstPoint gets called, it gets passed an empty ATPA and then it's out of range when it tries to sort the TPAs.

My question is, why split it up in the first place? I'm pretty sure using
  FindColorsTolerance(TPA, 4016722, B.X1, B.Y1, B.X2, B.Y2, 0);
If Length(TPA) < 10 Then
Exit;
B.X2 := 0;
B.Y2 := 0;
B := GetTPABounds(TPA);
//aTPA := SplitTPAEx(TPA, 20, 20);
//SortATPASize(aTPA, True);
//B := GetTPABounds(aTPA[0]);
would work fine, and it fixes the problem.

Narcle

2010-06-15 17:15:29

I believe the only reason they split that TPA is to make sure its getting the right box. In case there are other colors on the screen, since ChooseOption looks at the whole screen.

I've had similar problems running in Simba with the box being to big… I've actually already reported this but I think it was in Dev section. It doesn't crash it in Simba just makes the mouse go weird.

Tim0suprem0

2010-06-15 17:19:49

From: Narcle
I believe the only reason they split that TPA is to make sure its getting the right box. In case there are other colors on the screen, since ChooseOption looks at the whole screen.

I've had similar problems running in Simba with the box being to big… I've actually already reported this but I think it was in Dev section. It doesn't crash it in Simba just makes the mouse go weird.


So is there some kind of fix where it will find the right box and not crash? I'm waiting to release my fisher/cooker because it crashes everytime with this.

EDIT: Does anyone know of another instance in RS where the optionbox edge color occurs?

Wanted

2010-06-15 21:41:29

I've been debating over the best solution to this problem, apparently when the options box becomes large enough the color 4016722 does not go around the entire border, some times only the left side in fact, I believe by adding another color search (4409686 the color of the horizontal outline bar that divides the words choose option and walk here) and then merging it with the other TPA it should always yield at least an upside down L shaped TPA which you can grab accurate bounds with and not cause the other error.

I want you to replace your ChooseOptionMultiEx function with this and tell me if it works

Edit: I had to fix something urgent in Login.scar, just update your SRL to the latest and tell me if it works the function seen below is already in there.

{*******************************************************************************
function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean;
By: Wizzup?, Nava2, and N1ke!
Description: Finds Popup menu, then clicks on it.
Will look for the first string first and so on.
It will search for the Text Type you input valid arguments are
'action', 'player': The white text
'npc': The yellow text
'object': The cyan text
'all': Searches for all colors of text.
Will default to 'all'.
*******************************************************************************}
function ChooseOptionMultiEx(Texts: TStringArray; TextType: String; Action: fnct_ActionOptions): Boolean;
var
B,OptionBox: TBox;
TPA, TPA1, TPA2, TextTPA: TPointArray;
aTPA: T2DPointArray;
I, H, HH, ii, L: Integer;
Colors,SearchCols: TIntegerArray;
begin
Result := False;
GetClientDimensions(B.X2, B.Y2);
B.X1 := 0;
B.Y1 := 0;
Dec(B.X2);
Dec(B.Y2);
FindColorsTolerance(TPA1, 4016722, B.X1, B.Y1, B.X2, B.Y2, 0);
FindColorsTolerance(TPA2, 4409686, B.X1, B.Y1, B.X2, B.Y2, 0);
TPA := CombineTPA(TPA1, TPA2);
If Length(TPA) < 10 Then
Exit;
B.X2 := 0;
B.Y2 := 0;
aTPA := SplitTPAEx(TPA, 20, 20);
SortATPASize(aTPA, True);
B := GetTPABounds(aTPA[0]);
Colors := [13034990, 4231423, 2070783, 65535, 16776960, 9812166];
TextType := LowerCase(TextType);
case TextType of
'action', 'player': SearchCols := [0,5];
'item' : SearchCols := [1,2];
'npc' : SearchCols := [3];
'object': SearchCols := [4];
else
SearchCols := [0,1,2,3,4,5];
end;
L := High(SearchCols);
SetLength(aTPA,l+1);
for i := 0 to l do
FindColorsTolerance(aTPA[I], Colors[SearchCols[I]], B.X1, B.Y1, B.X2, B.Y2, 3);
TPA := MergeATPA(aTPA);
aTPA := SplitTPAEx(TPA, 7, 1);
L := High(aTPA);
H := High(Texts);
SortATPAFromFirstPoint(ATPA, Point(OptionBox.X1, optionbox.y1));
for I :=0 To H do
begin
TextTPA := LoadTextTPA(Texts[i], UpChars, HH);
for ii := 0 to L do
If FindTextTPAInTPA(HH, TextTPA, aTPA[ii], TPA) Then
begin
Result := True;
case Action of
ClickLeft: MouseBoxEx(B.x1 + 5, TPA[0].Y, B.x2 - 5, TPA[0].Y + 5,5, 1);
Move: MouseBoxEx(B.x1 + 5, TPA[0].Y, B.x2 - 5, TPA[0].Y + 5,5, 3);
Nothing: begin end;
else
srl_warn('ChooseOptionMultiEx', 'ClickRight not a valid click for RS menus!', warn_AllVersions);
end;
Exit;
end;
end;
MMouse(B.X1 - 50, B.Y1 - 50, 40, B.Y2 - B.Y1);
Wait(200 + Random(100));
end;

Tim0suprem0

2010-06-15 23:47:38

From: IceFire908
I've been debating over the best solution to this problem, apparently when the options box becomes large enough the color 4016722 does not go around the entire border, some times only the left side in fact, I believe by adding another color search (4409686 the color of the horizontal outline bar that divides the words choose option and walk here) and then merging it with the other TPA it should always yield at least an upside down L shaped TPA which you can grab accurate bounds with and not cause the other error.

I want you to replace your ChooseOptionMultiEx function with this and tell me if it works

Edit: I had to fix something urgent in Login.scar, just update your SRL to the latest and tell me if it works the function seen below is already in there.



The appearance of the edgecolor on only one side was really weird. As I was testing this out today and debugging I noticed that with DebugTPA of 4016722 it found the color on both sides every time, whereas there were some times that after doing SplitTPAEx(tpa, 20, 20) where DebugATPA highlighted only the left side. This happened only when the optionbox was as big from the client top to bottom (and 4016722 wasn't there on the bottom of the optionbox).

Anyways your fix worked perfectly for me, and I believe it is a good complete solution to both problems. So thanks! :D

Wanted

2010-06-15 23:52:10

From: Tim0suprem0
The appearance of the edgecolor on only one side was really weird. As I was testing this out today and debugging I noticed that with DebugTPA of 4016722 it found the color on both sides every time, whereas there were some times that after doing SplitTPAEx(tpa, 20, 20) where DebugATPA highlighted only the left side. This happened only when the optionbox was as big from the client top to bottom (and 4016722 wasn't there on the bottom of the optionbox).

Anyways your fix worked perfectly for me, and I believe it is a good complete solution to both problems. So thanks! :D


Just to clear things up, it's to my understanding that SplitTPA works by removing points that are not within a certain distance of eachother, so when two different halfs of a TPA are too far away from eachother it splits them (depending on your w/h ect..) thats why adding the horizontal color brings the two together and gives an accurate bounds that won't throw an access violation of somesort.

Glad to hear it worked :)

Tim0suprem0

2010-06-15 23:55:32

From: IceFire908
Just to clear things up, it's to my understanding that SplitTPA works by removing points that are not within a certain distance of eachother, so when two different halfs of a TPA are too far away from eachother it splits them (depending on your w/h ect..) thats why adding the horizontal color brings the two together and gives an accurate bounds that won't throw an access violation of somesort.

Glad to hear it worked :)


Ahhh ok, the description says "Splits the points with max X and Y distances W and H to their own TPointArrays." so I assumed it would keep all the points and just divide them up, but I was too lazy to go digging around the source.

Very creative solution, thanks again bro ;)

Wanted

2010-06-16 00:00:56

From: Tim0suprem0
Ahhh ok, the description says "Splits the points with max X and Y distances W and H to their own TPointArrays." so I assumed it would keep all the points and just divide them up,


Actually I think it does, I worded it wrong.

It's kinda like the contiguous United states, even though one cluster may be huger than another it still keeps all the clusters based on their distance from the nearest cluster. I'm pretty sure it keeps all points, Naum has a good tutorial on it.

Tim0suprem0

2010-06-23 16:28:45

EDIT: Got impatient so went to IRC. Narcle fixed :D

Sorry to bring this back up, but I didn't think it deserved a whole new thread. Can we add white to the Colors array in ChooseOptionMultiEx? That way you can select the '->' when you need to use an item on another one, as well as selecting a player's name, if necessary.

  Colors := [13034990, 4231423, 2070783, 65535, 16776960, 9812166, 16777215];
TextType := LowerCase(TextType);
case TextType of
'action', 'player': SearchCols := [0,5,6];
'item' : SearchCols := [1,2];
'npc' : SearchCols := [3];
'object': SearchCols := [4];
else
SearchCols := [0,1,2,3,4,5,6];
end;

Wanted

2010-06-23 23:17:25

Done. (I think?)

Narcle

2010-07-20 18:33:41

Didn't feel like making a new post, and I believe its associated with this fix.

1. It no longer searches top to bottom from text all the time, its sometimes selects the bottom most option. Say you give it a item name like "rune" instead of say picking it up (Take), instead it'll just examine it.

2. The variable "OptionBox" has nothing declared to it and is used for the splittpa sorting. I've tried a couple different ways and I have not been able to fix problem 1.

Any ideas?

Wanted

2010-07-21 01:09:50

I actually got the same error again today for the first time since the fix. Dunno

NCDS

2010-07-21 01:14:40

From: Narcle
Didn't feel like making a new post, and I believe its associated with this fix.

1. It no longer searches top to bottom from text all the time, its sometimes selects the bottom most option. Say you give it a item name like "rune" instead of say picking it up (Take), instead it'll just examine it.

2. The variable "OptionBox" has nothing declared to it and is used for the splittpa sorting. I've tried a couple different ways and I have not been able to fix problem 1.

Any ideas?

1. Could just be misreading the text? That happens for me quite often.

2. :cartman: 1:14 a.m.

Narcle

2010-07-21 11:31:34

From: NCDS
1. Could just be misreading the text? That happens for me quite often.

2. :cartman: 1:14 a.m.


I don't think its misreading it. I changed it to "ake Nat" for example and it works every time, but putting just "rune" sometimes it will examine instead.