PDA

Просмотр полной версии : Ошибка при отставание ведомого.


BloodAngel
02.05.2011, 21:02
Давно не ботил. Решил взяться за старое =)

Суть проблемы:
Использую самую новую версию бота скачанную с СВН.
Revision: r7718
Есть два персонажа Син и Прист. Качаются в пати и прист в роли суппорта. Когда прист задерживается(при любых обстоятельствах хоть то долгий каст или даже отключение ai на короткое время) и теряет ведущего из поля зрения выдаёт вот такую ошибку: "BUG: Actor::move(undef, undef) called!"
После чего бот пытается идти вперёд, но его откидывает назад как буд-то он и не пытался двигаться и выдаёт следующую ошибку "You tried too long to move". и эта ошибка повторяется несколько раз после чего бот перестаёт пытаться. Координаты показанные в боте отличаются от координат в игре (/where)

Вопрос:
Как избавиться от этой ошибки?

Мой временный и глупый вариант от залипания бота:
С помощью макроса
1)при виде строчки "You tried too long to move" останавливаю движение "move stop"
2)вывожу в игровой чат команду "@refresh"(обновляет место положение персонажа. В игре это выглядит как использование винга)
3)двигаюсь рандомно на 1-2 клетки в любую сторону
После всего этого бот пытается двигаться дальше к ведущиму, но иногда ошибка повторяется.
Пытался найти решение на форумах, но не нашёл. Нашёл хороший плагин "ReactOnActor" с помощью которого можно было заставить ведущего ждать ведомого если тот отстал на определённое количество клеток, но ссылка битая. Если у кого есть новая версия подходящая под мою ревизию киньте ссылку.

В помощь по устранению данной ошибки:
"BUG: Actor::move(undef, undef) called!" - данная строка находится в "src\Actor.pm"
sub move {
my ($self, $x, $y, $attackID) = @_;

unless ($x and $y) {
# that happens when called from AI::CoreLogic::processFollow
error "BUG: Actor::move(undef, undef) called!\n";
return;
}

require Task::Move;

$self->queue('move', my $task = new Task::Move(
actor => $self,
x => $x,
y => $y,
));
$task->{attackID} = $attackID;
}
Удивил комментарий "# that happens when called from AI::CoreLogic::processFollow" в переводе означает "# Это происходит когда вызывается из AI::CoreLogic::processFollow" это типа пометка разработчикам что есть такой баг?

"You tried too long to move" - находится в "src\Task\Move.pm"
sub iterate {
my ($self) = @_;
return if (!$self->SUPER::iterate());
return if ($net->getState() != Network::IN_GAME);

# If we're sitting, wait until we've stood up.
if ($self->{actor}{sitting}) {
debug "Move $self->{actor} - trying to stand\n", "move";
my $task = new Task::SitStand(actor => $self->{actor}, mode => 'stand');
$self->setSubtask($task);

# Stop if the map changed.
} elsif ($self->{mapChanged}) {
debug "Move $self->{actor} - map change detected\n", "move";
$self->setDone();

# Stop if we've moved.
} elsif ($self->{actor}{time_move} > $self->{start_time}) {
debug "Move $self->{actor} - done\n", "move";
$self->setDone();

# Stop if we've timed out.
} elsif (timeOut($self->{giveup})) {
debug "Move $self->{actor} - timeout\n", "move";
$self->setError(TOO_LONG, TF("%s tried too long to move", $self->{actor}));

} elsif (timeOut($self->{retry})) {
debug "Move $self->{actor} - (re)trying\n", "move";
$self->{actor}->sendMove(@{$self}{qw(x y)});
$self->{retry}{time} = time;
}
}

BloodAngel
03.05.2011, 22:51
Вижу придётся самому пытаться править ошибку.
Тогда вопрос:
Как корректно узнать координаты сопартийца?

Покопался в "AI::CoreLogic::processFollow" и нашёл место когда бот потерял ведущего.
Проверка на потерю ведущего идёт после комментария "##### FOLLOW-LOST #####"
Ниже расписаны всякие варианты потери ведущего(ушёл в портал, телепортнулся, вышел из игры и т.д.) но нужная часть в самом низу my $portalID = $args->{follow_lost_portalID};
if ($args->{'follow_lost_portalID'} ne "" && $portalID) {
if ($portals{$portalID} && !$args->{'follow_lost_portal_tried'}) {
$args->{'follow_lost_portal_tried'} = 1;
%{$ai_v{'temp'}{'pos'}} = %{$portals{$args->{'follow_lost_portalID'}}{'pos'}};
ai_route($field->baseName, $ai_v{'temp'}{'pos'}{'x'}, $ai_v{'temp'}{'pos'}{'y'},
attackOnRoute => 1);
}
} else {
moveAlongVector($ai_v{'temp'}{'pos'}, $chars[$config{'char'}]{'pos_to'}, $args->{'ai_follow_lost_vec'}, $config{'followLostStep'});
$char->move(@{$ai_v{temp}{pos}}{qw(x y)});
}
А ещё точнее при поиске потерявшегося ведущего выполняется всё что после "else".
Посмотрев как реализованы движения чуть выше я и дописал перед "moveAlongVector" вот такой код
ai_route($field->baseName, $ai_v{'temp'}{'pos'}{'x'}, $ai_v{'temp'}{'pos'}{'y'},
attackOnRoute => 1);
После чего бот не перестал выводить ошибку "BUG: Actor::move(undef, undef) called!", но перестал выводить "You tried too long to move". Теперь не залипает, но если мельком увидел ведущего, а потом опять же потерял то бежит к точке где раньше его видел.
"$ai_v{'temp'}{'pos'}" - как я понял "pos" хранит предыдущие координаты, а "pos_to" новые координаты. Но если прописать "$ai_v{'temp'}{'pos_to'}" то начинает опять залипать и выдавать ошибки.

Какие есть идеи? Или никто здесь так углублённо бот не ломает?

P.S. - сервак игровой с сайтом целый день валяется. А хотел сегодня ещё покопаться с проблемой.

4epT
12.05.2011, 11:07
.
Перед moveAlongVector возможно не определено $ai_v{temp}{pos} (Utils::moveAlongVector записывает результат в первый аргумент), поэтому вряд ли стоит его использовать перед этим вызовом для ai_route.

$ai_v{temp}{pos_to} вообще там нету вроде, оно есть в $char и остальных объектах Actor.

Вместо $chars[$config{char}]{something} вообще там бы давно должно везде использоваться $char->{something}.

Вместо ai_route теперь можно использовать $char->route, аргументы те же.

Чтобы разобраться, в чём дело, можно сначала проверить аргументы, передающиеся в moveAlongVector, добавив перед ним что-нибудь вроде этого:

use Data::Dumper;
message Dumper({pos_to => $char->{pos_to}, vec => $args->{ai_follow_lost_vec}, step => $config{followLostStep}});


А добавлено это сообщение про BUG: move очень давно: http://openkore.svn.sourceforge.net/viewvc/openkore/trunk/openkore/src/AI.pm?r1=3412&r2=3474&pathrev=4003

BloodAngel
14.05.2011, 01:38
Дописал в CoreLogic.pm перед moveAlongVector
use Data::Dumper;
message Dumper({pos_to => $char->{pos_to}, vec => $args->{ai_follow_lost_vec}, step => $config{followLostStep}});

Вот что пишет
$VAR1 = {
'vec' => {
'y' => 21,
'x' => -22
},
'step' => '10',
'pos_to' => {
'y' => 43,
'x' => 108
}
};
BUG: Actor::move(undef, undef) called!
$VAR1 = {
'vec' => {
'y' => 21,
'x' => -22
},
'step' => '10',
'pos_to' => {
'y' => 46,
'x' => 104
}
};
You tried too long to move

Если сделать проверку на отсутствие координат "{pos_to}{x}" и "{pos_to}{y}" то "BUG: Actor::move(undef, undef) called!" Уже не выводит.

Заметил что прист бегает по прямой быстрее чем син. Я бы сказал иногда обгоняет как-будто син без аги идёт.
Так же удивляет реакция приста когда он бежит к сину(ищет его) а син бежит к нему на встречу и мимо пробегает. Прист пишет что мастер найден доходит до той точки куда шёл и только потом разворачивается, а син в этот момент уже мог убежать и вот тут частенько бывает этот BUG.
Нельзя ли сделать так что бы персонаж остановился как только нашёл мастера и сразу переключился на преследование?

BloodAngel
15.05.2011, 18:21
Что-то ни как не хочет исправляться баг. Ну да ладно, пойдём от обратного. Сделаем так что бы ведущий и ведомый не расставались. Макрос "Ждём ведомого" (http://ragbot.ru/forum/showthread.php?p=29498#post29498)