I know this is an old thread, but I've been fiddling around with some of this as I was looking into ways on mousing a moving target, and this thread is very aptly relevant aha -
Anyways, I've modified the code to be a little more generic (the basic groundwork has been laid to find any object) through the use of records (as @fady mentioned), and turning the procedure into a function that returns a TPoint.
This is still largely a draft, but I just want to get out there what I've been working on.
Here's the test record I've been using:
Simba Code:
type
TFinderObj = record
ColorData: TColorData;
Size: integer;
OverText: TStringArray;
end;
For the actual findObj function I've laid out, it's main weakness is the fact that it does return the point that which is the middle of literally every match of the color, the TPA - without further filtering that may be useful on a per-use instance. I do have a 'Size' record variable that I thought could be used for this, but I'm still trying to figure out the best method. Not sure if I want to use toATPA or cluster on the TPA, and then sort the results from the player or something - or maybe just return the whole TPA array and loop through as is a pretty standard method, but that still seems unnecessary. Maybe just set x and y to the player coordinates for the SpiralTolerance call... ¯\_(?)_/¯
Anyways, here's what my findObj function looks like:
Simba Code:
function findObj(objData: TFinderObj; searchArea: TBox): TPoint;
var
ATPA: T2DPointArray;
TPA: TPointARray;
x, y: integer;
t: TTimeMarker;
p: TPoint;
begin
t.reset(); t.start();
repeat
if (t.getTime() > 2500) then
exit(Point(-1, -1));
findColorsSpiralTolerance(x, y, TPA, objData.ColorData.color, searchArea, objData.ColorData.tolerance, objData.ColorData.settings);
until length(TPA) >= 1;
if length(TPA) >= 1 then
p := middleTPA(TPA);
result := p;
end;
- this will be used in conjunction with a slightly modified iteration of Camel's modification on _humanWindMouse which now is a function that returns a boolean on whether or not it's reached it's destination:
Simba Code:
function mMoving(xs, ys, gravity, wind, minwait, maxwait, targetArea: Extended; objData: TFinderObj; searchArea: TBox): boolean;
var
veloX, veloY, windX, windY, veloMag, dist, randomDist, D: extended;
lastX, lastY, MSP, W, TDist: integer;
pointI: TPoint;
T: LongWord;
sqrt2, sqrt3, sqrt5, maxStep, rCnc: extended;
begin
MSP := mouseSpeed;
sqrt2:= sqrt(2);
sqrt3:= sqrt(3);
sqrt5:= sqrt(5);
pointI := findObj(objData, searchArea);
if PointI.X = -1 then
exit;
TDist := distance(round(xs), round(ys), pointI.x, pointI.y);
t := getSystemTime() + 10000;
repeat
if (getSystemTime() > t) then
break;
pointI := findObj(objData, searchArea);
if PointI.X = -1 then
exit;
dist:= hypot(xs - pointI.x, ys - pointI.y);
wind:= minE(wind, dist);
if (dist < 1) then
dist := 1;
D := (round((round(TDist)*0.3))/7);
if (D > 25) then
D := 25;
if (D < 5) then
D := 5;
rCnc := random(6);
if (rCnc = 1) then
D := randomRange(2,3);
if (D <= round(dist)) then
maxStep := D
else
maxStep := round(dist);
if dist >= targetArea then
begin
windX:= windX / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
windY:= windY / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
end else
begin
windX:= windX / sqrt2;
windY:= windY / sqrt2;
end;
veloX:= veloX + windX;
veloY:= veloY + windY;
veloX:= veloX + gravity * (PointI.x - xs) / dist;
veloY:= veloY + gravity * (PointI.y - ys) / dist;
if (hypot(veloX, veloY) > maxStep) then
begin
randomDist:= maxStep / 2.0 + random(round(maxStep) div 2);
veloMag:= sqrt(veloX * veloX + veloY * veloY);
veloX:= (veloX / veloMag) * randomDist;
veloY:= (veloY / veloMag) * randomDist;
end;
lastX:= round(xs);
lastY:= round(ys);
xs:= xs + veloX;
ys:= ys + veloY;
if (lastX <> round(xs)) or (lastY <> round(ys)) then
moveMouse(round(xs), round(ys));
W := (random((round(100/MSP)))*6);
if (W < 5) then
W := 5;
W := round(W*0.9);
wait(W);
until(hypot(xs - PointI.x, ys - PointI.y) < 3);
if (hypot(xs - PointI.x, ys - PointI.y) < 3) then
exit(true);
mouseSpeed := MSP;
end;
... which of course is used through a wrapper function which returns that result:
Simba Code:
function mMovingObject(objData: TFinderObj; searchArea: TBox; button: integer): boolean;
var
randSpeed: extended;
x, y, ms: integer;
begin
if (button = MOUSE_NONE) then
exit;
ms := mouseSpeed;
randSpeed := (random(mouseSpeed) / 2.0 + mouseSpeed) / 10.0;
getMousePos(x,y);
if mMoving(x, y, MOUSE_HUMAN, 5, 10.0/randSpeed, 15.0/randSpeed, 10.0*randSpeed, objData, searchArea) then
begin
fastClick(button);
exit(true);
end;
mouseSpeed := ms;
end;
And then when used all together to find, say, the Prifddinas bonfire (data pulled from my Bonfirer for ease), we get a use case that looks something like:
Simba Code:
var
bonfire: TFinderObj;
begin
setupSRL();
with bonfire do
begin
ColorData := [2712485, 3, [2, [0.06, 0.25]]];
Size := 20;
OverText := ['onfire', 'Bonf'];
end;
if (mMovingObject(bonfire, mainScreen.getBounds(), MOUSE_MOVE)) then
if (isMouseOverText(bonfire.OverText, 1000)) then
writeLn('We found the bonfire!');
end.
Of course, this is still a draft in trying to get it to work in as many situations as possible, and probably some adjustments could be made to on what makes these functions return true and stuff - but I think this is a good start!
Very cool stuff!
Also, if you want to stay up to date with or contribute to this development, feel free to visit the GitHub.