Jump to content
MarkD

Make Scar find/read/save text

Recommended Posts

Well, that worked pretty good :-)

 

[scar]program FindTextBox;

var

TxtBox,x,y,t,length: Integer;

List: TPointArray;

Bmp: TSCARBitmap;

Cl: TSCARClient;

 

Procedure InitDTM;

Begin

TxtBox := DTMFromString('78DA6334666260D807C448606F3E2F986684F' +

'219CD81F21750D5945AB1A1AA0903CAEF4755F3EB58148A1A007F' +

'110728');

End;

 

Procedure InitBMP;

Begin

Bmp := TSCARBitmap.Create('');

Bmp := GetClient.Capture;

Cl := SetClient(TSCARBitmapClient.Create(Bmp));

end;

 

begin

ClearDebug;

InitDTM; //Load DTM

InitBMP; //Load BMP

SetLength(List, 40); //reserve some playground

List[0] := Point(0,0); //make sure there is at least something

//to prevent issues when searching

for t := 0 to 19 do

begin

if(FindDTM(TxtBox,x,y,0,0,1680,1050))

then begin

WriteLn(x);

WriteLn(y);

//MoveMouse(x,y); //point to match

//ClickMouse(x,y,False);

Wait(200); //for debug

Bmp.Pixels[x,y] := clRed; //paint it

List[t] := Point(x,y); //add to list

//ClickMouse(715,949,False);

end;

end;

SetClient(Cl).Free;

Bmp.Free;

length := SizeOf(List);

for t := 0 to length do

begin

// WriteLn(List[t]);

end;

end.[/scar]

 

I have been looking for a TPointToStr function, but it isn't really necessary. I'll probably erase that bit in the future.

Mouse actions don't work on canvas, so I guess I'll have to find the DTMs first, set the client back to my browser and start clicking there. Shouldn't be to much of a problem.

 

The problems with OCR still persist, so I'll try to put things together first (implement DTM in main program and do a little clean up) and give OCR another try. Perhaps OCR gives less trouble when reading from canvas then directly from screen, we'll see.

Link to comment
Share on other sites

Well, that worked pretty good :-)

 

[scar]program FindTextBox;

var

TxtBox,x,y,t,length: Integer;

List: TPointArray;

Bmp: TSCARBitmap;

Cl: TSCARClient;

 

Procedure InitDTM;

Begin

TxtBox := DTMFromString('78DA6334666260D807C448606F3E2F986684F' +

'219CD81F21750D5945AB1A1AA0903CAEF4755F3EB58148A1A007F' +

'110728');

End;

 

Procedure InitBMP;

Begin

Bmp := TSCARBitmap.Create('');

Bmp := GetClient.Capture;

Cl := SetClient(TSCARBitmapClient.Create(Bmp));

end;

 

begin

ClearDebug;

InitDTM; //Load DTM

InitBMP; //Load BMP

SetLength(List, 40); //reserve some playground

List[0] := Point(0,0); //make sure there is at least something

//to prevent issues when searching

for t := 0 to 19 do

begin

if(FindDTM(TxtBox,x,y,0,0,1680,1050))

then begin

WriteLn(x);

WriteLn(y);

//MoveMouse(x,y); //point to match

//ClickMouse(x,y,False);

Wait(200); //for debug

Bmp.Pixels[x,y] := clRed; //paint it

List[t] := Point(x,y); //add to list

//ClickMouse(715,949,False);

end;

end;

SetClient(Cl).Free;

Bmp.Free;

length := SizeOf(List);

for t := 0 to length do

begin

// WriteLn(List[t]);

end;

end.[/scar]

 

I have been looking for a TPointToStr function, but it isn't really necessary.

That's really simple to do, here:

 

[scar]function PointToStr(pt: TPoint): string;

begin

Result := (IntToStr(pt.X) + ',' + IntToStr(pt.Y));

end;

 

function CoordsToStr(X, Y: Integer): string;

begin

Result := (IntToStr(X) + ',' + IntToStr(Y));

end;

 

begin

WriteLn(PointToStr(Point(Random(101), Random(101))));

WriteLn(CoordsToStr(Random(101), Random(101)));

end.[/scar]

 

-Jani

Link to comment
Share on other sites

So, the current version of the project:

[scar]//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//

// Title: TBRPG gatherer (Ikariam version) //

// Purpose: Gathering information from TBRPGs //

// Status: Work In Progress //

// Author: MarkD aka MatVis //

// //

// To do: //

// - after DTM, switch back to client, click//

// coords, read data and return to BMP //

// - OCR //

// //

// Thanks to all who've helped! //

//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//

 

program TBRPGgIV;

 

var

x_a,y_a : array [0..5] of Integer;

xi,yi,watercheck,water,TxtBox,x,y,t,a_i,length : Integer;

List: TPointArray;

Bmp: TSCARBitmap;

Cl: TSCARClient;

 

//list of procedures

procedure MoveNClick(mx,my : integer);

begin

Wait(632);

MoveMouse(mx,my);

Wait(221);

MouseBtnDown(mx,my, False);

Wait(198);

MouseBtnUp(mx + 38, my + 2, False);

end;

 

Procedure InitDTM;

Begin

TxtBox := DTMFromString('78DA6334666260D807C448606F3E2F986684F' +

'219CD81F21750D5945AB1A1AA0903CAEF4755F3EB58148A1A007F' +

'110728');

End;

 

procedure InitXYArrays;

begin

for a_i := 0 to 5 do

begin

x_a[a_i] := a_i+1;

y_a[a_i] := a_i+1;

end;

end;

 

Procedure InitBMP;

Begin

Bmp := TSCARBitmap.Create('');

Bmp := GetClient.Capture;

Cl := SetClient(TSCARBitmapClient.Create(Bmp));

end;

 

Procedure FreeBMP;

Begin

SetClient(Cl).Free;

Bmp.Free;

end;

 

function PointToStr(pt: TPoint): string;

begin

Result := (IntToStr(pt.X) + ',' + IntToStr(pt.Y));

end;

 

//main program

begin

ClearDebug;

InitDTM;

InitXYArrays;

SetLength(List, 30); //reserve some playground

List[0] := Point(0,0); //make sure there is at least something

//to prevent issues when searching

water := 12418074; //define water

//var 12288039 11564307 12222763

 

for xi := 0 to 1 do

begin

Wait(697);

 

for yi := 0 to 2 do

begin

MoveNClick(594,949);

TypeText(IntToStr(x_a[xi])); //give new coords for left box

 

MoveNClick(658,949);

TypeText(IntToStr(y_a[yi])); //give new coords for right box

 

Wait(818);

MoveMouse(715,949);

Wait(557);

ClickMouse(715,949,False); //click go

Wait(567);

watercheck := GetColor(945,600);

WriteLn(IntToStr(watercheck));

if ((watercheck = water)) then //if there is water instead of an island,

Continue; //skip to next coordinate

Wait(121);

MoveMouse(945,600); //move mouse to island

Wait(420);

ClickMouse(945,600,False); //click island

 

//switching to island view

 

InitBMP;

for t := 0 to 19 do

begin

if(FindDTM(TxtBox,x,y,0,0,1680,1050))

then begin

WriteLn(x);

WriteLn(y);

Bmp.Pixels[x,y] := clRed; //paint it

List[t] := Point(x,y); //add to list

end;

 

end;

 

FreeBMP; //destruct

 

length := (SizeOf(List) - 1);

for t := 0 to length do

begin

WriteLn(PointToStr(List[t]));

end;

WriteLn(IntToStr(length));

 

Wait(884);

MoveMouse(80,220);

ClickMouse(80,225,False); //return to world screen

 

//switching to world view

 

end;

 

end;

 

WriteLn('Done');

end.

[/scar]

 

Perhaps OCR isn't even necessary. All characters are selectable, so if there is any way to make SCAR use ctrl+c and store this into a string, it's fine as well. If the storing part is a problem but ctrl+c works, I could copy the text to an instance of notepad and read from there. If ctrl+c doesn't work, I could even try it with the Right mouse button.

Link to comment
Share on other sites

Nice work, MarkD!

 

Btw, replace:

 

[scar]Procedure InitBMP;

Begin

Bmp := TSCARBitmap.Create('');

Bmp := GetClient.Capture;

Cl := SetClient(TSCARBitmapClient.Create(Bmp));

end;[/scar]

 

..with this:

 

[scar]Procedure InitBMP;

Begin

Bmp := GetClient.Capture;

Cl := SetClient(TSCARBitmapClient.Create(Bmp));

end;[/scar]

 

Sorry, it was my bad I used that TSCARBitmap.Create('') there, even though its not needed at all (and actually SHOULDN'T be used, because GetClient.Capture builds the TSCARBitmap)

 

Also, remember to add that FreeDTM to the end of the script, as it is a good habbit to free everything that you have loaded with SCAR.

Link to comment
Share on other sites

The text that you have entered is too long (481238 characters). Please shorten it to 25000 characters long.

So the result is missing.

 

Couldn't figure out why Bmp should be filled twice, now I know why. It shouldn't :-)

 

I've been trying to get some reading done. So I started Notepad (not the ++ version, redefining fonts is a pain in the * there) and typed ' More text! ' in Verdana 12.

[scar]begin

ClearDebug;

c := LoadCharsFromFont2('Verdana', 12, False, False, False, False);

s := 'More text!'

for x := 1 to 400 do

begin

for y := 1 to 400 do

begin

WriteLn(IsTextAtEx(x,y,s,50,c,false,false,0,0,0));

end;

end;

end.[/scar]

 

I really DON'T recommend you to try this at home. Why?

Successfully executed (2798028,5084 ms)

 

Output (removed).

 

Summary: 0's till ln 110110, 1's till 110145, 0's till 110451, 1's till 132673, 0's till 132898, 1's till 132936, 0's till 133007, a lone zero at 133008 (?), 1's till 133030, 0's till 113111, more like that.

Next question: Is there any usefulness in these numbers? The text was on the first line of notepad, why does it take 275 to the right to find something? Is this because of the tolerance? Are there quicker ways to detect text?

 

And yes, I know it would've been clearer to switch x and y in the increment process (it's in a way reading top to bottom now).

Link to comment
Share on other sites

So, I'm pretty much stuck here.

If I type a simple text in Notepad and use IsTextAt at the upper left coordinate of the first letter, it just says no. Whatever the tolerance is I give, whatever the color is, it just says no.

GetTextAt only gives rubbish.

 

I've tried both with SetFontSmoothing(false) in the script, the darn thing just doesn't give me any clues where to look for the problem.

Is there anyone with experience in SCAR OCR that DID produce a working script? I haven't seen any of them so far.

 

Eventually, I could hack my way around OCR (just click and copy about anything that looks like something valuable, paste it and sort it out later). But I won't. At least not until I've run out of options, but the OCR thingy should be working. So why isn't it?

Link to comment
Share on other sites

you have to disable font smoothing before you start notepad or it won't always update. It's best to just disable font smoothing globally before working with SCAR. On a side-note, you can get the content of the notepad window without OCR with 3.35 :P

 

Yeah that window api again! xD...

 

Remember that FindTextTPA, or w/e. You can use TPA's and other things for text too. You can create a bitmap FROM a font!

 

So if say, we wanted to write our own GetTextAt. I would go about it like this: Get the font's one letter bitmap into memory. Then at (x, y) search from there and all the way to the right as well. So it would be like...while not findbitmap(W); x := x + Width(W). This function would get a lot more complex with all its options though...for like the font's bitmap width and height. At X, Y search in a box with x until the end of the screen or you can set. Then Y would be the font bitmaps height. Then it could try to find the bitmap in the full box or w/e....if you get my idea

 

We could make like a box function for it. FindBitmapBox for x, y for width and height of bitmap, etc, etc.

Edited by LordJashin
Link to comment
Share on other sites

The font smoothing was updated. My entire computer had font smoothing disabled the moment I ran the script (hard not to notice).

 

Perhaps Janilabo has some good idea's, he's the one who wrote GetTextAt. I don't remember a FindTextTPA and I can't find anything like it on the TPA wiki. Yes, we can create bitmaps from fonts (pretty obvious, a font is actually a collection of bitmaps in some way). I'm not entirely sure what you're trying to do though. Are you suggesting to locate the coordinate of the first letter and read it by trial and error (compare it to every character in the alfabet available)?

Link to comment
Share on other sites

Well, not sure if these will help with your problem here, but anyways, I rewrote today my GetTextAt & IsTextAt.

They are now based on GetTextAtEx2, which is a fixed version of GetTextAtEx (with fix for that good ol' width problem of the OCR)

 

Here:

 

function GetTextAtEx2(x, y, Tolerance, Chars: Integer; CheckShadow, CheckOutline: Boolean; MinSpacing, MaxSpacing, TextColor, TextLength: Integer; Strict: Boolean; Range: TCharRange): string;
var
 e, l, t: Integer;
 b: TSCARBitmap;
 s: string;
begin
 if (TextLength < 1) then
   Exit;
 t := TextLength;
 if (t > 9) then
   t := 10;
 while (l < TextLength) do
 begin
   s := GetTextAtEx((x + e), y, Tolerance, Chars, CheckShadow, CheckOutline, MinSpacing, MaxSpacing, TextColor, t, Strict, Range);
   Result := (Result + s);
   l := (l + Length(s));
   if ((l + t) > TextLength) then
     t := (TextLength - l);
   b := CreateBitmapFromText(s, Chars, TextColor);
   e := (e + b.Width);
   b.Free;
 end;
end;

function GetTextAt(x, y, Tolerance, Chars, MinSpacing, MaxSpacing, TextColor, TextLength: Integer; Strict: Boolean; Range: TCharRange): string;
begin
 Result := GetTextAtEx2(x, y, Tolerance, Chars, False, False, MinSpacing, MaxSpacing, TextColor, TextLength, Strict, Range);
end;

function IsTextAt(x, y: Integer; S: string; Tolerance, Chars, MinSpacing, MaxSpacing, TextColor: Integer): Boolean;
begin
 Result := (S = GetTextAtEx2(x, y, Tolerance, Chars, False, False, MinSpacing, MaxSpacing, TextColor, Length(S), True, tr_AllChars));
end;

 

NOTE: I added MinSpacing / MaxSpacing to both of em (GetTextAt / IsTextAt)

Link to comment
Share on other sites

The font smoothing was updated. My entire computer had font smoothing disabled the moment I ran the script (hard not to notice).

 

Perhaps Janilabo has some good idea's, he's the one who wrote GetTextAt. I don't remember a FindTextTPA and I can't find anything like it on the TPA wiki. Yes, we can create bitmaps from fonts (pretty obvious, a font is actually a collection of bitmaps in some way). I'm not entirely sure what you're trying to do though. Are you suggesting to locate the coordinate of the first letter and read it by trial and error (compare it to every character in the alfabet available)?

 

I'm not sure either. But I think fonts are collections of glyphs*, and idk how that works I forget. Janilabo's is good! I remember lols!

 

GetTextAt, uses X, Y position. For the X pos, to the end of the screen on the X-axis or width provided GetTextAt will try to get the text. Now does GetTextAt use the Y efficient enough? For the Y, I think you should do it like this. For the highest height of the bitmaps for the font put in to GetTextAT, use that as a variable. Lets say the highest height is 60.

 

Idk how GetTextAt works exactly. But I imagine that it just moves X over and searchs for the bitmap again. There is no changes in Y? So i think there should be. Because when I use GetTextAt, or EX or W/E I want it to do a BOX. Not just at that particular Y value. What if the text is one pixel higher?

 

Scenario: All the text you are trying to get is at Y: 300. But you search at 299. So nothing shows up. BUT if you said like: from 300-400. BOOM box, and we get the text magically somehow...

 

Something like that...

 

tldr;

 

Bring in xs, ys, xe, ye for the searching!!! Or just for the Y axis

Link to comment
Share on other sites

I'm not sure either. But I think fonts are collections of glyphs*, and idk how that works I forget. Janilabo's is good! I remember lols!

 

GetTextAt, uses X, Y position. For the X pos, to the end of the screen on the X-axis or width provided GetTextAt will try to get the text. Now does GetTextAt use the Y efficient enough? For the Y, I think you should do it like this. For the highest height of the bitmaps for the font put in to GetTextAT, use that as a variable. Lets say the highest height is 60.

 

Idk how GetTextAt works exactly. But I imagine that it just moves X over and searchs for the bitmap again. There is no changes in Y? So i think there should be. Because when I use GetTextAt, or EX or W/E I want it to do a BOX. Not just at that particular Y value. What if the text is one pixel higher?

 

Scenario: All the text you are trying to get is at Y: 300. But you search at 299. So nothing shows up. BUT if you said like: from 300-400. BOOM box, and we get the text magically somehow...

 

Something like that...

 

tldr;

 

Bring in xs, ys, xe, ye for the searching!!! Or just for the Y axis

Mate, the function you are thinking/dreaming about would be GetTextIn.. :P GetTextAt[Ex] means getting the text from exact coordinate.. And yes, GetTextAt uses extra X in it, but that's for dealing with the problem of current OCR's width problems, which is limited to RuneScape bounds (I think). Freddy will change that in the future with new OCR (the current OCR is still the same old from ancient SCAR versions, IIRC)

 

I'll see what I can come up with GetTextIn.. But I think it is a function that should be built-in to SCAR instead (future OCR), because it really requires as fast speed as possible.

Link to comment
Share on other sites

Mate, the function you are thinking/dreaming about would be GetTextIn.. :P GetTextAt[Ex] means getting the text from exact coordinate.. And yes, GetTextAt uses extra X in it, but that's for dealing with the problem of current OCR's width problems, which is limited to RuneScape bounds (I think). Freddy will change that in the future with new OCR (the current OCR is still the same old from ancient SCAR versions, IIRC)

 

I'll see what I can come up with GetTextIn.. But I think it is a function that should be built-in to SCAR instead (future OCR), because it really requires as fast speed as possible.

 

Yeah! I think GetTextIn might solve problems that people have with GetTextAt(ex)! Thanks for creating these Janilabo!

Link to comment
Share on other sites

Yeah! I think GetTextIn might solve problems that people have with GetTextAt(ex)! Thanks for creating these Janilabo!
Hey mate,

 

I have been thinking about ways to build the function.. But it's not the easiest thing to create, AT ALL... :S

 

This is what I have came up with so far (uses currently SCAR's bugged GetTextAtEx to keep at least somekind of a speed with it):

 

function GetText(XS, YS, XE, YE: Integer; var x, y: Integer; Tolerance, Chars, MinSpacing, MaxSpacing, TextColor, TextLength: Integer; Strict: Boolean; Range: Byte): string;
var
 a: TBox;
 h, i: Integer;
 p: TPointArray;
 b: TSCARBitmap;
 c: TSCARClient;
 o: TPoint;
 t: string;
begin
 if ((XS > XE) or (YS > YE) or (TextColor < 0) or (TextColor > 16777215)) then // To make sure coordinates are somewhat correct and also, the text color is valid. -1 color (all colors) doesn't work with this.. It would make this function very slow, but also hard to develop...
   Exit;
 if FindColorTolEx(p, TextColor, XS, YS, XE, YE, Tolerance) then // If any points matched with TextColor + Tolerance from XS, YS, XE, YE, then we CONTINUE...
 begin            
   if ((XS <> 0) or (YS <> 0)) then
     o := Point((0 - XS), (0 - YS)); // We create an offset point, if XS or YS <> 0.
   a := TPABounds(p); // Area where the points were found..
   if ((a.X1 - 10) > XS) then
     XS := (a.X1 - 10); // We do this just to gain some speed for searching/matching process.
   if ((a.Y1 - 10) > YS) then
     YS := (a.Y1 - 10); // We do this just to gain some speed for searching/matching process.
   b := TSCARBitmap.Create('');
   try
     b.SetSize(((XE + o.X) + 1), ((YE + o.Y) + 1)); // Creating the bitmap for area to look for text. Background of the bitmap is black, matched points will be clWhite.
     h := High(p);
     for i := 0 to h do // We set all the matched points clWhite, that were found using TextColor + Tolerance. 
       b.Pixels[(p[i].X + o.X), (p[i].Y + o.Y)] := clWhite; 
     c := SetClient(TSCARBitmapClient.Create(b)); // We create a bitmap client for SCAR to look the text from..
     try
       for x := XS to XE do
       begin                  
         for y := YS to YE do
         begin
           t := GetTextAtEx((x + o.X), (y + o.Y), Tolerance, Chars, False, False, MinSpacing, MaxSpacing, clWhite, TextLength, Strict, Range);
           if not StartsWith(' ', t) then // We make sure the text found at current position does NOT start with empty space.
             if (Length(Replace(t, ' ', '')) > (TextLength div 2)) then // To check that at least 50% of the matched text characters ARE NOT empty spaces.
               Result := t; // Result was found. 
           if (Result <> '') then
             Break; // Breaking out when the text has been found.
         end;
         if (Result <> '') then
           Break; // Breaking out when the text has been found.
       end;       
       if (Result = '') then
       begin
         x := -1;
         y := -1;
       end;    
     finally
       SetClient(c).Free; // To free the bitmap client
     end; 
     SetLength(p, 0); // Setting the p to 0, just so any memory wont leak.     
   finally          
     b.Free; // Freeing the area bitmap 
   end;     
 end;
end; 

var
 x, y, SWFont: Integer;
 s: string;  

begin
 ClearDebug;
 GetClient.Activate;
 SWFont := LoadChars2(FontsPath + 'SWFont\'); 
 s := GetText(0, 21, 500, 561, x, y, 0, SWFont, 0, 0, 16253176, 10, True, tr_AllChars); 
 WriteLn('s: ' + s + ' [' + IntToStr(x) + ', ' + IntToStr(y) + ']');
 FreeChars2(SWFont);
end.

 

Have fun with it guys! But do note that, it is not perfect at all... But at least it's a start, I guess.

We can always improve it. ;)

Edited by Janilabo
Link to comment
Share on other sites

Hey mate,

 

I have been thinking about ways to build the function.. But it's not the easiest thing to create, AT ALL... :S

 

This is what I have came up with so far (uses currently SCAR's bugged GetTextAtEx to keep at least somekind of a speed with it):

 

function GetText(XS, YS, XE, YE: Integer; var x, y: Integer; Tolerance, Chars, MinSpacing, MaxSpacing, TextColor, TextLength: Integer; Strict: Boolean; Range: Byte): string;
var
 a: TBox;
 h, i: Integer;
 p: TPointArray;
 b: TSCARBitmap;
 c: TSCARClient;
 o: TPoint;
 t: string;
begin
 if ((XS > XE) or (YS > YE) or (TextColor < 0) or (TextColor > 16777215)) then // To make sure coordinates are somewhat correct and also, the text color is valid. -1 color (all colors) doesn't work with this.. It would make this function very slow, but also hard to develop...
   Exit;
 if FindColorTolEx(p, TextColor, XS, YS, XE, YE, Tolerance) then // If any points matched with TextColor + Tolerance from XS, YS, XE, YE, then we CONTINUE...
 begin            
   if ((XS <> 0) or (YS <> 0)) then
     o := Point((0 - XS), (0 - YS)); // We create an offset point, if XS or YS <> 0.
   a := TPABounds(p); // Area where the points were found..
   if ((a.X1 - 10) > XS) then
     XS := (a.X1 - 10); // We do this just to gain some speed for searching/matching process.
   if ((a.Y1 - 10) > YS) then
     YS := (a.Y1 - 10); // We do this just to gain some speed for searching/matching process.
   b := TSCARBitmap.Create('');
   try
     b.SetSize(((XE + o.X) + 1), ((YE + o.Y) + 1)); // Creating the bitmap for area to look for text. Background of the bitmap is black, matched points will be clWhite.
     h := High(p);
     for i := 0 to h do // We set all the matched points clWhite, that were found using TextColor + Tolerance. 
       b.Pixels[(p[i].X + o.X), (p[i].Y + o.Y)] := clWhite; 
     c := SetClient(TSCARBitmapClient.Create(b)); // We create a bitmap client for SCAR to look the text from..
     try
       for x := XS to XE do
       begin                  
         for y := YS to YE do
         begin
           t := GetTextAtEx((x + o.X), (y + o.Y), Tolerance, Chars, False, False, MinSpacing, MaxSpacing, clWhite, TextLength, Strict, Range);
           if not StartsWith(' ', t) then // We make sure the text found at current position does NOT start with empty space.
             if (Length(Replace(t, ' ', '')) > (TextLength div 2)) then // To check that at least 50% of the matched text characters ARE NOT empty spaces.
               Result := t; // Result was found. 
           if (Result <> '') then
             Break; // Breaking out when the text has been found.
         end;
         if (Result <> '') then
           Break; // Breaking out when the text has been found.
       end;       
       if (Result = '') then
       begin
         x := -1;
         y := -1;
       end;    
     finally
       SetClient(c).Free; // To free the bitmap client
     end; 
     SetLength(p, 0); // Setting the p to 0, just so any memory wont leak.     
   finally          
     b.Free; // Freeing the area bitmap 
   end;     
 end;
end; 

var
 x, y, SWFont: Integer;
 s: string;  

begin
 ClearDebug;
 GetClient.Activate;
 SWFont := LoadChars2(FontsPath + 'SWFont\'); 
 s := GetText(0, 21, 500, 561, x, y, 0, SWFont, 0, 0, 16253176, 10, True, tr_AllChars); 
 WriteLn('s: ' + s + ' [' + IntToStr(x) + ', ' + IntToStr(y) + ']');
 FreeChars2(SWFont);
end.

 

Have fun with it guys! But do note that, it is not perfect at all... But at least it's a start, I guess.

We can always improve it. ;)

 

Wow nice!!! You did a great job, lots of code written!

 

I think I want to make some new bitmap functions, and etc for games. I'm tired of writing if FindBitmap lines. I need to learn how OSI's wait function works. Can some one explain that to me again. In the function that it is waiting on, does it wait until it returns true? I don't understand exactly...

Link to comment
Share on other sites

I need to learn how OSI's wait function works. Can some one explain that to me again. In the function that it is waiting on, does it wait until it returns true? I don't understand exactly...
Are you talking about WaitFunction?

 

It's actually pretty straight forward once you get your head wrapped around it:

 

[sCAR]function WaitFunc(Func: function: Boolean; DesiredResult: Boolean; MinWait, MaxWait, MinTotalWait, MaxTotalWait: LongInt): Boolean;[/sCAR]

You pass in a function that takes no arguments and returns a Boolean result. You tell it what you are result waiting for (True or False) and every so often it will run the function, check the result, and if it matches yippee we are done! It will continue to do this periodically until the total time is reached, in which case it returns failure.

 

MinWait and MaxWait are used to generate a randomized WaitTime of how often to execute the function and check it's result. If you don't want randomization make MinWait and MaxWait the same.

 

Similar idea for MinTotalWait and MaxTotalWait are used to generate a random TotalWait (total time before giving up returning failure).

 

Think of it something like this:

repeat
 if Func() = DesiredResult then
   Success!
 otherwise
   Wait RandomRange(MinWait, MaxWait)
until elapsed time = RandomRange(MinTotalWait, MaxTotalWait)

 

So...WaitFunc(@LoginScreen, True, 25, 50, 5000, 6000) would execute the function LoginScreen() every 25..50 milliseconds. This will continue until LoginScreen() returns our desired result of True or 5000..6000 milliseconds have elapsed.

 

Edit: WaitFuncEx allows you to call a function that takes parameters, but afaik it does not work.

Edited by Bixby Sayz
Link to comment
Share on other sites


Many thanks. I appreciate this!
next https://lawsocietytribunal.ca/licensee/caitlin-eloise-gossage/?referer=https://uscasinoguides.com/
his explanation sneak a peek at this web-site
check over here https://busho-tai.jp/schedule/event_detail.php?eventname=New%20ab%20Description&url=https://uscasinoguides.com/
his response https://maps.google.cl/url?sa=t&source=web&rct=j&url=https://uscasinoguides.com/
you could look here https://www.thetriumphforum.com/proxy.php?link=https://uscasinoguides.com/
you can look here https://galant37.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
visit this site right here https://zaox.ru:443/redirect?url=https://uscasinoguides.com/
Link to comment
Share on other sites

Гидроизоляция это ключевой элемент в строительстве, обеспечивающий охрану объектов от воздействия влаги и воды. В зависимости от условий эксплуатации и материала конструкции, выбирается определенный тип гидроизоляции. Рассмотрим основные разновидности и их применения.

1. Рулонные материалы

Рулонные гидроизоляционные материалы используются для защиты кровель и фундаментов. Они бывают на основе битума и полимеров.
- Битумные рулоны известны благодаря своей доступности и безопасности. Используются на плоских крышах и в основании зданий.
- Полимерные рулоны имеют более высокую прочность и долговечность, подходят для трудных климатических условий.

2. Жидкая гидроизоляция

Водянистые гидроизоляторы используются для создания бесшовного покрытия. Они посещают на основе:
- Полимеров легко наносятся и образуют прочную мембрану.
- Цемента совершенно то что надо для ванной и кухни, владеют превосходными гидрофобными свойствами.

3. Проникающая гидроизоляция

Этот тип проникает в структуру бетона и наполняет микротрещины, обеспечивая надежную охрану. Применяется в большей степени для фундаментов и подвалов. Проникающая гидроизоляция отлично совладевает с постоянным воздействием воды.

4. Мембранная гидроизоляция

Мембранные системы часто употребляются для крыши и подземных конструкций. Такой метод обеспечивает надежную защиту от осадков и грунтовых вод.
- ЭПДМ и ТПО мембраны имеют высокую устойчивость к ультрафиолету и механическим повреждениям https://gidroizolyaciya-dlya-vsekh.ru

5. Гидрофобные добавки

Гидрофобные добавки в бетон или раствор помогают предупредить проникновение влаги. Они идеально то что надо для создания водонепроницаемых конструкций, таких как бассейны и резервуары.

Выбор типа гидроизоляции

При выборе гидроизоляции важно учесть:
- Правила использования влажность, температура, возможные нагрузки.
- Материалы конструкции для каждого типа материала существует меня называют Господом лучший вариант гидроизоляции.
- Бюджет некие методы более затратные, но дают обеспечение огромную долговечность.

В заключение, выбор гидроизоляции зависит от множества факторов. Правильное решение поможет продлить срок службы строительных объектов и избежать суровых проблем с влажностью.
Link to comment
Share on other sites

You expressed that terrifically.
advice https://velik.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
look at this website how you can help
you can find out more http://zolotoi-mebelshchik.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
more about the author recommended site
helpful site https://www.biounion.de/firmeneintrag-loeschen?nid=1&element=https://uscasinoguides.com/
try these out https://www.autokiste.de/kontakt/mailforms/leserbrief.htm?headline=Hyundai%20Kona:%20Erste%20Details,%20erste%20Bilder&id=12192&url=https://uscasinoguides.com/
you can check here use this link
Link to comment
Share on other sites

Гидроизоляция это ключевой элемент в строительстве, обеспечивающий защиту объектов от воздействия влаги и воды. В зависимости от условий эксплуатации и материала конструкции, выбирается определенный тип гидроизоляции. Рассмотрим главные разновидности и их применения.

1. Рулонные материалы

Рулонные водоизоляционные материалы используются для защиты кровель и фундаментов. Они посещают на основе битума и полимеров.
- Битумные рулоны популярны благодаря своей доступности и безопасности. Используются на плоских крышах и в основании зданий.
- Полимерные рулоны имеют более высокую прочность и долговечность, то что надо для сложных климатических условий.

2. Жидкая гидроизоляция

Жидкие гидроизоляторы применяются для творения бесшовного покрытия. Они посещают на основе:
- Полимеров с легкостью наносятся и образуют прочную мембрану.
- Цемента идеально подходят для ванной и кухни, обладают превосходными гидрофобными свойствами.

3. Проникающая гидроизоляция

Этот тип проникает в структуру бетона и наполняет микротрещины, обеспечивая надежную защиту. Применяется предпочтительно для фундаментов и подвалов. Проникающая гидроизоляция эффективно совладевает с неизменным воздействием влаги.

4. Мембранная гидроизоляция

Мембранные системы часто употребляются для крыши и подземных конструкций. Такой метод обеспечивает надежную защиту от осадков и грунтовых вод.
- ЭПДМ и ТПО мембраны имеют высокую устойчивость к солнечному излучению и механическим повреждениям https://gidroizolyaciya-dlya-vsekh.ru

5. Гидрофобные добавки

Гидрофобные добавки в бетон или раствор помогают предупредить проникновение воды. Они образцово подходят для творения водонепроницаемых конструкций, таких как бассейны и резервуары.

Выбор типа гидроизоляции

При выборе гидроизоляции главно учитывать:
- Правила использования влажность, температура, вероятные нагрузки.
- Материалы конструкции для каждого типа материала существует свой лучший вариант гидроизоляции.
- Бюджет некоторые способы более затратные, но обеспечивают огромную долговечность.

В заключение, выбор гидроизоляции зависит от множества причин. Правильное решение поможет продлить срок эксплуатации строительных объектов и избежать суровых проблем с влажностью.
Link to comment
Share on other sites

You reported this terrifically!
navigate here redirected here
click this link https://white-sign.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
top article https://therapy.school/bitrix/redirect.php?goto=https://uscasinoguides.com/
site here https://eshop.logictim.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
take a look at the site here https://avangard-eco.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
you could try here https://sibhunter22.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
check linked here
Link to comment
Share on other sites


Cheers. Awesome information.
browse around here http://enotmebel.uz/bitrix/rk.php?goto=https://uscasinoguides.com/
here are the findings https://osheerus.ru/bitrix/rk.php?goto=https://uscasinoguides.com/
learn more http://medical-dictionary.tfd.com/_/cite.aspx?url=https%3A%2F%2Fuscasinoguides.com%2F&word=Dip%20Pract%20Derm&sources=hcMed
you could try these out https://mineralx.ru/bitrix/redirect.php?goto=https://uscasinoguides.com/
what is it worth https://zgpc.ru:443/bitrix/redirect.php?goto=https://uscasinoguides.com/
view publisher site https://altaysnab.ru:443/bitrix/redirect.php?goto=https://uscasinoguides.com/
here https://lepnina.top/bitrix/rk.php?goto=https://uscasinoguides.com/
Link to comment
Share on other sites

Он-лайн казино в Беларуси стали модным способом развлечений для большинства людей. Беря во внимание развитие технологий и доступность прибегают к помощи, азартные игры в сети привлекают все большее количество игроков. В этой статье мы рассмотрим характерные черты онлайн казино в Беларуси, их регулирование и перспективы развития этого сегмента.

Законодательство и Регулирование

В 2021 году Беларусь приняла ряд конфигураций в законодательство, касающиеся он-лайн-игр. Теперь онлайн казино подлежат лицензированию, что позволяет государству держать под контролем их деятельность и оберегать интересы игроков. Лицензии выдают специальные органы, обеспечивая прозрачность и безопасность игр.

Игроки могут рассчитывать на защиту своих прав и легитимное регулирование азартных игр. Поэтому, выбор лицензированных онлайн казино становится более безопасным для юзеров.

Популярность Онлайн Казино

С увеличением энтузиазма к он-лайн азартным играм в Беларуси, многие известные международные операторы начали делать отличное предложение свои услуги. Игроки могут наслаждаться разнообразием игр, включая слоты, покер, рулетку и блэкджек. Огромное количество платформ делают отличное предложение интересные акции, призы и программы лояльности для вербования пользователей.

Платежные Методы

Онлайн казино в Беларуси предлагают различные способы пополнения счета и вывода средств. Знаменитыми методами являются банковские карты, электронные кошельки и криптовалюты. Удобство и скорость транзакций существенно упрощают игровой процесс и увеличивают уровень удовлетворенности игроков.

Безопасность и Ответственная Забава

С развитием онлайн казино возрастает и необходимость в обеспечении безопасности данных игроков. Лицензированные платформы используют современные технологии шифрования для защиты личной инфы и валютных средств пользователей.

Не считая а всё потому великое внимание уделяется принципам ответственной забавы. Операторы предлагают приборы, которые подсобляют игрокам держать под контролем свое время и бюджет на азартные игры, снижая опасности зависимости.

Перспективы Развития

Будущее сделать ставку фрибет смотрится многообещающе. С ростом популярности азартных игр в социальных сетях и мобильных приложениях, ожидается, что количество пользователей будет только увеличиваться. Развитие технологий, таких как виртуальная и дополненная действительность, может изменить сферу онлайн-гейминга, предоставляя игрокам новые форматы веселий.

Заключение

Он-лайн казино в Беларуси совмещают в себе способности современных технологий и требования законодательства. Сохранение управления и контроля со стороны государства содействует развитию неопасной и ответственной игорной среды. При этом игрокам главно внимательно выбирать лицензионные платформы, что позволит им наслаждаться играми на деньги в комфортной и неопасной обстановке.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.




×
  • Create New...