Making your own uptext function
Making your own uptext for your RSPS of choice is a pretty good idea if you want to find objects that may have the same colors as others. Uptext will help you always click on the correct object! Now this section is not on creating a font set, it's on creating your own uptext so we will be taking a shortcut: There are 1 of 2 font sets the RSPS will use, either 'P07Chars' (even if the server is from 2008-2011!) or the current upchars set! This means we can use the font set that is already on your computer. In order to get the uptext we will be using GetTextATPA, because it is IMO the most easy to use.
Simba Code:
GetTextATPA(ATPA:T2DPointArray, maxvspacing:LongInt, font:String):string;
First, we are going to want to grab the colors of the text, you WILL need to get the best coloring using ACA(this is a intermediate tutorial I am going to assume you know how to grab good colors using ACA). You will have to keep relogging until ACA highlights all of the uptext. Re-log a few times to make sure it finds all of the uptext like this:
First make a function and define the variables needed for a TPA and ATPA:
Simba Code:
function rsps_getUpText:string;
var
blueTPA: tpointarray;
blueATPA: t2dpointarray;
Next, you will want to find all of the text color of your choice:
Simba Code:
FindColorsTolerance(blueTPA, color, X1, Y1, X2, Y2, tol);
Make sure the area it's searching is were the uptext is!
Next, if the length is > 1 then we want to continue:
Simba Code:
if (length(blueTPA) > 1) then
After it continues, we want to split it into an ATPA:
Simba Code:
blueATPA := splitTPAEx(blueTPA, 1, 10);
Next we want to sort the ATPAs from 0,0 so the text does not end up all jumbled up!
Simba Code:
sortATPAFromFirstPointX(blueATPA, point(0, 0));
Now we return whatever GetTextATPA finds:
Simba Code:
result:= getTextATPA(blueATPA, 5, 'UpChars07');
blueATPA is the found ATPA, 5 is the minimum vertical spacing(you may have to play around with this) and 'UpChars07' is the font set that is located in C:Simba/fonts
This should return 99% accurate uptext. If it does not then debug the TPA to make sure it's finding all of the text:
Simba Code:
DebugTPA(blueTPA, 'bmp');
(bmp must be declared as a interger)
Reasons for incorrect uptext:
-Wrong or bad font set
-Bad colors
-Not searching in the whole uptext area
Map Walking
Get Compass Angle
In order to accurately walk, you are going to have to make a function that will correctly be able to either:
A) Make the Compass close to perfect north
B) Be able to accurately determine the compass angle
I am going to start with being able to determine the compass angle first, because it will make making the compass to perfect north more easy.
Getting the exact compass angle in (degrees) is fairly easy because there is already a function for that in SRL! Why re-invent the wheel?
Simba Code:
Function rsps_GetCompassAngleRadians: Extended;
var
TPA: TPointArray;
T: TPoint;
B: TBox;
begin
B := IntToBox(519, 1, 564, 46);
with B do
FindColorsSpiralTolerance(T.x, T.y, TPA, 1911089, x1, y1, x2, y2, 0);
if Length(TPA) < 1 then
exit;
T := MiddleTPA(TPA);
Result := ArcTan2(-(T.Y - 24), T.X - 543) + Radians(90);
Result := fixRad(Result - Pi);
end;
Now all of this is confusing right? WRONG! There are only 2 lines that we need to edit:
this:
Code:
B := IntToBox(519, 1, 564, 46);
Change the numbers to the bounds of the compass (hopefully you know how to do this?) This box is were it's going to search for the color. Make it as EXACT as possible
and this:
Change COLOR to the color of the 'N' on the compass
Code:
FindColorsSpiralTolerance(T.x, T.y, TPA, COLOR, x1, y1, x2, y2, 0);
and then your done... getting the compass angle in radians. To get it in degrees just do:
Simba Code:
function rsps_GetCompassAngleDegrees: Extended;
begin
Result := Degrees(rsps_GetCompassAngleRadians());
end;
SPS
This tutorial will not cover how to SPS walk, it will cover how to edit SPS to work on the RSPS of your choice. Editing SPS is fairly simple, open up SPS.simba (C:\Simba\Includes\SPS). Now paste the SPS source into a new simba script, and save that simba script to your include folder. Now, it is important that you do everything I say or else it won't work. Here is what my SPS.simba looks like so you can accurately follow along:
Simba Code:
(*
SPS ~ SRL Positioning System
============================
Concept and original work done by marpis @ SRL-Forums. Work continued by Coh3n
and members of the SRL community.
*)
{$loadlib sps}
const
// Path where all the SPS files are
SPS_IMG_PATH = IncludePath + 'SPS\img\';
SPS_IMG_FMT = '.png';
// Surfaces
RUNESCAPE_SURFACE = 0;
RUNESCAPE_SURFACE_FOLDER = 'runescape_surface\';
RUNESCAPE_OTHER = 1;
RUNESCAPE_OTHER_FOLDER = 'runescape_other\';
// User defined SPS global variables
var
SPS_Debug: boolean;
SPS_MultiMouse: boolean; // simulates a human like "spam-click" when walking
SPS_AnyAngle: boolean; // true = work at any angle; false = only north
SPS_ClickNorth: boolean; // call ClickNorth instead of MakeCompass to set the compass to north
// SPS Global variables
var
SPS_Areas: TStringArray;
SPS_AreaMaps: T3DIntegerArray; // Grids of the combined SPS_Areas
SPS_Tolerance, SPS_MatchesPercent: extended;
SPS_Accuracy: integer; // Splits minimap/areas into squares of this side length; used for area recognition
SPS_IsSetup: boolean; // Used to make sure the user calls SPS_Setup
// Author: marpis & Coh3n
// Returns an image of the minimap in a TMufasaBitmap
function SPS_GatherMinimap: TMufasaBitmap;
var
c: TClient;
begin
try
Result := TMufasaBitmap.Create;
Result.SetSize(150, 150);
c := getTClient;
Result.CopyClientToBitmap(
c.IOManager, false, 0, 0, MMCX-75, MMCY-75, MMCX+75, MMCY+75
);
except
Writeln('SPS_GatherMinimap ERROR: '+ExceptionToString(ExceptionType, ExceptionParam));
end;
end;
// Author: Ollybest & J J
// gets the rotated RS minimap and rotates to face north
// needed for SPS to work at any compass angle
function SPS_RotateMinimap: TMufasaBitmap;
var
W, H, t: Integer;
mmBMP, rBMP: TMufasaBitmap;
MiddleBMP: TPoint;
begin
try
t := getSystemTime();
//gathering minimap
mmBMP := SPS_GatherMinimap;
//rotating minimap
rBMP := GetMufasaBitmap(RotateBitmap(mmBMP.index, 0-rs_GetCompassAngleRadians))
//getting the middle of the rotated bitmap
GetBitmapSize(rBMP.Index, W, H);
MiddleBMP := Point(W/2, H/2);
//creating the result by using a 74 radius around the centre
Result := rbmp.Copy(MiddleBMP.X-74, MiddleBMP.Y-74, MiddleBMP.X+74, MiddleBMP.Y+74);
mmBMP.free
rbmp.free
If SPS_Debug Then
Writeln('Rotating map took '+toStr(getSystemTime - t)+' ms.');
except
Writeln('SPS_RotateMinimap ERROR: '+ExceptionToString(ExceptionType, ExceptionParam));
end;
end;
// Author: marpis & Coh3n
// Gets the starting area coordinates depending on the area image
procedure SPS_GetAreaCoords(Area: string; var x, y: integer);
var
p: integer;
begin
// if it's a specific dungeon map (i.e. name isn't 0_0, 10_2, etc.)
if (length(getNumbers(Area)) < 2) then
begin
x := 0;
y := 0;
Exit;
end;
p := pos('_', Area);
x := StrToIntDef(copy(Area, 1, p - 1), -1);
y := StrToIntDef(copy(Area, p + 1, Length(Area) - p), -1);
//writeln('SPS_GetAreaCoords: '+toStr(point(x, y)));
end;
// Author: marpis
// Converts a point from a map piece to a point on the entire map
function SPS_LocalToGlobal(Area: string; x, y: integer): TPoint;
var
cx, cy: integer;
begin
SPS_GetAreaCoords(Area, cx, cy);
Result.x := (cx * 400) + x;
Result.y := (cy * 400) + y;
end;
// Author: marpis
// Converts a point from the entire map to a point on the main screen
function SPS_GlobalToLocal(x, y: integer): TPoint;
var
cx, cy: integer;
begin
cx := Floor(x / 400);
cy := Floor(y / 400);
Result.x := x - (cx * 400);
Result.y := y - (cy * 400);
end;
// Author: marpis
// Returns the coordinates (x, y) in the form of a string
function SPS_AreaCoordsToString(x, y: integer): string;
begin
Result := IntToStr(x)+'_'+IntToStr(y);
end;
// Author: Coh3n
// Returns a TPA of the areas' values
function SPS_TPAFromAreas(areas: TStringArray): TPointArray;
var
i: integer;
begin
setLength(result, length(areas));
for i := 0 to high(areas) do
SPS_GetAreaCoords(areas[i], result[i].x, result[i].y);
end;
// Author: Coh3n
// Sorts the areas by columns, and sorts each column by rows
// Example: ['1_5', '1_3', '0_5'] results ['0_5', '1_3', '1_5']
function SPS_SortAreas(areas: TStringArray): TStringArray;
var
i, j: integer;
tpa: TPointArray;
begin
setLength(tpa, length(areas));
tpa := SPS_TPAFromAreas(areas);
clearDoubleTPA(tpa);
sortTPAByX(tpa, true); // first sort by column number
// then sort the Y values for each column number
for i := 0 to high(tpa) do
for j := i to high(tpa) do
if (tpa[i].x = tpa[j].x) then
if (tpa[i].y > tpa[j].y) then
tSwap(tpa[i], tpa[j]);
setLength(result, length(tpa));
for i := 0 to high(tpa) do
result[i] := SPS_AreaCoordsToString(tpa[i].x, tpa[i].y);
//writeln('SPS_SortAreas: '+toStr(result));
end;
// Author: Coh3n
// Loads the "Area" image
function SPS_GetArea(Area: string; surface: integer): TMufasaBitmap;
var
x, y: integer;
S: string;
begin
SPS_GetAreaCoords(Area, x, y);
case surface of
RUNESCAPE_SURFACE: s := RUNESCAPE_SURFACE_FOLDER;
RUNESCAPE_OTHER: s := RUNESCAPE_OTHER_FOLDER;
end;
try
Result := TMufasaBitmap.Create;
Result.LoadFromFile(SPS_IMG_PATH + s + Area + SPS_IMG_FMT);
except
Writeln('SPS_GetArea ERROR: '+ExceptionToString(ExceptionType, ExceptionParam));
end;
end;
// Author: Coh3n
// Merges the SPS 'areas' into one bitmap (makes more more accurate GetMyPos)
function SPS_MergeAreas(areas: TStringArray): TMufasaBitmap;
var
t, i, l, x, y, diffX, diffY, newWidth, newHeight: integer;
startPoint: TPoint;
newAreas: TStringArray;
xVals, yVals: TIntegerArray;
bmpTemp: TMufasaBitmap;
tmpTPA: TPointArray;
begin
if (length(areas) <= 0) then
exit;
t := getSystemTime();
// sort the areas from by columns/rows; remove duplicates
newAreas := SPS_SortAreas(areas);
l := length(newAreas);
// if there's only one area in the array
if (l = 1) then
begin
result := SPS_GetArea(areas[0], RUNESCAPE_SURFACE);
exit;
end;
// get the x and y values for each area
setLength(xVals, l);
setLength(yVals, l);
for i := 0 to high(newAreas) do
SPS_GetAreaCoords(newAreas[i], xVals[i], yVals[i]);
// get the lowest Y value so we can calculate the starting point to draw the first image
tmpTPA := SPS_TPAFromAreas(newAreas);
sortTPAByY(tmpTPA, true);
try
result := TMufasaBitmap.create();
// calculate the starting point
// x is always 0 because of how the areas are sorted
// y is relative to the lowest y value in the areas
SPS_GetAreaCoords(newAreas[0], x, y);
startPoint.x := 0;
startPoint.y := ((y - tmpTPA[0].y) * 400);
// draw the first area to the starting point on the bitmap
bmpTemp := SPS_GetArea(newAreas[0], RUNESCAPE_SURFACE);
result.SetSize(bmpTemp.width, bmpTemp.height + startPoint.y);
bmpTemp.fastDrawTransparent(startPoint.x, startPoint.y, result);
bmpTemp.free();
// loop through each area, drawing them to the result bitmap
// coordinates are calculated relative to the first area drawn (areas[0])
for i := 0 to (l - 2) do
begin
diffX := (xVals[i + 1] - xVals[0]);
diffY := (yVals[i + 1] - yVals[0]);
newWidth := 500 + (round(abs(diffX)) * 400);
newHeight := 500 + (round(abs(diffY)) * 400);
// only set the size if the width or height is increasing
if (newWidth > result.width) then
result.setSize(newWidth, result.height);
if (newHeight > result.height) then
result.setSize(result.width, newHeight);
// copy the area image to the resulting bitmap
bmpTemp := SPS_GetArea(newAreas[i + 1], RUNESCAPE_SURFACE);
bmpTemp.fastDrawTransparent(startPoint.x + (diffX * 400 + 1),
startPoint.y + (diffY * 400 + 1), result);
bmpTemp.free();
end;
//result.saveToFile('C:/Simba/test.bmp');
except
Writeln('SPS_MergeAreas ERROR: '+ExceptionToString(ExceptionType, ExceptionParam));
end;
if (SPS_Debug) then
writeln('SPS_MergeAreas: Merged areas in '+toStr(getSystemTime - t)+' ms.');
end;
// Author: Coh3n
// Returns an SPS area of lowest x and y value. Used for calculating the
// player's correct position
function SPS_GetTopLeftCoords(areas: TStringArray): string;
var
tpa: TPointArray;
begin
tpa := SPS_TPAFromAreas(areas);
if (length(tpa) <= 0) then
begin
result := '0_0';
exit;
end;
sortTPAByX(tpa, true);
result := toStr(tpa[0].x);
sortTPAByY(tpa, true);
result := result + '_'+toStr(tpa[0].y);
//writeln('SPS_GetTopLeftCoords: '+result);
end;
// Author: marpis & SRL Community
function SPS_GetMyPos(): TPoint;
var
Minimap: TMufasaBitmap;
SmallMap: T3DIntegerArray;
a, t, FoundMatches: integer;
P: TPoint;
Searches: extended;
begin
Result := Point(-1, -1);
if (not SPS_IsSetup) then
begin
writeln('SPS ERROR: SPS_Setup was never called');
exit;
end;
if (not LoggedIn) then
Exit;
if (SPS_Tolerance < 1.0) then
SPS_Tolerance := 600.0;
if (SPS_MatchesPercent = 0.0) then
SPS_MatchesPercent := 0.35;
a := round(rs_GetCompassAngleDegrees);
if (SPS_AnyAngle) and (inRange(a, 10, 350)) then
Minimap := SPS_RotateMinimap()
else begin
if (inRange(a, 10, 350)) then
if (SPS_ClickNorth) then
ClickNorth(SRL_ANGLE_HIGH)
else
MakeCompass('N');
Minimap := SPS_GatherMinimap();
end;
t := getSystemTime();
SPS_FilterMinimap(Minimap);
//DrawBitmapDebugImg(Minimap.Index);
//DisplayDebugImgWindow(150, 150);
{$IFDEF SIMBAMAJOR990}
SetLength(SmallMap, 0); // Using this instead of SmallMap := [];
SPS_BitmapToMap(Minimap, SPS_Accuracy, SmallMap);
{$ELSE}
SmallMap := [];
SmallMap := SPS_BitmapToMap(Minimap, SPS_Accuracy);
{$ENDIF}
FoundMatches := SPS_FindMapInMap(P.x, P.y, SPS_AreaMaps, SmallMap, SPS_Tolerance);
Searches := ((Minimap.Width / SPS_Accuracy) * (Minimap.Height / SPS_Accuracy));
{
writeln('fx: '+toStr(p.x)+' ~ on area: '+toStr(P.X * SPS_Accuracy + (Minimap.Width / 2)));
writeln('fy: '+toStr(p.y)+' ~ on area: '+toStr(P.Y * SPS_Accuracy + (Minimap.Width / 2)));
writeln('matches: '+toStr(foundMatches));
writeln('searches: '+toStr(searches));
writeln('percent: '+toStr(FoundMatches / Searches));
}
if ((FoundMatches / Searches) > SPS_MatchesPercent) then
Result := SPS_LocalToGlobal(SPS_GetTopLeftCoords(SPS_Areas), // the top left of the total area
P.x * SPS_Accuracy + (Minimap.Width / 2),
P.y * SPS_Accuracy + (Minimap.Width / 2));
Minimap.Free;
t := (GetSystemTime - t);
if (SPS_Debug) then
Writeln('SPS_GetMyPos: Finished in '+ToStr(t)+' ms. Result = '+ToStr(Result));
end;
// Author: marpis
// Finds position P in minimap by checking your own location
function SPS_PosToMM(P: TPoint): TPoint;
var
MyPos: TPoint;
begin
if not LoggedIn then
Exit;
Result := Point(-1, -1);
MyPos := SPS_GetMyPos;
if (Distance(MyPos.X, MyPos.Y, P.X, P.Y) < 75) then
Result := RotatePoint(Point(MMCX + P.X - MyPos.X, MMCY + P.Y - MyPos.Y), 0-rs_GetCompassAngleRadians, MMCX, MMCY);
end;
// Author: marpis
// Walks to position, P.
function SPS_WalkToPos(P: TPoint): boolean;
var
MM: TPoint;
begin
if not LoggedIn then
Exit;
MM := SPS_PosToMM(P);
if (MM.X > 0) then
begin
if (SPS_MultiMouse) then
MultiMouse(MM.X, MM.Y, 25, 3, false)
else
Mouse(MM.X, MM.Y, 0, 0, mouse_Left);
if WaitFunc(@IsMoving, 1, 3000 + random(500)) then
while IsMoving do
Flag;
Result := True;
end;
end;
// Author: marpis
// Returns true if the point "Pt" is on the minimap
function SPS_PosOnMM(Pt: TPoint): Boolean;
var
p: TPoint;
begin
p := SPS_PosToMM(Pt);
Result := rs_OnMinimap(p.x, p.y);
end;
// Author: marpis & Coh3n
// Walks the path "Path"; always walks to the furthest point possible
function SPS_WalkPath(Path: TPointArray): boolean;
var
I, H, T, D, Fails: integer;
P, MM, MMF: TPoint;
begin
if (not SPS_IsSetup) then
begin
writeln('SPS ERROR: SPS_Setup was never called');
exit;
end;
H := High(Path);
T := GetSystemTime + 20000 + Random(5000);
Fails := 0;
while (not Result) and (GetSystemTime < T) and (Fails < 5) do
begin
if (not LoggedIn()) then
Exit;
RunEnergy(20);
P := SPS_GetMyPos();
for I := H downto 0 do
begin
MM := RotatePoint(Point(MMCX + Path[I].X - P.X, MMCY + Path[I].Y - P.Y),
0-rs_GetCompassAngleRadians, MMCX, MMCY);
if MM = MMF then
Inc(Fails);
D := Distance(MM.X, MM.Y, MMCX, MMCY);
if (D < 10) then
break
else
if (D < 70) then
begin
if (SPS_MultiMouse) then
MultiMouse(MM.X, MM.Y, 25, 3, false)
else
Mouse(MM.X, MM.Y, 5, 5, mouse_Left);
MMF := MM;
FFlag(5 + (Integer(I <> H) * 15));
T := getSystemTime + 20000 + Random(1000);
Break;
end;
end;
Result := (I = H);
end;
end;
// Walks blindly from the player's current position to the point T
function SPS_BlindWalk(P: TPoint): Boolean;
var
Tries: Integer;
M: TPoint;
ctrlPoints: TPointArray;
begin
if (not SPS_IsSetup) then
begin
writeln('SPS ERROR: SPS_Setup was never called');
exit;
end;
repeat
if (not LoggedIn()) then
Exit;
M := SPS_GetMyPos();
if (M.X = -1) then
Continue;
if (Length(ctrlPoints) = 0) then
ctrlPoints := TPABetweenPoints(Point(M.X, M.Y), Point(P.X, P.Y), 20 + Random(15), 10);
Inc(Tries);
if (Tries > 20) then
Exit;
Result := SPS_WalkPath(ctrlPoints);
until(Result);
end;
// Author: Coh3n
// Sets up SPS; needs to be called if you want to switch RS surfaces
function SPS_Setup(surface: integer; areas: TStringArray): boolean;
var
t: integer;
tmp: TMufasaBitmap;
begin
t := getSystemTime;
setLength(SPS_AreaMaps, 0);
setLength(SPS_Areas, 0);
SPS_MultiMouse := true;
SPS_Accuracy := 4;
if (length(areas) > 0) then
begin
if (surface = RUNESCAPE_SURFACE) then
tmp := SPS_MergeAreas(areas) // combine the SPS areas into 1; makes for a more accurate read
else
if (surface = RUNESCAPE_OTHER) then
if (length(areas) = 1) then
tmp := SPS_GetArea(areas[0], surface)
else begin
writeln('SPS_Setup(): Invalid dungeon areas. You can only select one!');
exit;
end;
SPS_IsSetup := true;
result := true;
{$IFDEF SIMBAMAJOR990}
SPS_BitmapToMap(tmp, SPS_Accuracy, SPS_AreaMaps);
{$ELSE}
SPS_AreaMaps := SPS_BitmapToMap(tmp, SPS_Accuracy);
{$ENDIF}
if (surface = RUNESCAPE_SURFACE) then
SPS_Areas := SPS_SortAreas(areas)
else
if (surface = RUNESCAPE_OTHER) then
SPS_Areas := areas;
tmp.free();
end else
writeln('SPS_Setup(): ERROR: SPS areas are not set!');
t := (getSystemTime - t);
if (SPS_Debug) and (result) then
writeln('[SPS] SPS_Setup() took '+toStr(t)+' ms. Areas: '+toStr(SPS_Areas));
end;
Step 1)
Go to line 51. Were it says:
Simba Code:
c.IOManager, false, 0, 0, MMCX-75, MMCY-75, MMCX+75, MMCY+75
Change MMCX and MMCY to the center of the minimap of your RSPS of choice. Change 75 to the distance from the center of the minimap to the very edge of the minimap (probably still 75, but you can change it if you want it to be exact)
step 2)
Go to line 340. Were it says
Simba Code:
if (not LoggedIn) then
Exit;
There are 1 of 2 things you can do:
1) make your own logged in function and change it to that
2) Erase those 2 lines
Step 3) go to line 403. Repeat step 2, and then go to line 410 were it says:
Simba Code:
Result := RotatePoint(Point(MMCX + P.X - MyPos.X, MMCY + P.Y - MyPos.Y), 0-rs_GetCompassAngleRadians, MMCX, MMCY);
Change all MMCX and MMCY to the center of your minimap, and change rs_GetCompassAngleRadians to your compass function that you created in the compass section(MAKE SURE IT'S THE RADIANS ONE)
Step 4) Go to line 419. Repeat step 2. Go to line 432, were it says
Create a procedure that will look for the flag DTM on your minimap and wait until it's gone. Replace 'Flag' with this procedures name. Here is what mine looks like:
Simba Code:
function rsps_FFlag:Boolean;
var
x, y:Integer;
begin
result := FindDTM(Flag_DTM, x, y, rsps_MMX1, rsps_MMY1, rsps_MMX2, rsps_MMY2);
end;
procedure rsps_Flag;
begin
waitFunc(@rsps_FFlag, 100, 6000);
end;
Replace rsps_MMX1, rsps_MMY1, rsps_MMX2, and rsps_MMY2 with the bounds of the minimap.
Step 5) Go to line 468. Repeat step 2 again and then go to line 476 were it says:
Simba Code:
MM := RotatePoint(Point(MMCX + Path[I].X - P.X, MMCY + Path[I].Y - P.Y),
0-rs_GetCompassAngleRadians, MMCX, MMCY);
Change all MMCY and MMCX to the center of your minimap, and rs_GetCompassAngleRadians to your compass functions to get the compass angle(MAKE SURE IT'S THE RADIANS ONE)
Step 6) Go to line 520, and repeat step 2 yet again(you catching what I'm doing yet?) and your done!
In order for SPS to work for your RSPS of your choice you will have to use custom maps, guide on how to use custom maps:
http://villavu.com/forum/showthread.php?t=84360
DTM
DTM walking is a good way to walk if your too lazy to edit SPS or if the compass angle is > 15 degrees off the actual minimap. In order for a DTM to be found accurately we must use FindDTMRotated. This will look for the DTM as different angles! But before we do that, you should learn how to create a good DTM on the minimap. First, open up Simba's DTM editor. Next, find the point you want to walk and click there, and then make the tolerance '255'. Example:
Next, create points with a tolerance of around 35-40 on areas were NPCs/Players can't walk:
Now click show matching DTM's and make sure the point you want to walk at is the only red point:
Next, use the FindDTMRotated function to click on it:
Simba Code:
FindDTMRotated(DTM, x, y, rsps_MMX1, rsps_MMY1, rsps_MMX2, rsps_MMY2, startD, endD, step, FA)
startD is the start angle it will look for the DTM, I always put 0, endD is the ending angle that it will look for the DTM at I always put 360, and step is the amount (in degrees) that it will look each time. So if you put 10.00 as step, it will start at startD degrees, go to 10.00, go to 20.00 and so on until it reaches the endD degrees. The lower the number you put, the longer it will take. I advise (if) you are just going to look for 1 7.00-10.00.
Now just looking for 1 DTM for 1 point may not be accurate, so I created this function that allows you have have multple DTMs each point. If the first DTM isn't found for the point, it moves onto the second, then third etc etc.
function:
Simba Code:
function walk_dtmPath(Points:T2DIntegerArray):Boolean;
var
i, l, x, y:Integer;
FA:Extended;
begin
for i := 0 to high(Points) do
begin
for l := 0 to high(Points[i]) do
begin
if FindDTMRotated(Points[i][l], x, y, rsps_MMX1, rsps_MMY1, rsps_MMX2, rsps_MMY2, 0, 360, 14.00, FA) then
begin
if (distance(x, y, 648, 83) > 15) then
begin
Mouse(x, y, 0, 0, Mouse_left);
wait(1200);
if (rsps_FFlag) then
begin
rsps_Flag;
break;
end;
end;
end;
end;
end;
end;
Of course you will have to make your own rsps_FFlag and rsps_Flag functions.
Here is how I use it. First I declare a path as a record:
Simba Code:
type Path = record
dtmpoint:T2DIntegerArray;
end;
Next, I create a variable and make it refer to that record like so:
And then I declare DTMs for each point:
Simba Code:
toBank.dtmPoint[0][0] := DTMFromString('m1gAAAHic42JgYOhiYmCoBeJZQNwLxCVAvBqIC4G4DSo+H4gdgGoNgdgEiA2A2AmI/YDYEsq3A2JXIH77loHhzZMXePG7d+8Y/gPV6hKBGYnECAAAvt4k7w==');
To add another DTM for that point just increase the second 0 by 1:
Simba Code:
toBank.dtmPoint[0][1] := DTMFromString('mrAAAAHic42BgYJjHxMCwFIjXAPFGIN4CxJuAeD4QdwJxKlBNKRBnM0DYMUAcDsRlQFwIxGfOMDC8efICBb979w7O1gWqwYcZCWAYAAAybh6t');
Then to add Points increase the first 0 by 1. Example of a path with 4 points:
Simba Code:
toBank.dtmPoint[0][0] := DTMFromString('m1gAAAHic42JgYOhiYmCoBeJZQNwLxCVAvBqIC4G4DSo+H4gdgGoNgdgEiA2A2AmI/YDYEsq3A2JXIH77loHhzZMXePG7d+8Y/gPV6hKBGYnECAAAvt4k7w==');
toBank.dtmPoint[0][1] := DTMFromString('mrAAAAHic42BgYJjHxMCwFIjXAPFGIN4CxJuAeD4QdwJxKlBNKRBnM0DYMUAcDsRlQFwIxGfOMDC8efICBb979w7O1gWqwYcZCWAYAAAybh6t');
toBank.dtmPoint[1][0] := DTMFromString('blahblahhhfdjfk');
toBank.dtmPoint[1][1] := DTMFromString('dfgsdfgdfsd');
toBank.dtmPoint[1][2] := DTMFromString('dsfgfdsgdfdg');
toBank.dtmPoint[2][0] := DTMFromString('blahblahhhfdjfk');
toBank.dtmPoint[2][1] := DTMFromString('dfgsdfgdfsd');
toBank.dtmPoint[3][0] := DTMFromString('blahblahhhfdjfk');
toBank.dtmPoint[3][1] := DTMFromString('dfgsdfgdfsd');
toBank.dtmPoint[3][2] := DTMFromString('dsfgfdsgdfdg');
And then to walk the path I just do
Simba Code:
walk_dtmPath(ToBank.dtmPoint);
Inventory functions
Inventory functions are hella useful. I will be using @
Janilabo's Explode box function here! Ok first let's say you want to get the amount of items in your inventory. First declare a TBoxArray variable:
Next use this function to make the variable Inventory Represent every one of the inventory slots:
Simba Code:
function ExplodeBox(bx: TBox; rows, columns: integer): TBoxArray;
var
r, c, w, h, ew, eh, ow, oh, i, x, y: integer;
begin
if ((rows > 0) and (columns > 0) and (bx.X1 <= bx.X2) and (bx.Y1 <= bx.Y2)) then
begin
w := ((bx.X2 - bx.X1) + 1);
h := ((bx.Y2 - bx.Y1) + 1);
if (rows < 1) then
rows := 1
else
if (rows > h) then
rows := h;
if (columns < 1) then
columns := 1
else
if (columns > w) then
columns := w;
w := (w div columns);
h := (h div rows);
ew := (((bx.X2 - bx.X1) + 1) - (w * columns));
eh := (((bx.Y2 - bx.Y1) + 1) - (h * rows));
SetLength(Result, (rows * columns));
y := bx.Y1;
for r := 0 to (rows - 1) do
begin
x := bx.X1;
if ((eh > 0) and (r < eh)) then
oh := 1
else
oh := 0;
for c := 0 to (columns - 1) do
begin
if ((ew > 0) and (c < ew)) then
ow := 1
else
ow := 0;
i := ((r * columns) + c);
Result[i].X1 := x;
Result[i].X2 := (x + (w - 1) + ow);
Result[i].Y1 := y;
Result[i].Y2 := (y + (h - 1) + oh);
x := (Result[i].X2 + 1);
end;
y := (Result[i].Y2 + 1);
end;
end else
SetLength(Result, 0);
end;
You use it by getting the exact bounds of the inventory:
The most easy way to do this is to put a large item in the first slot, and another large item in the last slot.
Simba Code:
Inventory := ExplodeBox(IntToBox(X1, Y1, X2, Y2), 7, 4);
7 is the number of rows, 4 is the number of colums.
Replaces X1, Y1, X2, and Y2 with the bounds of the inventory.
Now, EVERY SINGLE item in the whole entire game of Runescape that has ever been released has a black outline. There is no such thing as an item without a black outline, we you will have to find out what color that is by finding.... the black outline on a item like this:
The color will usually 65536 but it's different for some servers. I advise you use ACA so you can make sure the color you chose is infact the black outline. As you can see here, 65536 is infact the black outline:
Now first, we want to see if a selected slot is full:
Simba Code:
function rsps_slotFull(slot:Integer):Boolean;
var
x, y:Integer;
begin
if FindColor(x, y, 65536, Inventory[slot].x1, Inventory[slot].y1, Inventory[slot].x2, Inventory[slot].y2) then
result := true;
end;
This will look at the index that you have chosen, so if you do rsps_slotFull(0) it will check the first slot.
Now to get the inventory count, all you have to do is call the rsps_slotFull function inside of another function like so:
Simba Code:
function rsps_Invcount:Integer;
var
i:Integer;
begin
for i := 0 to high(Inventory) do
begin
if rsps_slotFull(i) then
result := result + 1;
end;
end;
TADA!
Infull:
Simba Code:
function rsps_invFull:Boolean;
begin
result := (rsps_invcount = 28);
end;
Count Item(DTM):
Simba Code:
function rsps_CountInventoryDTM(DTMSearch:Integer):Integer;
var
i, x, y:Integer;
begin
for i := 0 to high(Inventory) do
begin
if FindDTM(DTMSearch, x, y, Inventory[i].x1, Inventory[i].y1, Inventory[i].x2, Inventory[i].y2) then
result := result + 1;
end;
end;
Hope this guide help! If you see any grammar mistakes or need help just post below