@@ -10,6 +10,16 @@ craft certain items in OldSchool RuneScape.
1010{$INCLUDE_ONCE WaspLib/osrs.simba}
1111
1212type
13+ (*
14+ ## TRSMakeQuantityButton type
15+ Helper record used to cache make menu buttons.
16+ *)
17+ TRSMakeQuantityButton = record
18+ Quantity: ERSItemQuantity;
19+ Button: TRSButton;
20+ UpText: String;
21+ end;
22+
1323(*
1424## TRSMakeItem
1525Helper record used to cache make menu items.
@@ -25,12 +35,15 @@ Main record used to interact with the {ref}`Make` menu.
2535*)
2636 TRSMake = record
2737 Items: array of TRSMakeItem;
28- QuantityButtons : TBoxArray;
38+ QuantityButtonBoxes : TBoxArray;
2939 SelectedQuantity: Integer;
30- {%codetools on}
40+ QuantityArea: TBox;
41+ {%codetools off}
3142 _IsOpenHelper, _ItemsHelper: TBox;
3243 {%codetools on}
44+
3345 const TEXT_COLOR: TColor = $203040;
46+ const BORDER_COLOR: TColorTolerance = [$080707, 5, EColorSpace.RGB, [1.000, 1.000, 1.000]];
3447 end;
3548
3649(*
@@ -51,13 +64,14 @@ begin
5164 Self._IsOpenHelper.X2 := X2 - 10;
5265 Self._IsOpenHelper.Y2 := Y1 + 34;
5366
54- Self.QuantityButtons := TBoxArray.Create([X2-228, Y1+15], 6, 1, 29, 29, [6,0]).Reversed();
55- Self.QuantityButtons[0].X2 += 5;
67+ Self.QuantityButtonBoxes := TBoxArray.Create([X2-228, Y1+15], 6, 1, 29, 29, [6,0]).Reversed();
68+ Self.QuantityButtonBoxes[0].X2 += 5;
69+ Self.QuantityArea := Self.QuantityButtonBoxes.Merge();
5670
5771 Self._ItemsHelper.X1 := X1 + 8;
5872 Self._ItemsHelper.Y1 := Y1 + 51;
5973 Self._ItemsHelper.X2 := X2 - 8;
60- Self._ItemsHelper.Y2 := Y2 - 19 ;
74+ Self._ItemsHelper.Y2 := Y2 - 14 ;
6175 end;
6276end;
6377
96110 Result := SleepUntil(Self.IsOpen(), interval, time);
97111end;
98112
99-
100113(*
101114## Make.GetItemBoxes
102115```pascal
117130 tpa: TPointArray;
118131 b: TBox;
119132begin
120- tpa := Target.FindColor($080707, 5 , Self._ItemsHelper);
133+ tpa := Target.FindColor(Self.BORDER_COLOR , Self._ItemsHelper);
121134 for tpa in tpa.Cluster(1.5) do
122135 begin
123136 b := tpa.Bounds();
@@ -126,6 +139,172 @@ begin
126139 end;
127140end;
128141
142+ (*
143+ ## Make.GetQuantityBoxes
144+ ```pascal
145+ function TRSMake.GetQuantityBoxes(): TBoxArray;
146+ ```
147+ Finds quantity button boundaries and returns them as a TBoxArray.
148+
149+ You have 2 ways of getting the quantity boxes, a static one:
150+ ```pascal
151+ ShowOnTarget(Make.QuantityButtons);
152+ ```
153+ ```{figure} ../../images/make_static_quantity_boxes.png
154+ The make static boxes.
155+ ```
156+
157+ And a dynamic one:
158+ ```pascal
159+ ShowOnTarget(Make.GetQuantityBoxes());
160+ ```
161+ ```{figure} ../../images/make_quantity_boxes.png
162+ The make "dynamic" boxes.
163+ ```
164+
165+ There are use cases for both, internally, `Make.GetQuantityBoxes` is usually used.
166+ *)
167+ function TRSMake.GetQuantityBoxes(): TBoxArray;
168+ var
169+ tpa: TPointArray;
170+ b: TBox;
171+ begin
172+ tpa := Target.FindColor(Self.BORDER_COLOR, Self.QuantityArea);
173+ for tpa in tpa.Cluster(1.5) do
174+ begin
175+ b := tpa.Bounds();
176+ if InRange(b.Height, 20, 40) and InRange(b.Width, 20, 40) then
177+ Result += b;
178+ end;
179+ Result := Result.SortByX(True);
180+ end;
181+
182+ (*
183+ ## Make.GetQuantityButtons()
184+ ```pascal
185+ function TRSMake.GetQuantityButtons(): array of TRSMakeQuantityButton;
186+ ```
187+ Returns the visible quantity buttons as a array of TRSMakeQuantityButton.
188+
189+ Example:
190+ ```pascal
191+ WriteLn Make.GetQuantityButtons();
192+ ```
193+ *)
194+ function TRSMake.GetQuantityButtons(): array of TRSMakeQuantityButton;
195+ var
196+ boxes: TBoxArray;
197+ i: Integer;
198+ quantityStr: String;
199+ begin
200+ boxes := Self.GetQuantityBoxes();
201+ SetLength(Result, Length(boxes));
202+
203+ for i := 0 to High(boxes) do
204+ begin
205+ quantityStr := OCR.Recognize(boxes[i], RSFonts.PLAIN_11, [Self.TEXT_COLOR, RSFonts.WHITE], 0);
206+
207+ Result[i].Quantity := ERSItemQuantity.String2Quantity(quantityStr);
208+ Result[i].Button.Bounds := boxes[i];
209+ Result[i].Button.EnabledColors := [[RSFonts.WHITE, 0]];
210+
211+ if quantityStr.Equals('X', True) then
212+ Result[i].UpText := 'Other'
213+ else
214+ Result[i].UpText := quantityStr;
215+ end;
216+ end;
217+
218+
219+ (*
220+ ## Make.FindQuantityButtons
221+ ```pascal
222+ function TRSMake.FindQuantityButtons(): array of TRSMakeQuantityButton;
223+ ```
224+ Attempts to find and return all quantity buttons in the Make interface.
225+ This is a safe wrapper around `GetQuantityButtons()` that first verifies
226+ the Make interface is open before attempting to locate the buttons.
227+
228+ Returns an empty array if the Make interface is not currently open.
229+
230+ Example:
231+ ```pascal
232+ var
233+ buttons: array of TRSMakeQuantityButton;
234+ i: Integer;
235+ begin
236+ buttons := Make.FindQuantityButtons();
237+ for i := 0 to High(buttons) do
238+ WriteLn('Button ', i, ' bounds: ', buttons[i].Button.Bounds);
239+ end;
240+ ```
241+ *)
242+ function TRSMake.FindQuantityButtons(): array of TRSMakeQuantityButton;
243+ begin
244+ if not Self.IsOpen() then
245+ Exit;
246+ Result := Self.GetQuantityButtons();
247+ end;
248+
249+ (*
250+ ### Make.GetCurrentQuantityButton
251+ ```pascal
252+ function TRSMake.GetCurrentQuantityButton(): Integer;
253+ ```
254+ Get the current active make quantity button.
255+
256+ Example:
257+ ```pascal
258+ current := Make.GetCurrentQuantityButton();
259+ WritLn current;
260+ ShowOnTarget(current.Button.Bounds);
261+ ```
262+ *)
263+ function TRSMake.GetCurrentQuantityButton(): TRSMakeQuantityButton;
264+ var
265+ btns: array of TRSMakeQuantityButton;
266+ i: Integer;
267+ begin
268+ btns := Self.FindQuantityButtons();
269+ if Length(btns) = 0 then
270+ Exit;
271+
272+ for i := 0 to High(btns) do
273+ if btns[i].Button.Enabled() then
274+ Exit(btns[i]);
275+ end;
276+
277+ (*
278+ ### Make.GetCurrentQuantity
279+ ```pascal
280+ function TRSMake.GetCurrentQuantity(): Integer;
281+ ```
282+ Get the current active make quantity as an integer.
283+ If All button is current then returns -1.
284+
285+ Example:
286+ ```pascal
287+ current := Make.GetCurrentQuantityButton();
288+ WritLn current;
289+ ShowOnTarget(current.Button.Bounds);
290+ ```
291+ *)
292+ function TRSMake.GetCurrentQuantity(): Integer;
293+ var
294+ current: TRSMakeQuantityButton;
295+ begin
296+ current := Self.GetCurrentQuantityButton();
297+ if current = [] then
298+ Exit;
299+
300+ if current.Button.Bounds.Area = 0 then
301+ raise GetDebugLn('Make', 'Failed to get current quantity button');
302+
303+ if current.UpText.Equals('All', True) then
304+ Exit(-1);
305+
306+ Result := StrToInt(current.UpText);
307+ end;
129308
130309(*
131310## Make.HasHint
@@ -248,49 +427,66 @@ are visible which you can do easily through the next methods.
248427*)
249428
250429(*
251- ### Make.IndexOfQuantity
430+ ### Make.FindQuantityButton
252431```pascal
253- function TRSMake.IndexOfQuantity (amount: Integer): Integer ;
432+ function TRSMake.FindQuantityButton (amount: Integer): TRSMakeQuantityButton ;
254433```
255- Finds the index of a quantity button by the specified `amount`.
256- If the `amount` we are looking for, the custom quantity button is returned,
257- otherwise the result is `-1`.
434+ Finds and returns the TRSMakeQuantityButton matching the specified `amount`.
435+
436+ For standard quantities (1, 5, 10, All), returns the corresponding button directly.
437+ For custom amounts, prioritizes a button already set to that value, otherwise
438+ returns the "Other" (X) button which will prompt for manual entry.
439+
440+ Returns an empty record if no matching button is found or the Make interface is not open.
441+
442+ Note: Automatically closes any tooltip that may be covering the quantity buttons.
258443
259444Example:
260445```pascal
261- WriteLn Make.IndexOfQuantity(Make.QUANTITY_ALL);
446+ var
447+ btn: TRSMakeQuantityButton;
448+ begin
449+ btn := Make.FindQuantityButton(5);
450+ if btn <> [] then
451+ WriteLn('Found button: ', btn);
452+ end;
262453```
263454*)
264- function TRSMake.IndexOfQuantity (amount: Integer): Integer ;
455+ function TRSMake.FindQuantityButton (amount: Integer): TRSMakeQuantityButton ;
265456var
266457 hintPt: TPoint;
267- i : Integer;
458+ idx : Integer;
268459 quantity: ERSItemQuantity;
460+ quantitybtns: array of TRSMakeQuantityButton;
269461begin
270- if amount <= 0 then Exit(0);
271-
272462 if Self.HasHint() then
273463 begin
274464 hintPt := Self.GetHintBox().TopRight;
275- if (hintPt.Y <= Self.QuantityButtons [5].Y2) and (hintPt.X >= Self.QuantityButtons [5].X1) then
465+ if (hintPt.Y <= Self.QuantityButtonBoxes [5].Y2) and (hintPt.X >= Self.QuantityButtonBoxes [5].X1) then
276466
277467 if not Self.CloseHint() then
278468 raise GetDebugLn('Make', 'Failed to close the tooltip which is covering the quanitty buttons');
279469 end;
280470
471+ quantitybtns := Self.FindQuantityButtons();
281472 quantity := ERSItemQuantity.Integer2Quantity(amount);
282473
283- if quantity = ERSItemQuantity.CUSTOM then
474+ for idx := 0 to High(quantitybtns) do
284475 begin
285- if amount = OCR.RecognizeNumber(Self.QuantityButtons[2], RSFonts.PLAIN_11, [Self.TEXT_COLOR, RSFonts.WHITE], 0) then
286- Exit(2);
287- Exit(1);
476+ if quantitybtns[idx].Quantity = quantity then
477+ begin
478+ if quantity = ERSItemQuantity.CUSTOM then
479+ begin
480+ if quantitybtns[idx].UpText = IntToStr(amount) then
481+ Exit(quantitybtns[idx]);
482+ if quantitybtns[idx].UpText = 'Other' then
483+ Exit(quantitybtns[idx]);
484+ end
485+ else
486+ Exit(quantitybtns[idx]);
487+ end;
288488 end;
289-
290- for i := 1 to High(Self.QuantityButtons) do
291- if amount = OCR.RecognizeNumber(Self.QuantityButtons[i], RSFonts.PLAIN_11, [Self.TEXT_COLOR, RSFonts.WHITE], 0) then
292- Exit(i);
293- Result := -1;
489+ Result := [];
294490end;
295491
296492(*
@@ -307,10 +503,9 @@ WriteLn Make.IsQuantitySelected(Make.QUANTITY_ALL);
307503*)
308504function TRSMake.IsQuantitySelected(idx: Integer): Boolean;
309505begin
310- Result := Target.HasColor(RSFonts.WHITE, 0, 1, Self.QuantityButtons [idx]);
506+ Result := Target.HasColor(RSFonts.WHITE, 0, 1, Self.QuantityButtonBoxes [idx]);
311507end;
312508
313-
314509(*
315510### Make.SetQuantity
316511```pascal
@@ -325,18 +520,19 @@ WriteLn Make.SetQuantity(Make.QUANTITY_ALL);
325520*)
326521function TRSMake.SetQuantity(amount: Integer): Boolean;
327522var
328- idx: Integer ;
523+ quantityButton: TRSMakeQuantityButton ;
329524 done: Boolean;
330525begin
331- idx := Self.IndexOfQuantity (amount);
332- if idx < 0 then
526+ quantityButton := Self.FindQuantityButton (amount);
527+ if quantityButton = [] then
333528 raise GetDebugLn('Make', 'Quantity button for "' + ToStr(amount) + '" is not available.');
334529
335- if Self.IsQuantitySelected(idx) then Exit(True);
530+ if quantityButton.Button.Enabled() then Exit(True);
531+
532+ quantityButton.Button.Click(EMouseButton.LEFT);
336533
337- Mouse.Click(Self.QuantityButtons[idx], EMouseButton.LEFT);
338534 Result := SleepUntil(
339- (done := Self.IsQuantitySelected(idx )) or
535+ (done := quantityButton.Button.Enabled( )) or
340536 Chat.FindQuery('Enter amount', True), RandomMode(100, 50, 1500), 600
341537 );
342538 if done then Exit;
@@ -369,7 +565,7 @@ begin
369565 boxes[index].Y1 := boxes[index].Y2 + 1;
370566 boxes[index].Y2 += 15;
371567
372- if OCR.Locate(boxes[index], 'Space', [Self.TEXT_COLOR], 0, RSFonts.PLAIN_11) < 0.95 then
568+ if OCR.Locate(boxes[index], 'Space', [Self.TEXT_COLOR], 0, RSFonts.PLAIN_11) >= 0.95 then
373569 Keyboard.KeyPress(EKeyCode.SPACE)
374570 else
375571 Keyboard.KeyPress(EKeyCode(Ord(EKeyCode.NUM_1) + index));
@@ -438,15 +634,16 @@ begin
438634 end;
439635end;
440636
441-
442637procedure TRSMake.Draw(img: TImage);
443638begin
444639 if not Self.IsOpen() then Exit;
445640
446641 img.DrawColor := $00FFFF;
447642 img.DrawBox(Chat.Bounds);
448643 img.DrawColor := $FFFFFF;
449- img.DrawBoxArray(Self.QuantityButtons, False);
644+ img.DrawBoxArray(Self.QuantityButtonBoxes, False);
645+ img.DrawColor := $0000FF;
646+ img.DrawBoxArray(Self.GetQuantityBoxes(), False);
450647 img.DrawColor := $00FF00;
451648 img.DrawBoxArray(Self.GetItemBoxes(), False);
452649 img.DrawColor := $FF0000;
0 commit comments