Advertisement
WarPie90

Auto map builder for RS

Apr 1st, 2024 (edited)
1,120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 8.51 KB | None | 0 0
  1. program MinimapCapture;
  2. {$I SRL-T/osr.simba}
  3. (*
  4.   Simple program to capture the minimap at 400x400 from the memory of RS.
  5.   Requires: https://github.com/slackydev/Simba-MemScan/releases/tag/1.1
  6.  
  7.   Download the plugin (dll) named `memscan32`, add it to your "Plugins" folder in Simba
  8.  
  9.   Start RS, target RS, start the script
  10. *)
  11. {$loadlib memscan32.dll}
  12.  
  13. // all you have to do is to run around and have runescape load new world regions
  14. // while tihs tool puzzles together each new region to build a single map.
  15. //
  16. // Sometimes a build can take a minute, but usually within seconds.
  17. // Just dont try to go to fast, step back if it gets stuck, maybe log in and out
  18. // while it's running in such a case (this will generate a new region).
  19.  
  20. const
  21.   PATH = 'C:\Simba\Includes\Test.png';  //change it to where u wanna save
  22.   LOAD_MAP = TRUE;
  23.   REBUILD_TIMER = 15000;   {rebuild world map every}
  24.   BACKUP_TIMER  = 5*60000; {save a .bak world map every}
  25.  
  26.  
  27.  
  28. type
  29.   PInt32 = ^Int32;
  30.  
  31. var
  32.   mem: TMemScan;
  33.  
  34. const
  35.   _512: array of Int64 = [0,0,0,0,0,0,0,0];
  36.  
  37. function BytesToTIA(data:TByteArray): TIntegerArray;
  38. begin
  39.   SetLength(result, length(data) div 4);
  40.   MemMove(data[0], result[0], Length(data));
  41. end;
  42.  
  43. function ValidMapAddr(address:PtrUInt): Boolean;
  44. var
  45.   data:Int32;
  46.   tmp: TByteArray;
  47. begin
  48.   data := PInt32(mem.CopyMem(address+8,4))^;
  49.   if (data = 512 * 512) then
  50.   begin
  51.     tmp := mem.CopyMem(address+12, 64);
  52.     Result := CompareMem(_512[0], tmp[0], 64); //row of black
  53.   end;
  54. end;
  55.  
  56. function GetMemBufferImage(scan:TMemScan; loc:PtrUInt; W,H:Int32): TMufasaBitmap;
  57. var
  58.   data:TByteArray;
  59.   ptr: PRGB32;
  60. begin
  61.   data := scan.CopyMem(loc, W*H*SizeOf(TRGB32));
  62.   Result.Init();
  63.   Result.SetSize(W,H);
  64.   ptr := Result.getData();
  65.   MemMove(data[0], ptr^, Length(data));
  66. end;
  67.  
  68. function GetMap(): TMufasaBitmap;
  69. var
  70.   res: TPtrIntArray;
  71.   ptr: PtrUInt;
  72.   raw: TByteArray;
  73.   i,c: Int32;
  74.   ints: TIntegerArray;
  75. begin
  76.   res := mem.FindInt32(512, 1);
  77.  
  78.   Result := nil;
  79.   for ptr in res do
  80.   begin
  81.     c   := 0;
  82.     raw := mem.CopyMem(ptr, 48);
  83.  
  84.     for i:=0 to 44 with 4 do
  85.       if PInt32(raw+i)^ = 512 then Inc(c);
  86.  
  87.     if c >= 4 then
  88.     begin
  89.       ints := BytesToTIA(raw);
  90.       for i in ints do
  91.         if (i > $FFF) and ValidMapAddr(i) then begin
  92.           Result := GetMemBufferImage(mem, i+12, 512, 512);
  93.           break;
  94.         end;
  95.     end;
  96.   end;
  97.   Result.SetList(client.GetMBitmaps);
  98.   client.GetMBitmaps.AddBMP(Result);
  99. end;
  100.  
  101.  
  102.  
  103. var
  104.   ResMap: TMufasaBitmap;
  105.   LastSaveT, LastBackT: Int64;
  106.  
  107. procedure TMufasaBitmap.DrawTo(X,Y: Int32; var Image: TMufasaBitmap);
  108. var
  109.   tmp: TMufasaBitmap;
  110.   x1,y1,W,H: Int32;
  111.   xx,yy,R1,G1,B1,R2,G2,B2: Int32;
  112. begin
  113.   tmp.Init(client.GetMBitmaps);
  114.  
  115.   W := Max(Image.GetWidth  + Abs(Min(0,X)), Self.GetWidth()  + X);
  116.   H := Max(Image.GetHeight + Abs(Min(0,Y)), Self.GetHeight() + Y);
  117.  
  118.   tmp.SetSize(W,H);
  119.   Image.DrawTransparent(Abs(Min(X,0)), Abs(Min(Y,0)), tmp);
  120.  
  121.   // Self.DrawTransparent(Max(0, X), Max(0, Y), tmp);
  122.   begin // smoother draw instead
  123.     x1 := Max(0, X); y1 := Max(0, Y);
  124.     for yy:=0 to Self.GetHeight-1 do
  125.       for xx:=0 to Self.GetWidth-1 do
  126.       begin
  127.         ColorToRGB(tmp.GetPixel(x1+xx, y1+yy), R1,G1,B1);
  128.         if (R1=0) and (G1=0) and (B1=0) then
  129.           tmp.SetPixel(x1+xx, y1+yy, Self.GetPixel(xx,yy))
  130.         else
  131.         begin
  132.           ColorToRGB(Self.GetPixel(xx,yy), R2,G2,B2);
  133.           tmp.SetPixel(x1+xx, y1+yy, RGBtoColor((R1*3+R2) div 4, (G1*3+G2) div 4, (B1*3+B2) div 4));
  134.         end;
  135.       end;
  136.   end;
  137.   Image.Free();
  138.   Image := tmp;
  139. end;
  140.  
  141. function AddPiece(Piece: TMufasaBitmap): Boolean;
  142.  
  143.   function AssertValidMatch(World, Piece: TMufasaBitmap; pt: TPoint; Tol:Int32; Match:Double): Boolean;
  144.   var
  145.     x,y,W,H,WorldW,WorldH,color,count,SAD:Int32;
  146.     c1,c2:TRGB32;
  147.   begin
  148.     GetBitmapSize(Piece.GetIndex, W,H);
  149.     GetBitmapSize(World.GetIndex, WorldW, WorldH);
  150.  
  151.     WriteLn('>>> Validating location');
  152.     SAD := 0;
  153.     for y:=0 to H-1 do
  154.       for x:=0 to W-1 do
  155.       begin
  156.         if ((x+pt.x >= 0) and (y+pt.y >= 0)) and ((x+pt.x < WorldW) and (y+pt.y < WorldH)) then
  157.         begin
  158.           color := World.GetPixel(x+pt.x,y+pt.y);
  159.           if color = 0 then continue;
  160.           c1 := TRGB32(color);
  161.           c2 := TRGB32(Piece.GetPixel(x,y));
  162.           if (Abs(c1.R-c2.R) < Tol) and
  163.              (Abs(c1.G-c2.G) < Tol) and
  164.              (Abs(c1.B-c2.B) < Tol) then
  165.             Inc(SAD);
  166.           Inc(count);
  167.         end;
  168.       end;
  169.     Result := SAD / Max(1,count) >= Match;
  170.     if Result then
  171.       WriteLn('>>> Validated location (',pt.x, ', ',pt.y,')')
  172.     else
  173.       WriteLn('>>> Invalid location (',pt.x, ', ',pt.y,') -> ', SAD / Max(1,count))
  174.  
  175.     //WriteLn(SAD / Max(1,count), ' at ', pt,', sz = ', [WorldW, WorldH]);
  176.   end;
  177.  
  178.   function Find(Sub, Map: TMufasaBitmap; out PT: TPoint): Boolean;
  179.   var
  180.     x,y,W,H: Int32;
  181.     OldTarget, NewTarget: NativeInt;
  182.     TL,BL,TR,BR: TMufasaBitmap;
  183.   begin
  184.     OldTarget := GetImageTarget;
  185.     NewTarget := SetTargetBitmap(Map.GetIndex());
  186.  
  187.     W := Sub.GetWidth();
  188.     H := Sub.GetHeight();
  189.  
  190.     TL := Sub.Copy(0,     0,     130, 130); TL.SetList(client.GetMBitmaps); client.GetMBitmaps.AddBMP(TL);
  191.     TR := Sub.Copy(W-131, 0,     W-1, 130); TR.SetList(client.GetMBitmaps); client.GetMBitmaps.AddBMP(TR);
  192.     BL := Sub.Copy(0,     H-131, 130, H-1); BL.SetList(client.GetMBitmaps); client.GetMBitmaps.AddBMP(BL);
  193.     BR := Sub.Copy(W-131, H-131, W-1, H-1); BR.SetList(client.GetMBitmaps); client.GetMBitmaps.AddBMP(BR);
  194.  
  195.     if (not Result) then
  196.     begin
  197.       WriteLn('>>> Searching for fitting location [1]');
  198.       if (Result := FindBitmapToleranceIn(TL.GetIndex(), x,y, [0,0,Map.GetWidth()-1, Map.GetHeight()-1], 50)) then
  199.         PT := [x,y];
  200.       Result := AssertValidMatch(Map, Sub, PT, 55, 0.999);
  201.     end;
  202.  
  203.     if (not Result) then
  204.     begin
  205.       WriteLn('>>> Searching for fitting location [2]');
  206.       if (Result := FindBitmapToleranceIn(TR.GetIndex(), x,y, [0,0,Map.GetWidth()-1, Map.GetHeight()-1], 50)) then
  207.         PT := [x-(W-131), y];
  208.       Result := AssertValidMatch(Map, Sub, PT, 55, 0.999)
  209.     end;
  210.  
  211.     if (not Result) then
  212.     begin
  213.       WriteLn('>>> Searching for fitting location [3]');
  214.       if (Result := FindBitmapToleranceIn(BL.GetIndex(), x,y, [0,0,Map.GetWidth()-1, Map.GetHeight()-1], 50)) then
  215.         PT := [x, y-(H-131)];
  216.       Result := AssertValidMatch(Map, Sub, PT, 55, 0.999)
  217.     end;
  218.  
  219.     if (not Result) then
  220.     begin
  221.       WriteLn('>>> Searching for fitting location [4]');
  222.       if (Result := FindBitmapToleranceIn(BR.GetIndex(), x,y, [0,0,Map.GetWidth()-1, Map.GetHeight()-1], 50)) then
  223.         PT := [x-(W-131), y-(H-131)];
  224.       Result := AssertValidMatch(Map, Sub, PT, 55, 0.999)
  225.     end;
  226.  
  227.     TL.Free();
  228.     TR.Free();
  229.     BL.Free();
  230.     BR.Free();
  231.     FreeTarget(NewTarget);
  232.     SetImageTarget(OldTarget);
  233.   end;
  234.  
  235. var
  236.   pt: TPoint;
  237. begin
  238.   if ResMap = nil then
  239.   begin
  240.     ResMap.Init(client.GetMBitmaps);
  241.     Piece.DrawTo(0,0,ResMap);
  242.     Exit(True);
  243.   end;
  244.  
  245.   if Find(Piece, ResMap, PT) then
  246.   begin
  247.     Piece.DrawTo(pt.x,pt.y, ResMap);
  248.     Result := True;
  249.     if (GetTickCount()-LastSaveT > REBUILD_TIMER) then
  250.     begin
  251.       ResMap.SaveToFile(PATH);
  252.       LastSaveT := GetTickCount();
  253.     end;
  254.  
  255.     if (GetTickCount()-LastBackT > BACKUP_TIMER) then
  256.     begin
  257.       ResMap.SaveToFile(PATH+'.bak.png');
  258.       LastBackT := GetTickCount();
  259.     end;
  260.   end else
  261.   begin
  262.     WriteLn('Warning: Failed to add piece, please walk back');
  263.     Wait(5000);
  264.   end;
  265.  
  266.   ResMap.Debug();
  267. end;
  268.  
  269.  
  270. var
  271.   bmp, tmp, prev: TMufasaBitmap;
  272.   t: Double;
  273.  
  274. procedure OnTerminate();
  275. begin
  276.   ResMap.SaveToFile(PATH);
  277.   ResMap.Free();
  278.   prev.Free();
  279. end;
  280.  
  281. begin
  282.   mem.Init(GetTargetPID());
  283.   AddOnTerminate('OnTerminate');
  284.  
  285.   if (LOAD_MAP) and FileExists(PATH) then
  286.   begin
  287.     ResMap.Init(client.GetMBitmaps);
  288.     ResMap.LoadFromFile(PATH);
  289.   end;
  290.  
  291.   while True do
  292.   begin
  293.     bmp := GetMap();
  294.     WriteLn(bmp.GetIndex(),', ',[bmp.GetWidth(), bmp.GetHeight()]);
  295.     bmp.Crop(65,65, 511-65,511-65);
  296.  
  297.     if (prev = nil) or (bmp.MatchTemplate(prev, TM_CCORR_NORMED).Max() < 1) then
  298.     begin
  299.       WriteLn('Rebuilding map... Please wait, this might take some time');
  300.       t := PerformanceTimer();
  301.       if AddPiece(bmp) then
  302.       begin
  303.         if (prev <> nil) then prev.Free();
  304.         prev := bmp;
  305.         WriteLn('Map rebuilt in ', PerformanceTimer-t,'ms');
  306.       end else
  307.         BMP.Free();
  308.     end else
  309.       bmp.Free();
  310.   end;
  311. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement