PageRenderTime 36ms CodeModel.GetById 24ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/mapwalk/MapWalk.simba

http://github.com/Drags111/Reflection_Dev
Unknown | 858 lines | 661 code | 197 blank | 0 comment | 0 complexity | 6f2fa300b63121fbca42508f76d1bc77 MD5 | raw file
  1(*
  2MapWalk
  3=======
  4
  5Contains routines for walking the runescape minimap.
  6
  7*)
  8
  9(*
 10R_GetMinimapAngleDeg
 11~~~~~~~~~~~~~~~~~~~~
 12
 13.. code-block:: pascal
 14
 15    function R_GetMinimapAngleDeg: extended;
 16
 17Returns the current Map angle in degrees. North: 0 deg, increases in the
 18counter clockwise direction
 19
 20.. note::
 21
 22  by BenLand100
 23
 24*)
 25function R_GetMinimapAngleDeg: extended;
 26begin
 27  Result := SmartGetFieldFloat(0, hook_static_MapAngle) * 45.0 / 2048.0;
 28end;
 29
 30(*
 31R_GetMinimapAngleRad
 32~~~~~~~~~~~~~~~~~~~~
 33
 34.. code-block:: pascal
 35
 36    function R_GetMinimapAngleRad: extended;
 37
 38Returns the current Map angle in radians. North: 0 deg, increases in the
 39counter clockwise direction
 40
 41.. note::
 42
 43  by BenLand100
 44
 45*)
 46function R_GetMinimapAngleRad: extended;
 47begin
 48  Result := SmartGetFieldFloat(0, hook_static_MapAngle) * pi / 8192.0;
 49end;
 50
 51(*
 52R_GetCamPosX
 53~~~~~~~~~~~~
 54
 55.. code-block:: pascal
 56
 57    function R_GetCamPosX: integer;
 58
 59Camera Position X
 60
 61.. note::
 62
 63  by lordsaturn
 64
 65*)
 66function R_GetCamPosX: integer;
 67begin
 68  Result := SmartGetFieldInt(0, hook_static_CamPosX);
 69end;
 70
 71(*
 72R_GetCamPosY
 73~~~~~~~~~~~~
 74
 75.. code-block:: pascal
 76
 77    function R_GetCamPosY: integer;
 78
 79Camera Position Y
 80
 81.. note::
 82
 83  by lordsaturn
 84
 85*)
 86function R_GetCamPosY: integer;
 87begin
 88  Result := SmartGetFieldInt(0, hook_static_CamPosY);
 89end;
 90
 91(*
 92R_GetCameraAngle
 93~~~~~~~~~~~~~~~~
 94
 95.. code-block:: pascal
 96
 97    function R_GetCameraAngle: Integer;
 98
 99Returns the Camera Angle. 0 = lowest, 100 = highest.
100
101.. note::
102
103  by Drags111
104
105*)
106function R_GetCameraAngle: Integer;
107var
108  D: Extended;
109begin
110  D := (SmartGetFieldInt(0, hook_static_CameraPitch) / 1024.0);
111  Result := Round((D - 1) * 50);
112end;
113
114(*
115R_SetCameraAngle
116~~~~~~~~~~~~~~~~
117
118.. code-block:: pascal
119
120    function R_SetCameraAngle(Angle: Integer): Boolean;
121
122Sets the Camera Angle. 0 = lowest, 100 = highest.
123
124.. note::
125
126  by Drags111
127
128*)
129function R_SetCameraAngle(Angle: Integer): Boolean;
130var
131  C, T: Integer;
132begin
133  Result := False;
134  if(Angle = R_GetCameraAngle)then
135  begin
136    Result := True;
137    Exit;
138  end;
139  if(Angle < R_GetCameraAngle)then
140    C := VK_DOWN
141  else
142    C := VK_UP;
143
144  KeyDown(C);
145  MarkTime(T);
146  while(TimeFromMark(T) < 5000)do
147  begin
148    if(C = VK_DOWN) and (Angle >= R_GetCameraAngle)then
149      Break;
150    if(C = VK_UP) and (Angle <= R_GetCameraAngle)then
151      Break;
152    wait(10+Random(10));
153  end;
154  KeyUp(C);
155end;
156
157(*
158R_TileToMM
159~~~~~~~~~~
160
161.. code-block:: pascal
162
163    function R_TileToMM(tile: TTile): TPoint;
164
165Converts the global tile position to a screen location on the minimap, taking
166map rotation into account.
167
168.. note::
169
170  by BenLand100
171
172*)
173function R_TileToMM(tile: TTile): TPoint;
174var
175  angle, x, y: extended;
176  temp: TPoint;
177begin
178   angle:= -R_GetMinimapAngleRad;
179   temp := R_GetMyPos();
180   x:= (tile.x - temp.x) * 4 - 2;
181   y:= (temp.y - tile.y) * 4 - 2;
182   result.x:= round(x*cos(angle) + y*sin(angle)) + 628;
183   result.y:= round(y*cos(angle) - x*sin(angle)) + 87;
184end;
185
186(*
187R_TileOnMM
188~~~~~~~~~~
189
190.. code-block:: pascal
191
192    function R_TileOnMM(Tile: TTile): boolean;
193
194Checks if the Tile is on the MM.
195
196.. note::
197
198  by Drags111
199
200*)
201function R_TileOnMM(Tile: TTile): boolean;
202var
203  P: TPoint;
204begin
205  P := R_TileToMM(Tile);
206  Result := rs_OnMinimap(P.x, P.y);
207end;
208
209(*
210R_GetDest
211~~~~~~~~~
212
213.. code-block:: pascal
214
215    function R_GetDest: TTile;
216
217Returns the tile of the Flag destination.
218
219.. note::
220
221  by Drags111
222
223*)
224function R_GetDest: TTile;
225begin
226  Result.X := SmartGetFieldInt(0, hook_static_BaseX) + SmartGetFieldInt(0, hook_static_DestX);
227  Result.Y := SmartGetFieldInt(0, hook_static_BaseY) + SmartGetFieldInt(0, hook_static_DestY);
228end;
229
230(*
231R_GetLocDest
232~~~~~~~~~~~~
233
234.. code-block:: pascal
235
236    function R_GetLocDest: TTile;
237
238Returns the local tile of the Flag destination.
239
240.. note::
241
242  by Drags111
243
244*)
245function R_GetLocDest: TTile;
246begin
247  Result.X := SmartGetFieldInt(0, hook_static_DestX);
248  Result.Y := SmartGetFieldInt(0, hook_static_DestY);
249end;
250
251(*
252R_FlagExists
253~~~~~~~~~~~~
254
255.. code-block:: pascal
256
257    function R_FlagExists: Boolean;
258
259Returns true if there is a flag.
260
261.. note::
262
263  by Drags111
264
265*)
266function R_FlagExists: Boolean;
267var
268  xFlag: LongInt;
269begin
270  xFlag := SmartGetFieldInt(0, hook_static_DestX);
271  Result := (xFlag) > -1;
272end;
273
274(*
275R_DistanceTile
276~~~~~~~~~~~~~~
277
278.. code-block:: pascal
279
280    function R_DistanceTile(T, TT: TTile): Integer;
281
282Returns the distance between two tiles.
283
284.. note::
285
286  by mormonman
287
288*)
289function R_DistanceTile(T, TT: TTile): Integer;
290begin
291  Result := Distance(T.x, T.y, TT.X, TT.Y);
292end;
293
294(*
295R_DistanceFromTile
296~~~~~~~~~~~~~~~~~~
297
298.. code-block:: pascal
299
300    function R_DistanceFromTile(TheTile: TTile): Integer;
301
302Returns the distance between your player and the tile.
303
304.. note::
305
306  by Widget
307
308*)
309function R_DistanceFromTile(TheTile: TTile): Integer;
310var
311  MyPos: TTile;
312begin
313  MyPos := R_GetMyPos;
314  Result := R_DistanceTile(MyPos, TheTile);
315end;
316
317(*
318R_DistanceFromFlag
319~~~~~~~~~~~~~~~~~~
320
321.. code-block:: pascal
322
323    function R_DistanceFromFlag: Integer;
324
325Returns the distance your char is from the flag.
326
327.. note::
328
329  by Drags111
330
331*)
332function R_DistanceFromFlag: Integer;
333var
334  MyPos, FlagPos: TTile;
335  Me: integer;
336begin
337  if not R_FlagExists then Exit;
338  Me := SmartGetFieldObject(0, hook_static_MyPlayer);
339  MyPos.x := SmartGetFieldArrayInt(Me, hook_character_WalkQueueX, 0);
340  MyPos.y := SmartGetFieldArrayInt(Me, hook_character_WalkQueueY, 0);
341  FlagPos := R_GetLocDest;
342  Result := Distance(MyPos.x, MyPos.y, FlagPos.x, FlagPos.y);
343  SmartFreeObject(me);
344end;
345
346(*
347R_RandomizeTile
348~~~~~~~~~~~~~~~
349
350.. code-block:: pascal
351
352    function R_RandomizeTile(Tile: TTile; rX, rY: Integer): TTile;
353
354Randomizes a tile using rX and rY.
355
356.. note::
357
358  by lordsaturn
359
360*)
361function R_RandomizeTile(Tile: TTile; rX, rY: Integer): TTile;
362begin
363  Result := Point(RandomRange(Tile.X-rX, Tile.X+rX),
364                   RandomRange(Tile.Y-rY, Tile.Y+rY));
365end;
366
367(*
368R_MakeCompass
369~~~~~~~~~~~~~
370
371.. code-block:: pascal
372
373    function R_MakeCompass(setAngle: Variant): Boolean;
374
375MakesCompass to degress set (Degress or n, e, s, w).
376
377.. note::
378
379  by Timer
380
381*)
382function R_MakeCompass(setAngle: Variant): Boolean;
383var
384  StartAngle, Angle, DirectionDeg, i: Extended;
385  Bool : Boolean;
386  Mark : Integer;
387begin
388  StartAngle := (R_GetMinimapAngleDeg);
389  if(StartAngle < 0)Or(Not LoggedIn)then
390    Exit;
391  case varType(setAngle) of
392    varString:
393    begin
394      case (LowerCase(setAngle)) of
395        'n': DirectionDeg := -1;
396        'w': DirectionDeg := 90;
397        's': DirectionDeg := 180;
398        'e': DirectionDeg := 270;
399      end;
400    end;
401    varDouble, varSingle:
402      DirectionDeg := setAngle;
403  end;
404  if((MinE(Abs(StartAngle - DirectionDeg), MinE(Abs(StartAngle - (DirectionDeg + 360)), Abs((StartAngle + 360) - DirectionDeg)))) <= 8.0)then
405  begin
406    Result := True;
407    Exit;
408  end;
409  Bool := (Round((360 - StartAngle) + DirectionDeg) mod 360 > Round((StartAngle + 360) - DirectionDeg) mod 360);
410  if(Bool)then
411    KeyDown(VK_LEFT)
412  else
413    KeyDown(VK_RIGHT);
414  Wait(Random(40));
415  MarkTime(Mark);
416  repeat
417    Wait(16);
418    Angle := R_GetMinimapAngleDeg;
419    If ((TimeFromMark(Mark) > 6000)  and (i < 1.0)) or
420       ((TimeFromMark(Mark) > 10000) and (i < 2.0)) or
421       ((TimeFromMark(Mark) > 14000) and (i < 3.0)) then
422      i := i + 1.0;
423  until ((MinE(Abs(Angle - DirectionDeg), MinE(Abs(Angle - (DirectionDeg + 360)), Abs((Angle + 360) - DirectionDeg)))) <= (7.0 + i))
424    or (TimeFromMark(Mark) > 14000)
425    or (Angle < 0);
426  if(Bool)then
427    KeyUp(VK_Left)
428  else
429    KeyUp(VK_Right);
430  Wait(Random(100) + 40);
431  Result := ((MinE(Abs(Angle - DirectionDeg), MinE(Abs(Angle - (DirectionDeg + 360)), Abs((Angle + 360) - DirectionDeg)))) <= (7.0 + i));
432end;
433
434(*
435R_Flag
436~~~~~~
437
438.. code-block:: pascal
439
440    procedure R_Flag;
441
442Waits Till A COMPLETE Stop. (Not dependant on Flag hooks)
443
444.. note::
445
446  by Drags111
447
448*)
449procedure R_Flag;
450var
451  Ticker: Integer;
452begin
453  Ticker := (GetSystemTime + 30000);
454  if not R_WaitToMove(1500) then Exit;
455  while (R_GetMotion > 0) do
456  begin
457    Wait(10 + Random(10));
458    if SRL_Procs[SRL_AntiBan] <> nil then
459      SRL_Procs[SRL_AntiBan]();
460    if (GetSystemTime > Ticker) then
461      Exit;
462  end;
463  Wait(500 + Random(50));
464end;
465
466(*
467R_FFlag
468~~~~~~~
469
470.. code-block:: pascal
471
472    procedure R_FFlag(Dist: Integer);
473
474Waits till you are within the distance specified from the flag.
475
476.. note::
477
478  by ZephyrsFury
479
480*)
481procedure R_FFlag(Dist: Integer);
482
483var
484  Tx, Ty, m, d1, d2: Integer;
485  D: TTile;
486
487begin
488  if not R_WaitToMove(1500) then Exit;
489  if(Dist = 0)then
490  begin
491    R_Flag;
492    Exit;
493  end;
494  while (R_FlagExists) do
495  begin
496    D := R_GetLocDest;
497    d1 := R_DistanceFromFlag;
498    if (d1 >= Dist) then
499    begin
500      if not (R_GetMotion > 0) then Exit;
501      Inc(m);
502      Wait(100 + Random(30));
503      if SRL_Procs[SRL_AntiBan] <> nil then
504        SRL_Procs[SRL_AntiBan]();
505      if (Random(100) = 0) then IdleTime(500, 1000, 0.01);
506      if (m mod 100 = 0) then
507        if (d1 = d2) then
508        begin
509          if (FindColor(Tx, Ty, 255, MMX1, MMY1, MMX2, MMY2)) then
510            Mouse(Tx, Ty + 14, 0, 0, True)
511          else
512            Mouse(MMCX, MMCY, 0, 0, True);
513        end else d2 := d1;
514    end else Break;
515  end;
516end;
517
518(*
519R_WalkToTileEx
520~~~~~~~~~~~~~~
521
522.. code-block:: pascal
523
524    function R_WalkToTileEx(Tile: TTile; Randomness, FlagDist: Integer; UseFFlag: Boolean): Boolean;
525
526Walks to the tile using minimap.
527
528.. note::
529
530  by Wizzup, TheGuyWhoGotOn, and Drags111
531
532*)
533function R_WalkToTileEx(Tile: TTile; Randomness, FlagDist: Integer; UseFFlag: Boolean): Boolean;
534var
535   wTile: TPoint;
536   t: Integer;
537begin
538  Result := False;
539  Tile := R_RandomizeTile(Tile, Randomness, Randomness);
540  wTile := R_TileToMM(Tile);
541  if not rs_OnMiniMap(wTile.X, wTile.Y) then
542    Exit;
543  Mouse(wTile.x, wTile.y, 1, 1, true);
544  Wait(RandomRange(80, 100));
545  t := getsystemtime;
546  if UseFFlag then R_FFlag(FlagDist);
547  Result := (GetSystemTime - t) < 60000;
548end;
549
550(*
551R_WalkToTile
552~~~~~~~~~~~~
553
554.. code-block:: pascal
555
556    function R_WalkToTile(Tile: TPoint; Randomness, FlagDist: Integer): Boolean;
557
558Walks to the tile using minimap.
559
560.. note::
561
562  by Drags111
563
564*)
565function R_WalkToTile(Tile: TPoint; Randomness, FlagDist: Integer): Boolean;
566begin
567  Result := R_WalkToTileEx(Tile, Randomness, FlagDist, true);
568end;
569
570(*
571R_WalkToTileMS
572~~~~~~~~~~~~
573
574.. code-block:: pascal
575
576    function R_WalkToTileMS(Tile: TPoint; FlagDist: Integer): Boolean;
577
578Walks to the tile using mainscreen.
579
580.. note::
581
582  by mormonman
583
584*)
585function R_WalkToTileMS(Tile:TTile; FlagDist: Integer): boolean;
586var
587  P: TPoint;
588  x, y, t: Integer;
589begin
590  if not LoggedIn then
591    Exit;
592
593  P := R_TileToMS(Tile, 50);
594  if not PointInBox(Point(P.x,P.y), IntToBox(MSX1, MSY1, MSX2, MSY2)) then
595    Exit;
596  MMouse(P.x, P.y, 5, 5);
597  GetMousePos(x, y);
598  if R_WaitUpText('Walk here', 300) then
599    Mouse(x, y, 0, 0, True) else
600    begin
601      Mouse(x, y, 0, 0, False);
602      Wait(RandomRange(400, 500));
603      R_ChooseOption('Walk here');
604    end;
605  Wait(RandomRange(120, 180));
606  t := getsystemtime;
607  R_FFlag(FlagDist);
608  Result := (GetSystemTime - t) < 60000;
609end;
610
611(*
612R_WalkPathEx
613~~~~~~~~~~~~
614
615.. code-block:: pascal
616
617    function R_WalkPathEx(Path: TTileArray; Randomness, FlagDistance: Integer; Inverted: Boolean): Boolean;
618
619Walks the Path of TTileArray from start to finish in a human-like style. It
620looks for the next tile in path and clicks it as soon as it comes up on the
621screen, just like a legit player would. This does make it more beneficial to
622use paths where the tiles are closer together, so it seems more active. All
623personal preference.
624-Path: The array of Tiles to use as the path.
625-Randomness: The amount of variance you want when walking to tiles.
626-FlagDist: The amount of distance from your player to the next tile before continuing walking. 
627-Inverted: If you want it to reverse the path (Walk from end to start).
628
629.. note::
630
631  by Drags111
632
633*)
634function R_WalkPathEx(Path: TTileArray; Randomness, FlagDist: Integer; Inverted: Boolean): Boolean;
635var
636  Index, Timer, Tries: Integer;
637begin
638  if Inverted then InvertTPA(Path);
639  while R_DistanceFromTile(Path[High(Path)]) > (FlagDist + Randomness + 1) do
640  begin
641    for Index := High(Path) downto 0 do
642      if R_TileOnMM(Path[Index]) then
643        Break;
644    if (Index = -1) then
645      Break;
646
647    if R_WalkToTileEx(Path[Index], Randomness, 0, false) then
648    begin
649      Timer := (GetSystemTime + 30000);
650      while R_DistanceFromTile(Path[Index]) > FlagDist do
651      begin
652        Wait(500 + Random(100));
653        if SRL_Procs[SRL_AntiBan] <> nil then
654          SRL_Procs[SRL_AntiBan]();
655        if (GetSystemTime > Timer) or (R_GetMotion = 0) or ((Index <> High(Path)) and (R_TileOnMM(Path[Index+1]))) then
656          Break;
657      end;
658
659      if (not (R_DistanceFromTile(Path[Index]) <= 5)) and
660          ((Index <> High(Path)) and (not R_TileOnMM(Path[Index+1]))) then
661        Inc(Tries);
662    end else
663    begin
664      Inc(Tries);
665      wait(800+Random(600));
666    end;
667    if Tries >= 10 then Break;
668  end;
669  R_FFlag(FlagDist);
670  Result := R_DistanceFromTile(Path[High(Path)]) <= (FlagDist + Randomness + 1);
671end;
672
673(*
674R_WalkPath
675~~~~~~~~~~
676
677.. code-block:: pascal
678
679    function R_WalkPath(Path: TTileArray): boolean;
680
681Walks the path. See WalkToPathEX for more info.
682
683.. note::
684
685  by Drags111
686
687*)
688function R_WalkPath(Path: TTileArray): boolean;
689begin
690  Result := R_WalkPathEx(Path, 3, 5, false);
691end;
692
693(*
694R_WindPath
695~~~~~~~~~~
696
697.. code-block:: pascal
698
699    function R_WindPath(xs, ys, xe, ye, gravity, wind, minWait, maxWait, maxStep, targetArea: extended): TPointArray;
700
701Generates a blind path of points!
702
703.. note::
704
705  by JuKKa
706
707*)
708function R_WindPath(xs, ys, xe, ye, gravity, wind, minWait, maxWait, maxStep, targetArea: extended): TPointArray;
709var
710  veloX, veloY, windX, windY, veloMag, dist, randomDist, lastDist, step: extended;
711  lastX, lastY: integer;
712  sqrt2, sqrt3, sqrt5: extended;
713begin
714  sqrt2:= sqrt(2);
715  sqrt3:= sqrt(3);
716  sqrt5:= sqrt(5);
717  while hypot(xs - xe, ys - ye) > 1 do
718  begin
719    dist:= hypot(xs - xe, ys - ye);
720    wind:= minE(wind, dist);
721    if dist >= targetArea then
722    begin
723      windX:= windX / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
724      windY:= windY / sqrt3 + (random(round(wind) * 2 + 1) - wind) / sqrt5;
725    end else
726    begin
727      windX:= windX / sqrt2;
728      windY:= windY / sqrt2;
729      if (maxStep < 3) then
730      begin
731        maxStep:= random(3) + 3.0;
732      end else
733      begin
734        maxStep:= maxStep / sqrt5;
735      end;
736    end;
737    veloX:= veloX + windX;
738    veloY:= veloY + windY;
739    veloX:= veloX + gravity * (xe - xs) / dist;
740    veloY:= veloY + gravity * (ye - ys) / dist;
741    if hypot(veloX, veloY) > maxStep then
742    begin
743      randomDist:= maxStep / 2.0 + random(round(maxStep) / 2);
744      veloMag:= sqrt(veloX * veloX + veloY * veloY);
745      veloX:= (veloX / veloMag) * randomDist;
746      veloY:= (veloY / veloMag) * randomDist;
747    end;
748    lastX:= Round(xs);
749    lastY:= Round(ys);
750    xs:= xs + veloX;
751    ys:= ys + veloY;
752    SetArrayLength(Result, GetArrayLength(Result) + 1);
753    Result[ High(Result) ] := Point(Round(xs), Round(ys));
754    step:= hypot(xs - lastX, ys - lastY);
755    lastdist:= dist;
756  end;
757end;
758
759(*
760R_WindPathMS
761~~~~~~~~~~
762
763.. code-block:: pascal
764
765    function R_WindPathMS(StartTile, TargetTile: TTile): TPointArray;
766
767Generates a blind path of onscreen points!
768
769.. note::
770
771  by mormonman
772
773*)
774function R_WindPathMS(StartTile, TargetTile: TTile): TPointArray;
775begin
776  Result := R_WindPath(StartTile.x, StartTile.y, TargetTile.x, TargetTile.y,
777                        5.0, 2.5, 0.0, 0.0, 1.5, 1.0);
778end;
779
780(*
781R_WindWalk
782~~~~~~~~~~
783
784.. code-block:: pascal
785
786    function R_WindWalk(T: TTile): Boolean;
787
788Walks blindly using WindPath! Does NOT consider walls or obstacles.
789
790.. note::
791
792  by JuKKa
793
794*)
795function R_WindWalk(T: TTile): Boolean;
796var
797  I, Tries: Integer;
798  M, P: TPoint;
799  CTRLPoints: TPointArray;
800begin
801  P := T;
802  repeat
803    M := R_GetMyPos;
804    CtrlPoints := R_WindPath(M.x, M.y, P.X, P.Y, 5.0, 2.5, 0.0, 0.0, 4.5, 2.5);
805    Inc(Tries);
806    if(Tries > 20)then
807    begin
808      R_Debug('Failed more than 20 times', 'R_WindWalk');
809      Exit;
810    end;
811    for I:= High(CtrlPoints) downto 0 do
812      if R_WalkToTile(CtrlPoints[i],0, 10) then
813      begin
814        Result := I = High(CtrlPoints);
815        Break;
816      end;
817  until(Result);
818end;
819
820(*
821R_WindWalkMS
822~~~~~~~~~~
823
824.. code-block:: pascal
825
826    function R_WindWalkMS(T: TTile): Boolean;
827
828Walks blindly using WindPathMS! Does NOT consider walls or obstacles.
829
830.. note::
831
832  by mormonman
833
834*)
835function R_WindWalkMS(T: TTile): Boolean;
836var
837  I, Tries: Integer;
838  M, P: TPoint;
839  CTRLPoints: TPointArray;
840begin
841  P := T;
842  repeat
843    M := R_GetMyPos;
844    CtrlPoints := R_WindPathMS(M, P);
845    Inc(Tries);
846    if(Tries > 20)then
847    begin
848      R_Debug('Failed more than 20 times', 'R_WindWalkMS');
849      Exit;
850    end;
851    for I:= High(CtrlPoints) downto 0 do
852      if R_WalkToTileMS(CtrlPoints[i], 1) then
853      begin
854        Result := I = High(CtrlPoints);
855        Break;
856      end;
857  until(Result);
858end;