Advertisement
WarPie90

MTA - Alchemist room example

Jul 3rd, 2023 (edited)
1,666
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 7.65 KB | None | 0 0
  1. program new;
  2. {$DEFINE SRL_USE_REMOTEINPUT}
  3. {$I SRL/osr.simba}
  4.  
  5. const
  6.   USE_SPELL = ERSSpell.HIGH_LEVEL_ALCHEMY;
  7.  
  8. type
  9.   TAlchemyValue = record
  10.     Name: string;
  11.     Points: Int32;
  12.     PatternId: Int32;
  13.   end;
  14.  
  15.   TAlchemyValues = array of TAlchemyValue;
  16.  
  17. var
  18.   RSW: TRSWalker;
  19.  
  20. const
  21.   cupboards: TPointArray = [
  22.     [190,154], [190,138], [190,122], [190,106],
  23.     [226,106], [226,122], [226,138], [226,154]
  24.   ];
  25.  
  26.   pattern: TStringArray := [
  27.     'Leather boots', 'Adamant kiteshield', 'Adamant med helm', 'Emerald',
  28.     'Rune longsword','','',''
  29.   ];
  30.  
  31.  
  32. function TRSInventory.GetUnusedSlots(): TIntegerArray;
  33. var slot: Int32;
  34. begin
  35.   Inventory.Open();
  36.   for slot:=0 to High(Inventory.GetSlotBoxes()) do
  37.     if not Inventory.IsSlotUsed(slot) then
  38.       Result += slot;
  39. end;
  40.  
  41. function MatchingName(A,B: String): Boolean;
  42. begin
  43.   Result := LowerCase(A).Pos(LowerCase(B)) > 0;
  44. end;
  45.  
  46.  
  47. procedure onterm();
  48. begin
  49.   RSClient.Image.Clear();
  50. end;
  51.  
  52.  
  53. (*
  54.   Returns the ID of the cupboard in relation to to cupboards list.
  55. *)
  56. function NearestCupboardID(): Int32;
  57. var
  58.   i: Int32;
  59.   p: TPoint;
  60. begin
  61.   p := RSW.GetMyPos();
  62.   for i:=0 to High(Cupboards) do
  63.     if Cupboards[i].DistanceTo(p) < 11 then
  64.       Exit(i);
  65.  
  66.   Result := -1;
  67. end;
  68.  
  69.  
  70. (*
  71.   Uses the pattern list to return what item you just got, if you got one.
  72.   Returns the index from the pattern list.
  73. *)
  74. function GetExtractedItemId(unused: TIntegerArray): Int32;
  75. var
  76.   i: Int32;
  77. begin
  78.   Inventory.Open();
  79.   Result := -1;
  80.   for i:=0 to High(pattern)-3 do
  81.     if ItemFinder.Find(pattern[i], [Inventory.GetSlotBox(unused[0])]) <> [] then
  82.       Exit(i);
  83. end;
  84.  
  85. (*
  86.   Moves around the playground to find the pattern order.
  87. *)
  88. function GetCurrentOrderOffset(): Int32;
  89. var
  90.   unused: TIntegerArray;
  91.   pos: Int32;
  92.   TPA: TPointArray;
  93.   ATPA: T2DPointArray;
  94.   c: TCircle;
  95. begin
  96.   repeat
  97.     pos    := NearestCupboardID();
  98.     unused := Inventory.GetUnusedSlots();
  99.  
  100.     srl.FindColors( TPA, CTS2(9082515, 21, 0.30, 0.13), Minimap.PointToMsRect(RSW.WorldToMM(Cupboards[pos])).Bounds());
  101.     ATPA := TPA.Cluster(3);
  102.  
  103.     c := ATPA.Biggest().MinAreaCircle();
  104.     c.Radius := Round(c.Radius * 0.7);
  105.     RSClient.Image.DrawCircle(c.Mean(), c.Radius, 255);
  106.     Mouse.Click(c, MOUSE_LEFT);
  107.     WaitUntil(Length(Inventory.GetUnusedSlots()) <> Length(unused), 50, 3000);
  108.  
  109.     Result := GetExtractedItemId(unused);
  110.     if Result = -1 then
  111.       RSW.WalkPath([Cupboards[(pos+3) mod 8]]);
  112.   until Result <> -1;
  113.  
  114.   Result := srl.Modulo(pos-result, 8);
  115. end;
  116.  
  117. (*
  118.   Using the current order we can generate a translation list
  119.   used to find out what cupboards contains what item.
  120. *)
  121. function GetTranslationTable(): TIntegerArray;
  122. var
  123.   off,x,i: Int32;
  124.   pt: TPoint;
  125. begin
  126.   off := GetCurrentOrderOffset();
  127.   Result := [];
  128.   for i:=0 to High(pattern) do
  129.   begin
  130.     x := srl.Modulo(i-off, Length(pattern));
  131.     pt := Minimap.PointToMs(RSW.WorldToMM(Cupboards[i]));
  132.     RSClient.Image.DrawText(ToStr(i)+': '+ pattern[x], pt, 255);
  133.     Result += x;
  134.   end;
  135. end;
  136.  
  137. (*
  138.   a little bit of drawing is always nice.
  139. *)
  140. procedure DrawTranslationTable(table: TIntegerArray);
  141. var
  142.   x,i: Int32;
  143.   pt: TPoint;
  144. begin
  145.   for i:=0 to High(pattern) do
  146.   begin
  147.     x := table[i];
  148.     pt := Minimap.PointToMs(RSW.WorldToMM(Cupboards[i]));
  149.     RSClient.Image.DrawText(ToStr(i)+': '+ pattern[x], pt, 255);
  150.   end;
  151. end;
  152.  
  153.  
  154. (*
  155.   OCR to generate a list of values.
  156. *)
  157. function GetAlchValues(): TAlchemyValues;
  158. var
  159.   b: TBox;
  160.   TSA: TStringArray;
  161.   TPA: TPointArray;
  162.   ATPA: T2DPointArray;
  163.   i,j,z: Int32;
  164.  
  165.   function Compare(constref a,b: TAlchemyValue): Int32; static;
  166.   begin
  167.     Result := Sign(B.Points-A.Points);
  168.   end;
  169.  
  170. begin
  171.   try
  172.     b := Minimap.Bounds;
  173.     b := [b.x1-250, b.y1+80, b.x2-250, b.y2+50];
  174.  
  175.     SRL.FindColors(TPA, CTS2(45620, 6, 0.14, 0.01), b);
  176.     ATPA := TPA.Cluster(20, 2);
  177.     ATPA.SortByX(True);
  178.     ATPA.SortByY(True);
  179.  
  180.     RSClient.Image.DrawBox(b, 255);
  181.     for i:=0 to High(ATPA) do
  182.     begin
  183.       TSA += ocr.Recognize(ATPA[i].Bounds().Expand(2), TOCRColorFilter.Create([45620], [30]), RS_FONT_PLAIN_11);
  184.       z := TSA[High(TSA)].Pos('I');
  185.       if z > 1 then
  186.       begin
  187.         if LowerCase(TSA[High(TSA)][z-1]) = TSA[High(TSA)][z-1] then
  188.           TSA[High(TSA)][z] := 'l';
  189.       end;
  190.  
  191.       TSA[High(TSA)] := TSA[High(TSA)].Replace('Helm', 'med helm', [rfReplaceAll]);
  192.     end;
  193.  
  194.     for i:=0 to High(TSA) with 2 do
  195.       for j:=0 to High(pattern) do
  196.         if LowerCase(TSA[i]).Pos(LowerCase(pattern[j])) > 0 then
  197.         begin
  198.           Result += [pattern[j], StrToIntDef(TSA[i+1], 0), j];
  199.           break;
  200.         end;
  201.  
  202.     Sort(Result, @Compare);
  203.   except
  204.     SetLength(Result, 8); //hack!
  205.   end;
  206. end;
  207.  
  208. (*
  209. function GetBestAlch(scores: TAlchemyValues): Int32;
  210. var i: Int32;
  211. begin
  212.   for i:=0 to High(pattern) do
  213.     if LowerCase(scores[0].Name).Pos(LowerCase(pattern[i])) > 0 then
  214.       Exit(i);
  215. end;
  216. *)
  217.  
  218. function Equal(A,B: TAlchemyValues): Boolean;
  219. var i: Int32;
  220. begin
  221.   Result := True;
  222.   for i:=0 to High(A) do
  223.     if (A[i].Name <> B[i].Name) or (A[i].Points <> B[i].Points) then
  224.       Exit(False);
  225. end;
  226.  
  227.  
  228. function Extract(): Int32;
  229. var
  230.   i,item,slot,count: Int32;
  231.   p,best: TPoint;
  232.   TPA: TPointArray;
  233.   ATPA: T2DPointArray;
  234.   translate: TIntegerArray;
  235.   scores,newscores: TAlchemyValues;
  236.   c: TCircle;
  237.   items: TRSItemArray;
  238.   t: TCountDown;
  239. label
  240.   JUST_ALCH;
  241. begin
  242.   scores    := GetAlchValues();
  243.   if Length(scores) = 0 then
  244.     Exit;
  245.  
  246.   if Inventory.CountItem(scores[0].Name) > 5 then
  247.     JUST_ALCH;
  248.  
  249.   translate := GetTranslationTable();
  250.   item      := scores[0].PatternId;
  251.   best      := cupboards[translate.Find(item)];
  252.  
  253.   RSW.WalkPath([best]);
  254.   RSClient.Image.Clear();
  255.   DrawTranslationTable(translate);
  256.  
  257.   // extract fast:
  258.   WriteLn('Stage: Extract');
  259.   t.Init(Random(2000,3500));
  260.   while (scores[0].Name = GetAlchValues()[0].Name) and
  261.         (not t.IsFinished()) do
  262.   begin
  263.     srl.FindColors( TPA, CTS2(9082515, 21, 0.30, 0.13), Minimap.PointToMsRect(RSW.WorldToMM(best)).Bounds());
  264.     ATPA := TPA.Cluster(3);
  265.     c := ATPA.Biggest().MinAreaCircle();
  266.     c.Radius := Round(c.Radius * 0.7);
  267.     Mouse.Click(c, MOUSE_LEFT); //sometimes clicks are not registered --- fix plz!
  268.     Sleep(Random(250,500));
  269.   end;
  270.  
  271. JUST_ALCH:
  272.   // cast spell
  273.   WriteLn('Stage: cast spells!');
  274.  
  275.   repeat
  276.     Magic.CastSpell(USE_SPELL);
  277.     p := Mouse.Position();
  278.     WaitUntil(Inventory.IsOpen(), 20, 5000);
  279.     Inventory.ClickItem(pattern[item]);
  280.     item := (newscores := GetAlchValues())[0].PatternID;
  281.     count := Inventory.CountItem(pattern[item]);
  282.     Wait(150,1000, wdLeft);
  283.     if Random() > 0.05 then Mouse.Move(p, 20);
  284.     WaitUntil(Magic.IsOpen(), 20, 5000);
  285.     Wait(100,170, wdLeft); //reaction time limiter <---
  286.  
  287.     if count = 0 then break;
  288.   until count = 0;
  289.  
  290.   if Length(Inventory.GetUnusedSlots()) < 7 then
  291.   begin
  292.     WriteLn('Stage: dropping crap');
  293.     for i:=0 to High(pattern)-3 do
  294.       if not MatchingName(newscores[0].Name, pattern[i]) then
  295.         items += pattern[i];
  296.  
  297.     Inventory.ShiftDrop(items, DROP_PATTERN_REGULAR);
  298.   end;
  299.  
  300.   if Inventory.CountItem(newscores[0].Name) >= 2 then
  301.     JUST_ALCH;
  302. end;
  303.  
  304.  
  305.  
  306. begin
  307.   RSW_ADAPTIVE_SCREEN_TOGGLE_DISTANCES := [0,60];
  308.   RSW.Setup('mta0');
  309.   RSW.AdaptiveWalk := False;
  310.   AddOnTerminate(@onterm);
  311.   RSClient.Image.Clear();
  312.   RSClient.Image.setFontSize(14);
  313.   RSClient.Image.setFontAntialiasing(False);
  314.   Mouse.Speed := Random(14,17);
  315.  
  316.   while True do
  317.   begin
  318.     RSClient.Image.Clear();
  319.     Extract();
  320.  
  321.     // here we can check if we have reached 10K coins so we can leave the room
  322.     // and break this loop
  323.   end;
  324.  
  325. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement