Checking if our character is stuck (in the thread)

There are cases when the character gets stuck in the geodate \ rests on the wall and so on during the execution of the script. Such cases can be handled in a separate thread and take any measures. It will be useful for those who write their scripts:

uses SysUtils;

procedure CheckStuckThread(sec: integer);
var Timer: int64;  X, Y, Z: integer;
  while (Engine.Status <> lsOnline) do delay(555);    // expect to enter the game
  X:= User.X;  Y:= User.Y;  Z:= User.Z;               // remember current coordinates
  Timer:= GetTickCount + sec*1000;                    // remember the time

  while delay(555) do begin                           // run an endless loop
    if (Engine.Status = lsOnline) then begin          // if we're in the game then
      if (User.Cast.EndTime = 0)                      // if we don't cast anything at the moment
      and (not User.Sitting)                          // and do not sit
      and (Abs(User.X-X) < 10)                        // (value 10 can be changed) 
      and (Abs(User.Y-Y) < 10) then begin             // and our coordinates have hardly changed then
        Print('It looks like Im standing still');     // write to the logs (this line can be commented out)
        if (GetTickCount > Timer) then begin          // if more than a specified time has passed then
          Script.Suspend;                             // we slow down the script
          Print('I seem to be stuck');                // write to the logs (this line can be commented out)
          if Engine.UseItem(736) then begin           // use SoE
            while (User.Cast.EndTime <> 0) do delay(555); // waiting for the end of cast
            delay(5555);                              // and wait a little more to load
          Script.Replace;                             // restart the script (or do smth else)
      end else begin                                  // if we don't cast anything, and our coordinates have changed then
        X:= User.X;  Y:= User.Y;  Z:= User.Z;         // remember new coordinates
        Timer:= GetTickCount + sec*1000;              // update timer
        Print('All right im moving');                 // write to the logs (this line can be commented out)

  Script.NewThread(@CheckStuckThread, Pointer(30));  // specify the time parameter (in seconds) after which to use SOE
  // code ...

The general logic is:
We wait for the entrance to the game, remember our coordinates, and then every half a second we compare our coordinates with those that we remembered before: if the coordinates have not changed + we do not cast anything at the moment and it lasts longer than the specified time (30 seconds in our case), then we slow down the script, use SOE and restart the script. If our coordinates have changed a little or we cast something (for example SOE), then reset the timer and remember the current coordinates (we will compare them further)