PDA

View Full Version : How to select the smallest first.



KilKof
04-29-2017, 04:20 PM
Hello. Im trying to make a script to attack Kraken.
There are 4 small whirlpool which has to be attacked first.
Then there is one big in the middle. Looks like this:
28103

What i want to do is to make it click the smaller ones first, then the big one.
Here is what i managed to come up with.

procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
color_White : TColEx;
foundPnt : TPoint;

begin
color_White.create(15131068, 11, 0.03, 1.21);
if color_White.findIn(AREA_MS, foundPnt) then
begin
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
HumanMMouse(FoundPnt, 0, 0);
fastclick(mouse_left);
wait(4000);
end;
end;

What it does is, attack the first 2 small whirlpools at the top, but after those 2 it will click on the big one.

Hope somebody can help, thx :)

Borland
04-29-2017, 05:14 PM
You're sorting the ATPA by smallest which is what you're after but you don't actually do anything with that. You're moving the mouse using foundPnt which was assigned via the findIn function. You'll want to assign foundPnt using the newly re-arranged ATPA, the first element in the array (ATPA) will be the smallest found circle. So something like

SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
HumanMMouse(FoundPnt, 0, 0);


That all said, you should switch up your approach. Right now you're waiting an arbitrary 4 seconds after attacking. Instead, find the ATPA like you are, then you should filter out the larger middle whirlpool by looking at the size of each TPA in the ATPA and removing the largest. Now you have only the smaller whirlpools, loop through the ATPA and attack each one, after attacking wait for an exp drop so that the script will attack the next one right away. If you're using range to attack the smaller whirlpools, then you should wait for either an exp drop OR a blue hit split near the whirlpool location.

Remember, gold farm scripts are generally among the riskiest when it comes to bans so its worthwhile doing these extra bits to make it more human.

KilKof
04-30-2017, 02:04 PM
Thanks! I have changed the procedure a bit, but it will still click on the biggest whirlpool first, idk why :(. Im using range btw and i made the 4sec wait so it attacks the next one after the tenticle is out of whirlpool, 4 sec seems about it.


procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
foundPnt: TPoint;
begin
if FindColorsSpiralTolerance(265,181, TPA, 15460308, 1, 1, 518, 338, 30) then
begin
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
HumanMMouse(FoundPnt, 0, 0);
if waitUptext('Whirlpool', 250) then
fastclick(mouse_left);
wait(4000);
end;
end;

jstemper
04-30-2017, 02:19 PM
Thanks! I'm attacking them with range and i have to just attack every small whirlpool (dont have to kill them), before attacking the big one. I've tried chaning something in the procedure but now ill get "Access violation" error. Im using aerolib inculde btw.

procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
foundPnt : TPoint;
x, y: Integer
begin
if FindColorSpiralTolerance(x,y, 13617560, 1, 1, 518, 338, 30) then
begin
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
HumanMMouse(FoundPnt, 0, 0);
if waitUptext('Whirlpool', 250) then
fastclick(mouse_left);
wait(4000);
end;
end;

You're getting an access violation because ATPA[0] doesn't exist. TPA has a length of 0, then you floodfill it so ATPA has a length of 0. No points are ever being stored in your TPA var.

You need to use one of the FindColorsTolerance or FindColorsSpiralTolerance functions that stores the found points in a TPointArray

ex.
function FindColorsTolerance(var pts: TPointArray; col, x1, y1, x2, y2, tol: Integer): Boolean;

http://docs.villavu.com/simba/scriptref/color.html#findcolorstolerance

KilKof
04-30-2017, 02:33 PM
Yeah, i've done that and i edited my post :D. I've changed to FindColorsSpiralTolerance, but it will press on the big one first.


FindColorsSpiralTolerance(265,181, TPA, 15460308, 1, 1, 518, 338, 30)

Also tried the FindColorsTolerance and picking new colors of whirpool, but it will still press first on the biggest.

How it looks now:


procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
foundPnt: TPoint;
begin
if FindColorsTolerance(TPA, 15526093, 1, 1, 518, 338, 30) then
begin
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
HumanMMouse(FoundPnt, 0, 0);
if waitUptext('Whirlpool', 250) then
fastclick(mouse_left);
wait(4000);
end;
end;

EDIT: The tolerance was way too high, i changed it to lower and it seems to work just fine, thanks!

jstemper
04-30-2017, 02:44 PM
Yeah, i've done that and i edited my post :D. I've changed to FindColorsSpiralTolerance, but it will press on the big one first.


FindColorsSpiralTolerance(265,181, TPA, 15460308, 1, 1, 518, 338, 30)

Debug the ATPA

debugATPA(ATPA, '');

I don't think each TPA is filling out to the size you think it is. You may want to look into using CTS 2 settings for FindColorsSpiralTolerance

KilKof
04-30-2017, 03:23 PM
I've changed it abit and it works better now, but sometimes it still clicks the big one, but then moves to the small one, not a big problem i guess. Also when the Kraken spawned and there were no more whirlpools it kept searching and then crashed, giving me this error:

Error: Access violation at line 123
Execution failed.
The following bitmaps were not freed: [0, 1]

I guess i just need to make function to let the script know when the kraken is spawned and stop looking for whirlpools.

Here is what i managed to make now:


procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
foundPnt: TPoint;
CTS: integer;
begin
CTS := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
setcolorspeed2modifiers(0.28, 1.43);
FindColorsSpiralTolerance(272, 191, TPA, 10791822, 1, 1, 518, 338, 15);
ColorToleranceSpeed(CTS);
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
begin
HumanMMouse(FoundPnt, 0, 0);
if waitUptext('Whirlpool', 250) then
begin
fastclick(mouse_left);
wait(4000);
end;
end;
end;

jstemper
04-30-2017, 05:09 PM
I've changed it abit and it works better now, but sometimes it still clicks the big one, but then moves to the small one, not a big problem i guess. Also when the Kraken spawned and there were no more whirlpools it kept searching and then crashed, giving me this error:

Error: Access violation at line 123
Execution failed.
The following bitmaps were not freed: [0, 1]

I guess i just need to make function to let the script know when the kraken is spawned and stop looking for whirlpools.

Here is what i managed to make now:


procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
foundPnt: TPoint;
CTS: integer;
begin
CTS := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
setcolorspeed2modifiers(0.28, 1.43);
FindColorsSpiralTolerance(272, 191, TPA, 10791822, 1, 1, 518, 338, 15);
ColorToleranceSpeed(CTS);
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
begin
HumanMMouse(FoundPnt, 0, 0);
if waitUptext('Whirlpool', 250) then
begin
fastclick(mouse_left);
wait(4000);
end;
end;
end;

To stop that error, check your ATPA and make sure its length is greater than 0

Borland
04-30-2017, 06:45 PM
Here is what i managed to make now:


procedure Attack();
var
TPA: TPointArray;
ATPA: T2DPointArray;
foundPnt: TPoint;
CTS: integer;
begin
CTS := GetColorToleranceSpeed;
ColorToleranceSpeed(2);
setcolorspeed2modifiers(0.28, 1.43);
FindColorsSpiralTolerance(272, 191, TPA, 10791822, 1, 1, 518, 338, 15);
ColorToleranceSpeed(CTS);
ATPA := FloodFillTPA(TPA);
SortATPASize(ATPA, false);
foundPnt := MiddleTPA(ATPA[0]);
begin
HumanMMouse(FoundPnt, 0, 0);
if waitUptext('Whirlpool', 250) then
begin
fastclick(mouse_left);
wait(4000);
end;
end;
end;

I know it's tempting, especially when you just want to do something quick, but don't try and put everything into one function/procedure. It feels like it's not worth the time because you just need something basic but you'll pour more time into it overall this way than if you take 10 mins to separate everything out.

Using the AeroLib functions were fine and didn't cause any of your problems. Those functions use findColorsTolerance as well, it's just in a neat wrapper that handles the CTS setting and resetting for you. Also gives a more object oriented feel when you can use TColEx, as using findColorsTolerance yourself with a bunch of meaningless numbers isn't any help a week from now when you look at the script again.

When you split everything out it allows you to try different aproaches a lot easier. Have a single function that just finds the whirlpools, now you can use this in other functions where you try and work out which pool is which.

I went ahead and done a few functions on how I'd go about finding the pools. I used your image as my 'game screen' so you'll need to open the image and target it. If you want to use any of them in-game then you'll need to first decide how you want your camera to be, then adjust the functions where needed as these are based on the view from your image.

Open the image in something that doesn't distort the real colors. Chrome or Paint work fine. Windows image preview doesn't.


program whirlpoolExtravaganza;
{$i AeroLib/AeroLib.Simba}

function getClientBox: TBox;
var
cW, cH: Integer;
begin
GetClientDimensions(cW, cH);
Result := ToBox(0,0,cW-1,cH-1);
end;

function findWhirlpools(Size: Integer = 5): T2DPointArray; //Optional size param, default is 5
var //we use this later but can be avoided
colWhirlpool: TColEx;
poolPoints: TPointArray;
begin
colWhirlpool.create(14143913,12,0.05,1.08);

colWhirlpool.findAllIn(getClientBox, poolPoints);
Result := ClusterTPA(poolPoints, Size);

debugATPA(Result, '');
end;

procedure debugPoolSizes;
var
allPools: T2DPointArray;
i: Integer;
begin
allPools := findWhirlpools;

for i := 0 to High(allPools) do
begin
accurateMMouse(MiddleTPA(allPools[i]),0,0);
Writeln(i,': ',Length(allPools[i])); //Will let us know how many points are in the TPA
Wait(1500);
end;
end;

function findSmallPools(Size: Integer = 700): T2DPointArray;
var
allPools, smallPools: T2DPointArray;
i: Integer;
begin
allPools := findWhirlpools;

if Length(allPools) < 1 then //We make sure our ATPA has results in it to avoid access violation
Exit;

for i := 0 to High(allPools) do
if Length(allPools[i]) < Size then //We're only saving the TPAs whose size is below Size param
smallPools := smallPools + allPools[i];

Result := smallPools;

debugATPA(Result, '');
end;

function findLargePool: TPointArray;
var
allPools: T2DPointArray;
begin
allPools := findWhirlpools(30); //We change the default Size param here
//due to the player being in the way in the screenie
//a better camera angle and height would avoid this need

if Length(allPools) < 1 then //We make sure our ATPA has results in it to avoid access violation
Exit;

SortATPASize(allPools, True);

Result := allPools[0]; //Largest TPA is now the first element, so [0]

debugTPA(Result, '');
end;

function findCornerPools: TPointArray;
var
allPools: T2DPointArray;
midPoints: TPointArray;
i: Integer;
begin
allPools := findWhirlpools;

if Length(allPools) < 1 then //We make sure our ATPA has results in it to avoid access violation
Exit;

for i := 0 to High(allPools) do
midPoints := midPoints + MiddleTPA(allPools[i]); //Get a single point for each TPA (Pool)

SetLength(Result, 4);

SortTPAByX(midPoints, True); //Arrange the points by their X positions such that
//points closer to the left are first
//so the first 2 elements will be the 2 small pools on the left

//We could just assign the first two values and the last 2 values
//as those are the small pools, but it'd be nice if we can order
//the pools in the order that you'll attack them as a human would
//In the pic it'd be: top left, bottom left, top right, bottom right.

//You'll need to mess with this function if the camera will be
//from what the pic is at.

case midPoints[0].Y < midPoints[1].Y of //this case statement will sort the left 2 pools so that the
True: //top left pool is first in our returned array
Begin
Result[0] := midPoints[0];
Result[1] := midPoints[1];
end;

False:
Begin
Result[1] := midPoints[0];
Result[0] := midPoints[1];
end;
end;

SortTPAByX(midPoints, False); //same again but we flipped true -> false so the right most
//pools are now first and second in the array

case midPoints[0].Y < midPoints[1].Y of
True:
Begin
Result[2] := midPoints[0];
Result[3] := midPoints[1];
end;

False:
Begin
Result[3] := midPoints[0];
Result[2] := midPoints[1];
end;
end;

debugTPA(Result, '');

for i := 0 to High(Result) do
begin
accurateMMouse(Result[i],0,0);
Wait(1000);
end;
end;


begin
InitAL;

//Try the following one at a time.

findWhirlpools;

//debugPoolSizes;

//findSmallPools;

//findLargePool;

//findCornerPools;

end.

KilKof
05-01-2017, 02:44 PM
Wow thank you! It works flawless :D The last thing i wanna do is make it eat and loot, only after the kraken is killed. It eats while attacking the kraken and after it drinks a potion, you have to press on the monster again to attack it (I've tried making it to attack kraken after drinking potion each time, but it missclicked sometimed and ended up not attacking at all, wasnt good idea i guess :D). I noticed that every kraken kill, you get this message: 28105 Is it possible to make it like, if this msg appears, then start "CheckPray" and "loot", if both done then start over again with disturbing the pools. I dont expect somebody to write everything for me, but every little example or explanation helps alot.

Easygold
10-22-2017, 04:00 PM
Yo, add me on skype or discord pls live:easygoldgroup or ThomasEGG#8197