Форум работает в тестовом режиме. Все данные были перенесены со старого сайта 2018 года. Некоторая информация может быть недоступна, например вложения или хайды. Просьба сообщать о данных случаях через функционал "Жалоба", прямо под постом, где отсуствуют данные из хайда или проблемы с вложением.
Могут быть проблемы в "выкидыванием" с форума (слетевшей авторизацией). Нужно собрать статистику таких случаев.
Есть Тема, куда можете сообщить о проблемах с сайтом либо просто передать привет.

застрял тп

Рег
4 Фев 2016
Сообщения
34
Реакции
0
Всем привет .
Не могу найти команду , если перс стоит N секунд на одном месте то юзает тп , если кто поможет найти буду благодарен .
 
такую проверку легко можно реализовать таким потоком:
Код:
uses SysUtils;

procedure Sticking_Thread(sec: integer);
var Timer: int64;  X, Y, Z: integer;
begin
  while (Engine.Status <> lsOnline) do delay(555);
  X:= User.X;
  Y:= User.Y;
  Z:= User.Z;
  Timer:= GetTickCount + sec*1000;
  while delay(555) do begin
    if (Abs(User.X-X) < 50) and (Abs(User.Y-Y) < 50) and (Abs(User.Z-Z) < 50) then begin
      if (GetTickCount > Timer) then begin
        if Engine.UseItem(736) then begin
          while (User.Cast.EndTime <> 0) do delay(555);
          delay(5555);
        end;
      end;
    end else begin
      X:= User.X;
      Y:= User.Y;
      Z:= User.Z;
      Timer:= GetTickCount + sec*1000;
    end;
  end;
end;

begin
  Script.NewThread(@Sticking_Thread(10));  // параметром указываем время (в сек), после которого юзать СОЕ
end.
 
Если тяжело со скриптами, то сделай по другому. Зайди в События - выбери Событие EXP, если не меняется exp в течении N секунд, то пусть юзает сое например.
 
@farmwl, зачем так все усложнять?
Код:
uses SysUtils;

procedure Sticking_Thread(sec: integer);
var X, Y, Z: integer;
begin
  while (Engine.Status = lsOnline) do begin

    X:= User.X;
    Y:= User.Y;
    Z:= User.Z;

    delay((sec*1000));
  
    if (User.X = X) or (User.Y = Y) or (User.Z = Z) then begin
      Engine.UseItem(736);
      delay(30000);
    end;

  end;
end;

begin
  Script.NewThread(@Sticking_Thread(10));  // параметром указываем время (в сек), после которого юзать СОЕ
end.
 
@ХОРВЕСТР, затем, что твой вариант не учитывает 3 случая:
  1. поскольку координаты в л2 меняются даже при минимальном "шажочке", а у тебя проверка на строгое равенство координат - если персонаж упрется в стену и будет в нее тыкаться, его координаты скорей всего будут меняться туда-сюда на 10-20 единиц, и твой код вообще не обработает данный случай
  2. если персонаж на сам деле двигается, но по магическому стечению обстоятельств он в начале проверки и через указанное время секунд будет иметь одинаковые координаты - то по твоему коду все равно будет решено, что он застарял.- это конечно маловероятный случай, но все-равно дырка в логике небольшая (представь, что ты бегаешь между двумя НПС и разговариваешь с ними по квестам, а тут бац - скрипт решает, что ты застрял)
    ну и вообще, постановка задачи была "если перс стоит N секунд на одном месте", а это значит, что все 10 секунд мы должны были не двигаться а быть "застрявшими", у тебя же проверяется что-то вроде "если через N секунд наши координаты такие же, как были в начале".
  3. если твой скрипт будет запущен до того, как окно войдет в игру - твой поток просто сразу выйдет из бесконечного цикла, и не будет работать вообще
 
@farmwl,

1. сам во втором пункте ответил на свой коментарий: постановка задачи была "если перс стоит N секунд на одном месте".
Если координаты меняются значи перс стоит не на одном месте.

2. "если перс стоит N секунд на одном месте" === ТОЖЕ САМОЕ ЧТО === "если через N секунд наши координаты такие же, как были в начале"

3. Это сделано не для того что бы он работал всегда, а для того что бы работал до момента выхода из игры.

Думай перед тем как комментировать.
 
@farmwl, У меня почему-то после запуска потока основной скрипт не продолжает свою работу, и работает только 1 поток. Как это исправить можно? Я немного подредактировал под старый адрик...


Код:
procedure Sticking_Thread(sec: integer);
var Timer: int64;  X, Y, Z: integer;
begin
   engine.msg('Событие', 'Q.', 25855);
  while Engine.Status <> lsOnline do delay(5555);
  X:= User.X;
  Y:= User.Y;
  Z:= User.Z;
  Timer:= GetTickCount + sec*1000;
  while Engine.Status = lsOnline do begin
    if (Abs(User.X-X) < 50) and (Abs(User.Y-Y) < 50) and (Abs(User.Z-Z) < 50) then begin
      if (GetTickCount > Timer) then begin
        if Engine.UseItem(736) then begin
          while (User.Cast.EndTime <> 0) do delay(555);
          delay(5555);
        end;
      end;
    end else begin
      X:= User.X;
      Y:= User.Y;
      Z:= User.Z;
      Timer:= GetTickCount + sec*1000;
    end;
  end;
end;








begin
Script.NewThread(@reconnect);// reconnect - процедура, в которой выполняется перезаход при дисконнекте
Script.NewThread(@Sticking_Thread(5));
if (User.Level<26) then QuestExp_1to25lvl();
........
 
Харе флеймить, все 3 решения вынесены в тему и имеют место быть)
 
@ХОРВЕСТР, это ты должен думать прежде чем делать замечания таким опытным ребятам как farmwl.
То, что ты скинул, не продумано и в некоторых случаях будет работать не так, как хотелось бы ТСу. А разница в ваших подходах и причина "сложности" скрипта farmwl'a в том, что ты проверяешь "через", а он "в течении". А именно "в течении" и нужно автору.

Да, автора вполне может устроить и твой вариант, но он 100% хуже и никакого смысла упрощать вариант farmwl'a нет, т.к. в нем нет суперсложных и ресурсозатратных алгоритмов.

@SARCAZM, да не, эт не флейм, вполне адекватная интеллектуальная беседа.
 
@sasha282, скорей всего дело в том, что на кряке нельзя подавать аргументы в процедуры, когда вызываешь их в потоке. странно, что оно вообще не посыпалось у тебя
попробуй так:



procedure Sticking_Thread(); // в объявлении процедуры убираешь подаваемые аргументы
var Timer: int64; X, Y, Z: integer;
begin
while (Engine.Status <> lsOnline) do delay(555);
X:= User.X;
Y:= User.Y;
Z:= User.Z;
Timer:= GetTickCount + 30*1000; // здесь вместо sec указываешь точную цифру, ее при желании можно вынести в const
while true do begin // здесь меняешь delay(555) на true, так как в старых версиях delay - это процедура, а не функция
delay(555); // добавляешь задержку сюда, т.к. циклы без зедержки грузят ЦП
if (Abs(User.X-X) < 50) and (Abs(User.Y-Y) < 50) and (Abs(User.Z-Z) < 50) then begin
if (GetTickCount > Timer) then begin
if Engine.UseItem(736) then begin
while (User.Cast.EndTime <> 0) do delay(555);
delay(5555);
end;
end;
end else begin
X:= User.X;
Y:= User.Y;
Z:= User.Z;
Timer:= GetTickCount + 30*1000; // здесь как и выше вместо sec указываешь точную цифру
end;
end;
end;


begin
Script.NewThread(@Sticking_Thread); // параметром указываем время (в сек), после которого юзать СОЕ
end.




@ХОРВЕСТР, странная реакция)
твой упрощенный вариант действительно имеет много дыр в логике и отрицать это глупо. я лишь указал на эти недочеты, и описал ситуации, в которых такой код покажет себя плохо и почему
взгляни хотя бы на эту строчку:

if (User.X = X) or (User.Y = Y) or (User.Z = Z)
ты в курсе, что если ты будешь спокойно и размеренно бегать на одном уровне Z в течение N секунд (например, ты бегаешь в Годдарте на одном из уровней), то твой решит, что ты застрял?) ситуаций, когда "упрощенный" вариант отработает неверно - много, и некоторые из них весьма вероятны.
так что к чему такие едкие высказывания, тем более, если ты сам ошибаешься - НИПАНЯТНА :hz:
 
Добавлю от себя, давно уже решил тоже эту проблему и такой вариант не всегда срабатывает четко ибо часто ГЕОДАТА ОЧЕНЬ КРИВАЯ и персонаж при застревании "дергается" и постоянно меняется +- 2-3 координаты, опытным путем вычислил от чего зависит (конечно от скорости персонажа), в скрипте от Фарма это значение равно 50, на самом деле оно на много меньше, но вы смотрите сами:


farmwl написал(а):
if (Abs(User.X-X) < 50) and (Abs(User.Y-Y) < 50) and (Abs(User.Z-Z) < 50) then begin
var
UserSpeedDelay:Integer;
.....
UserSpeedDelay:=round(User.Speed / 160);
if ((abs(X-User.X)<UserSpeedDelay)and(abs(Y-User.Y)<UserSpeedDelay)))and (user.cast.endtime=0) then

Разница в нашем коде следующая:
  1. Если мы падаем вертикально вниз (провалились в "текстуры", мы поймем что "застряли", а не будем дальше считать что двигаемся.
  2. Переменная UserSpeedDelay вычисляется динамически в зависимости от скорости персонажа ( на самом деле смотрите сами и выставляйте сами)
  3. Ну и конечно самое главное - user.cast.endtime=0 Проверка что мы не кастуем сое или что-то другое (анстак), а подумали что застряли.
  4. П.С. можно еще много всякий исключительных ситуацй придумать и можно все это запихнуть в OnMoveEvent бота, почемуто все про него забыли.
@ХОРВЕСТР, Что за нахрен война с минусами может хватит уже? П.С. ты первый начал.
 
Ivanius написал(а):
Добавлю от себя, давно уже решил тоже эту проблему и такой вариант не всегда срабатывает четко ибо часто ГЕОДАТА ОЧЕНЬ КРИВАЯ и персонаж при застревании "дергается" и постоянно меняется +- 2-3 координаты, опытным путем вычислил от чего зависит (конечно от скорости персонажа), в скрипте от Фарма это значение равно 50, на самом деле оно на много меньше, но вы смотрите сами:
Да, действительно после дня тестирвания заметил такой нюанс, раза 3 не реагировал на горе кода персонаж стоял. Я вот не до конца пойму причем тут скорость бега? Наверно когда персонаж меняет 2-3 координата скорость бега не задействуется в игре, и таким образом можно точно вычислить застрял персонаж или нет? Что тут тогда динамически вычислять? Поставил <156 и все. (это вроде бы минимум, не считая дебафов, если дебафы есть, значит персонаж скорее всего в режиме боя, а значит поможет команда User.InCombat = false )

А вот не будет ли почти такой же эффект если тут изменить < 50 на < 2 :

if (Abs(User.X-X) < 2) and (Abs(User.Y-Y) < 2) and (Abs(User.Z-Z) < 2) then begin
Получается, если координаты не поменяются на хотя бы + - 1 единицу, то через указанное время срипт юзает сое.
 
@sasha282, Да все верно, я также написал об этом что можно просто поставить какое-то значение (около 5). А еще Z координату лучше убрать из условия и заменить ее на проверку каста.
 
Tfox написал(а):
Зайди в События - выбери Событие EXP, если не меняется exp в течении N секунд
не прокатывает если кап по лвлу и эксп/сп
 
Пробывал оба варианта, но почему-то бывает не срабатывает скрипт. Казалось бы и координаты не меняются совсем через команду /loc. Просто в стену вопрется и стоит.
Код:
procedure Sticking_Thread1;   // в объявлении процедуры убираешь подаваемые аргументы
var Timer: int64; UserSpeedDelay, X, Y, Z: integer;
begin
  Print('Запомнил точку');
  while (Engine.Status <> lsOnline) do delay(5555);
  X:= User.X;
  Y:= User.Y;
  Z:= User.Z;
  UserSpeedDelay:=round(User.Speed / 120);
  Timer:= GetTickCount + 120*1000;   // здесь вместо sec указываешь точную цифру, ее при желании можно вынести в const
    while User.InCombat = false do begin   // здесь меняешь delay(555) на true, так как в старых версиях delay - это процедура, а не функция
    delay(3000);         // добавляешь задержку сюда, т.к. циклы без зедержки грузят ЦП
if ((abs(X-User.X)<UserSpeedDelay)and(abs(Y-User.Y)<UserSpeedDelay))and (user.cast.endtime=0) then begin
      if (GetTickCount > Timer) then begin
      if user.dead then engine.msg('Важно', 'Что-то пошло не так! Персонаж умер.', 255);
      if not user.dead then engine.msg('Важно', 'Что-то пошло не так. Возможно персонаж застрял.', 255);
     engine.msg('Важно', 'Лечу в город и пытаюсь продолжить.', 255);
      engine.useitem (736);
      end;
    end else begin
      X:= User.X;
      Y:= User.Y;
      Z:= User.Z;
      Timer:= GetTickCount + 120*1000;  // здесь как и выше вместо sec указываешь точную цифру
    end;
  end;
end;





procedure Sticking_Thread(sec: integer);
var Timer: int64;  X, Y, Z: integer;
begin
  while (Engine.Status <> lsOnline) do delay(555);
  X:= User.X;
  Y:= User.Y;
  Z:= User.Z;
  Timer:= GetTickCount + sec*1000;
  while User.InCombat = false do begin
    if (Abs(User.X-X) < 2) and (Abs(User.Y-Y) < 2) and (Abs(User.Z-Z) < 2) and (user.cast.endtime=0) then begin
      if (GetTickCount > Timer) then begin
      if user.dead then engine.msg('Важно', 'Что-то пошло не так! Персонаж умер.', 255);
      if not user.dead then engine.msg('Важно', 'Что-то пошло не так. Возможно персонаж застрял.', 255);
     engine.msg('Важно', 'Лечу в город и пытаюсь продолжить.', 255);
     engine.useitem (736);
      if Engine.UseItem(736) then begin
      while (User.Cast.EndTime <> 0) do delay(555);
      delay(5555);
        end;
      end;
    end else begin
      X:= User.X;
      Y:= User.Y;
      Z:= User.Z;
      Timer:= GetTickCount + sec*1000;
    end;
  end;
end;
 
проблема если маг стоит в центре комнаты и бьет кастами он не двигается и делает ТП как это можно поправить?
 
Назад
Сверху