Failsafes!
The A - Z Manual
Here I will teach you some of the most jealously guarded secrets of how you can make those color scripts run for a very, very long time. How can you look perfectly human, how you avoid getting lost and finally, how if all fails you still manage to get up.
The first thing to know about failsafes is that 3 is the magical number. No less, no real need for more. But let's not start from here.
When running a script, you want it to waste as little time as possible, to think as fast, if not faster than a human would. How do you achieve this?
Let's look at this example of browsing a bank:
[ Bank 1 ]
We are aiming to take out the bronze axe.
If we search with color, we might end up on the surrounding bronze items.
If we search with a DTM Mask, we might end up on the mithril axe.
Bitmaps often break, so they are not a great choice either.
If we search for a DTM with a center point of the bronze color, we might not add enough tolerance and it will break soon enough.
So how can you be absolutely sure?
Also, a human does not go hovering over similar items, he goes straight to what he wants, so how do we do that?
My suggestion? A DTM Mask AND color.
It's incredibly easy to make a DTM mask, you just make 5 or 6 points, all from the outline, the same way you'd do a normal DTM, except you don't use a middle point.
SCAR Code:
type
TItem = Record
Name: string;
UpText: string;
DTM: integer;
Color: integer;
Tol: integer;
LastSpot: integer;
end;
Also, there is little point in searching the WHOLE MainScreen, the smaller the area you search, the faster and less likely of mistakes.
[ Bank 2 ]
No point in searching outside that area, as the rest does not interest you.
* Constants for these are now in SRL; MBX1, MBY1, MBX2, MBY2 *
So first, we do a simple color check.
SCAR Code:
program New;
begin
var
TPA: TPointArray;
ATPA: T2DPointArray;
i, x, y: integer;
begin
if FindColorsTolerance(TPA, Item.Color, MBX1, MBY1, MBX2, MBY2, Item.tol) then
begin
//now we break it up to bank spots
ATPA := TPAToATPAEx(TPA, 40, 40); //assuming each bank spot is 40*40
//now that we have the TPA broken up into an ATPA we can start looking for the dtm.
for i:=0 to High(ATPA) do
begin
MiddleTPAEx(ATPA[i], x, y);
if FindDTM(Item.DTM, x, y, x-30, y-30, x+30,y+30) then
begin
//we have found the color and the DTM
//therefore we are pretty damn sure it is the right thing
//so now, we move the mouse and do the last check
MMouse(x, y, 5, 5);
if WaitUpText('ze axe', 300) then
writeln('yay, we got it!');
end;
end;
end.
It's good to be sure we find it so accurately, right? No messing around, the mouse going all over the place to find the right thing. Notice how it used 3 checks? Color + DTM + UpText.
Could we improve this? Definitely. Maybe make it remember in which bank spot your item is, and next time it checks that spot first? I'll let you figure out on your own how to do that
Now, onto a different part of failsafes!
What is the magical number again? 3
We are chopping a tree... the one to the bottom right of our player
[ Tree 1 ]
How do I know I am chopping thing tree, and how do I know when it's gone?
- Inv Count
- Color Check
- UpText
1: Inv Count
SCAR Code:
var
CurrentCount, NextCount: integer;
begin
CurrentCount := InvCount;
NextCount := CurrentCount + 1;
if not WaitInvCount(NextCount, 15000) then
begin
//we haven't cut a log in 15 secs, therefore we are not cutting
end;
end.
2: Color Check
SCAR Code:
const
TreeColor = 123123123;
function MouseAtTree: boolean;
begin
Result := false;
// mouse is hovering over the tree
GetMousePos(x, y);
if SimilarColors(GetColor(x, y), TreeColor, 10) then
begin
Result := true;
exit;
end;
//if we are here, then the colors didn't match
//Perhaps one of the surrounding pixels will match
if FindColorTolerance(x, y, TreeColor, x-5, y-5, x+5, y+5, 10) then
begin
Result := true;
MMouse(x, y, 0, 0);
//we move the mouse to the exact point, to avoid future trouble
exit;
end;
//...
end;
3. UpText
SCAR Code:
Result := IsUpText('hop');
Individually these checks are ok, but if all put into one... they work miracles.
SCAR Code:
Function WaitUntilCut(which: TTree; x, y:integer): boolean;
var
Color, Time, x2, y2, Counts, NextCount: integer;
begin
wait(random(500));
RMDebug('WaitUntilCut');
Result := true;
GetMousePos(x,y);
Color := GetColor(x, y);
Time := GetSystemTime + (5+Random(3))*1000;
NextCount := InvCount + 1;
repeat
if GetSystemTime > Time then
begin
Time := GetSystemTime + (5+Random(3))*1000;
GetMousePos(x2, y2);
//x, y is the place where we found the color
// (done later in loop)
if Distance(x, y, x2, y2) > 10 then
MMouse(x, y, 3, 3);
//if the distance between our mouse and the color is too big,
//we bring the mouse closer to be sure we are able to get the UpText
if not WaitUpTextMulti(Which.UpText, 500) then
begin
RMDebug('WaitUntilCut - No Text');
break;
end;
end;
wait(250);
if not SimilarColors(GetColor(x, y), Color, 10) then
//if the color is not at the exact place, we search around it
if not FindColorTolerance(x, y, Color, x - 5, y - 5, x + 5, y + 5, 10) then
begin
//if it is not around it, then likely the tree is gone
RMDebug('WaitUntilCut - no color');
break;
end;
if not WaitInvCount(NextCount, 250) then
begin
//if we don't get a log then we increment "Counts"
Inc(Counts);
if Counts > (Players[CurrentPlayer].Integers[2] / 500) then
begin
//if the number of Counts*WaitTime(250) is more than the script user
//set as maximum wait time then
//we assume we are not cutting the tree
RMDebug('WaitUntilCut - NoInvCount');
break;
end;
end else begin
//if we do get a log then we prepare it for the next log
NextCount := InvCount + 1 ;
Counts := 0;
end;
until(InvFull)
end;
And so, once again, you have 3 checks to be sure you are doing the right thing.
Why? Very simple, because none of them is perfect.
- InvCount - you might just be a slow chopper
- Color - the tree might be gone, but the grass color is similar
- UpText - the text might be there, but you might be checking the wrong tree
And so, each failsafe complements each other.
Another Important thing on failsafes: You don't want to be stuck in a loop.
Once again, there are 3 things you definitely want to check for.
- Am I logged In?
- Am I in a Random?
- Have i been here for the past hour? ... or ...
- Have i tried to do this a million times?
SCAR Code:
Function AreWeGood: boolean;
var
Timer, Counts: Integer;
begin
Result := False;
Timer := GetSystemTime + 25000;
while BankScreen do
begin
if not LoggedIn then exit;
if FindNormalRandoms then exit;
Inc(Count);
if Count > 5 then exit; //we've tried 5 times and still failed.
//Something's just not working
if Timer >= GetSystemTime then exit; //we've been here too long
//...
end;
Result := True;
end;
Finally, walking. Walking is what usually needs the most failsafes, especially for long walks.
Once again, what do we go for? 3 failsafes. But here it's a bit different.
For example, you're not going to make 3 DDTMs as a failsafe, no. Here you should use 3 different techniques.
Here is a list of a few:
- DDTMs
- RadialWalking
- AngleWalking
A DDTM is a Dynamic DTM, for those who don't know. You'd use this over a normal DTM because you can change it during runtime, meaning that you can for example change the color of your points with your autocolor functions.
[Draynor 1]
Let's have a look here. We want to Fish some anchovies. How are we going to get to that fishing spot?
- We Try to walk to the symbol
- We Try to walk to the water
- We Try to walk in the tree's direction (light green color)
- And Finally - because this is a very short walk, we can use MouseAngle
Again, we found 3 good refference points, and because it is a very short distance we could risk using a coords clikc with some randomness.
SCAR Code:
If not FindSymbol('fish', ...) then
if not WaterWalk( ...) then
if not RadialWalk( TreeColor, ...) then
MouseAngle((MMCX - 7), (MMCY + 7), 3, 3);
[ Edgy 1 ]
Another Important thing is to constantly know where we are.
[
Explanation of changing fishing spots etc
]
[ AK 1 ]
[
Few ways of checking where we are
]
to be finished another time...
~RM