Creating and using a DDTM Anchor.
I promised you an explanation of my DDTM-method. Got some time today, so here it comes.
Using a DDTM as anchor in a script.
What can I use this for?
This method is ideal for scripts that focus around one spot, like my Masterfarmer Thiever of Happy Little Runescape.
What does it do?
Simply put: you gain full control over the position of your player as long as the DDTM is visible on the minimap.
How does it work?
You write code for a Dynamic DTM. This is nothing more than a predefined DTM with one or more variables build in.You will need provide the DTM with an argument and assemble the DDTM runtime, so while the script is running!
Detailed Explanation
Consider this picture. It is a blowup of the barndoor north of Draynor square. As you see it consists of 8 red pixels. This line of pixels is unique to the minimap. While there are more doors on the minimap visible, none are wider than 5 pixels.
This makes it ideal for a DDTM. For that i use a stoneold piece old code I wrote once, and since than always copied from one script to the other.
Simba Code:
Procedure AssembleDTM; //
var
DTMSubPoints: array[0..2] of TDTMPointDef;
DTMMainPoint: TDTMPointDef;
TempTDTM: TDTM;
begin
If FawkiDebug then Writeln('Assembling door...');
DTMMainPoint.x:=MMCx;
DTMMainPoint.y:=MMCy;
DTMMainPoint.areasize:=1;
DTMMainPoint.areashape:=0;
DTMMainPoint.color:=16777215;
DTMMainPoint.tolerance:=255;
DTMSubPoints[0].x:=610;
DTMSubPoints[0].y:=67;
DTMSubPoints[0].areasize:=1;
DTMSubPoints[0].areashape:=0;
DTMSubPoints[0].color:=DoorColor;
DTMSubPoints[0].tolerance:=0;
DTMSubPoints[1].x:=614;
DTMSubPoints[1].y:=67;
DTMSubPoints[1].areasize:=1;
DTMSubPoints[1].areashape:=0;
DTMSubPoints[1].color:=DoorColor;
DTMSubPoints[1].tolerance:=0;
DTMSubPoints[2].x:=617;
DTMSubPoints[2].y:=67;
DTMSubPoints[2].areasize:=1;
DTMSubPoints[2].areashape:=0;
DTMSubPoints[2].color:=DoorColor;
DTMSubPoints[2].tolerance:=0;
TempTDTM.MainPoint := DTMMainPoint;
TempTDTM.SubPoints := DTMSubPoints;
DoorDTM := AddDTM(TempTDTM);
If FawkiDebug then Writeln('Assembling door... Done.');
end;
You dont need to know how this works exactly, as long as you have a basic understanding what's going on. There are a couple of thing noteworthy:
This particular DDTM has one MainPoint (or centre point: The DTMMainPoint, the first point of our DDTM). The Mainpoint coords are MMCx and MMCy (where I am standing), and the color tolerance is 255, meaning it can be any color. I am simply not interested in that color. You will understand this later on.
This particular DDTM also has three subpoints. Lets examine these a little closer. Notice they all have distinct x and y coords. The y coords are all the same, and the x coords are 7 pixels apart. The three subpoints form in fact the outer boundaries of the barndoor. I sampled the subpoint coords while standing at Centre of Draynor Square. I wrote them down and typed then into the AssembleDTM procedure.
Notice also the Subpoints Tolerance is 0. This means I will be using the DDTM for one color and one color only, namely the DoorColor I will grab at script startup.
Grabbing the DDTM Color
Now I need to grab the DoorColor at script startup and pass it to the DoorColor variable in AssembleDDTM. This can be done manually, but then you will need to do this every time you run the script. Done this for some time, but is not really necessary if you know how to solidly grab a color. For that I wrote another function I always use:
Simba Code:
Function GetMyColorTPA(BaseColor, MinSize, MaxSize, x1, y1, x2, y2, tol:integer): Integer;
var
TPA: TPointArray;
begin
if FindColorsTolerance(TPA, BaseColor, x1, y1, x2, y2, tol) then
begin
if Fawkidebug then Writeln('Len TPA = ' + IntToStr(High(TPA)));
If (High(TPA) > MinSize) and (High(TPA) < MaxSize) then
begin
Result := GetColor(TPA[0].x, TPA[0].y);
Writeln('Storing Color ' + IntToStr(Result) + '...');
end
else
begin
if Fawkidebug then WriteLn('ERROR: NO COLOR FOUND');
Result := -1;
end
end
else
begin
if Fawkidebug then WriteLn('ERROR: NO COLOR FOUND');
Result := -1;
end;
end;
This function inputs a basecolor, min and maxsize of the object, and the boundary box of the area where to find this object. Again, there is no real need to fully comprehend what is going on in this function (though it is pretty straightforward) as long as you basically understand what i am doing here.
At script startup I make sure I am standing approximately at the DDTM Centre Point. (That explains why I keep it's tolerance at 255, so it doesn't matter what color it sees in relation to the DDTM subpoints). I use
Simba Code:
DoorColor:= GetMyColorTPA(131316,1,22, MMx1, MMy1, MMcx, MMcy, 20)
Writeln('Doorcolor = ' + IntToStr(DoorColor));
AssembleDTM;
and voila, I know where I am.
Checking to see if it works
Next we need to check runtime if the DDTM works. For that i have an also stone-old function called Callibrate.
Simba Code:
Function Callibrate(Offset:String): Boolean; // uses the red lines of the barndoor as ddtm
var // to callibrate all around draynor square.
Ox, Oy, x,y:Integer;
WhichAngle: Extended;
Begin
If not loggedin then begin Logout; ProgressReport; LeaveLobby; result := false; exit; end;
FTWait(1); // for randoms checking
case LowerCase(Offset) of
'c': // Centre
begin
Ox := 0;
Oy := 0;
Players[CurrentPlayer].loc :='C'
end;
'bank': // One click straight into the bank
begin
Ox := 50
Oy := 40;
Players[CurrentPlayer].loc :='Bank'
end;
'l': // To left of square
begin
Ox := -20;
Oy := 10;
Players[CurrentPlayer].loc :='CT'
end;
't': // To top of square
begin
Ox := 10;
Oy := -12;
Players[CurrentPlayer].loc :='LT'
end;
'r': // To right of square
begin
Ox := 20;
Oy := 10;
Players[CurrentPlayer].loc :='LT'
end;
'b': // To bottom of square
begin
Ox := 0;
Oy := 30;
Players[CurrentPlayer].loc :='RT'
end;
end
if FindDtmRotatedSE(DoorDTM, x, y, MMX1, MMY1, MMX2, MMY2, rs_GetCompassAngleRadians-pi, rs_GetCompassAngleRadians+pi, 0.05,
WhichAngle) then
begin
if rs_OnMiniMap(x,y) then
begin
MFF(x + Ox, y + Oy, 1, -1);
FFlag(0);
FTWait(1);
Result := True;
If FawkiDebug then writeln(' Callibrate -> ' + Offset + ' Succesfull !');
Exit;
end
else
If FawkiDebug then writeln('Coords for ' + Offset + ' are not on minimap');
end
else
begin
Result := False;
If FawkiDebug then writeln(' Couldnt Callibrate -> ' + Offset + ' !');
end;
end;
All this function does is click the DDTM with an offset, if it is visible on the minimap. Callibrate('C') f.i. Callibrates uses a X & Y -Offset of zero pixels (Ox:= 0; Oy := 0). Again, I never reprogram this function; I simply copy paste and adjust it to the scripts need.
Here is graphically what Callibrate does:
Done. This is the basic technique. You call Callibrate whenever you need it, and it lasso's you back to the desired point. You might want make a DTM checker that stores the last known coordinates. You call as often as you can and reposition your player when the DTM is not on the MM. But that is beyond the scope of this little tutorial.
There are always unique color combinations on the rs minimap. Try this technique out, you will see it is simple yet effective and it works regardless of color and rotation.
WT!