Code: Select all
Index: Commands.pm
===================================================================
--- Commands.pm (revision 7684)
+++ Commands.pm (working copy)
@@ -3953,6 +3953,7 @@
require Task::SitStand;
my $task = new Task::ErrorReport(
task => new Task::SitStand(
+ actor => $char,
mode => 'sit',
priority => Task::USER_PRIORITY
)
@@ -4056,6 +4057,7 @@
require Task::SitStand;
my $task = new Task::ErrorReport(
task => new Task::SitStand(
+ actor => $char,
mode => 'stand',
priority => Task::USER_PRIORITY
)
Index: Actor.pm
===================================================================
--- Actor.pm (revision 7684)
+++ Actor.pm (working copy)
@@ -40,6 +40,7 @@
use Utils::CallbackList;
use Log qw(message error debug);
use Misc;
+use Task;
use Translation qw(T TF);
use Actor::Unknown;
@@ -514,56 +515,98 @@
sub move {
my ($self, $x, $y, $attackID) = @_;
- unless ($x || $y) {
- error "BUG: Actor::move(0, 0) called!\n";
- return;
- }
+ require Task::Move;
- my %args = (
- move_to => { x => $x, y => $y },
- attackID => $attackID,
- time_move => $self->{time_move},
- ai_move_giveup => { timeout => $timeout{ai_move_giveup}{timeout} },
+ $self->queue('move', my $task = new Task::Move(
+ actor => $self,
+ x => $x,
+ y => $y,
+ ));
+ $task->{attackID} = $attackID;
+}
+
+sub route {
+ my ($self, $map, $x, $y, %args) = @_;
+ debug "$self on route to: $maps_lut{$map.'.rsw'}($map): $x, $y\n", "route";
+
+ # I can't use 'use' because of circular dependencies.
+ require Task::Route;
+ require Task::MapRoute;
+
+ # from Homunculus AI
+ ($x, $y) = map { $_ ne '' ? int $_ : $_ } ($x, $y);
+
+ my $task;
+ my @params = (
+ actor => $self,
+ x => $x,
+ y => $y,
+ maxDistance => $args{maxRouteDistance},
+ maxTime => $args{maxRouteTime},
+ avoidWalls => !$args{noAvoidWalls},
+ map { $_ => $args{$_} } qw(distFromGoal pyDistFromGoal notifyUponArrival)
);
- debug sprintf("%s sending move from (%d,%d) to (%d,%d) - distance %.2f\n",
- $self, @{$self->{pos}}{qw(x y)}, $x, $y, Utils::distance($self->{pos}, $args{move_to})), "ai_move";
- $self->queue("move", \%args);
+ if ($map && !$args{noMapRoute}) {
+ $task = new Task::MapRoute(map => $map, @params);
+ } else {
+ $task = new Task::Route(@params);
+ }
+ $task->{$_} = $args{$_} for qw(attackID attackOnRoute noSitAuto LOSSubRoute);
+
+ $self->queue('route', $task);
}
-sub processMove {
- my ($self) = @_;
-
- if ($self->action eq "move") {
- my $args = $self->args;
- $args->{ai_move_giveup}{time} = time unless $args->{ai_move_giveup}{time};
-
- # Wait until we've stand up, if we're sitting
- if ($self->{sitting}) {
- $args->{ai_move_giveup}{time} = 0;
- AI::stand;
-
- # Stop if the map changed
- } elsif ($args->{mapChanged}) {
- debug "$self move - map change detected\n", "ai_move";
- $self->dequeue;
-
- # Stop if we've moved
- } elsif ($args->{time_move} != $self->{time_move}) {
- debug "$self move - moving\n", "ai_move";
- $self->dequeue;
-
- # Stop if we've timed out
- } elsif (timeOut($args->{ai_move_giveup})) {
- debug "$self move - timeout\n", "ai_move";
- $self->dequeue;
-
- } elsif (timeOut($self->{move_retry}, 0.5)) {
- # No update yet, send move request again.
- # We do this every 0.5 secs
- $self->{move_retry} = time;
- $self->sendMove(@{$args->{move_to}}{qw(x y)});
+sub processTask {
+ my $self = shift;
+ my $ai_name = shift;
+ if ($self->action eq $ai_name) {
+ my $task = $self->args;
+ if ($task->getStatus() == Task::INACTIVE) {
+ $task->activate();
+ should($task->getStatus(), Task::RUNNING) if DEBUG;
}
+ if (DEBUG && $task->getStatus() != Task::RUNNING) {
+ require Scalar::Util;
+ require Data::Dumper;
+ # Make sure redundant information is not included in the error report.
+ if ($task->isa('Task::MapRoute')) {
+ delete $task->{ST_subtask}{solution};
+ } elsif ($task->isa('Task::Route') && $task->{ST_subtask}) {
+ delete $task->{solution};
+ }
+ die "Task '" . $task->getName() . "' (class " . Scalar::Util::blessed($task) . ") has status " .
+ Task::_getStatusName($task->getStatus()) .
+ ", but should be RUNNING. Object details:\n" .
+ Data::Dumper::Dumper($task);
+ }
+ $task->iterate();
+ if ($task->getStatus() == Task::DONE) {
+ # We can't just dequeue the last AI sequence. Perhaps the task
+ # pushed a new AI sequence on the AI stack just before finishing.
+ # For example, the Route task does that when it's stuck.
+ # So, we must dequeue the correct sequence without affecting the
+ # others.
+ my ($ai_seq, $ai_seq_args) = $self->isa('Actor::You') ? (\@AI::ai_seq, \@AI::ai_seq_args) : (@{$self}{qw(slave_ai_seq slave_ai_seq_args)});
+ for (my $i = 0; $i < @$ai_seq; $i++) {
+ if ($ai_seq->[$i] eq $ai_name) {
+ splice(@$ai_seq, $i, 1);
+ splice(@$ai_seq_args, $i, 1);
+ last;
+ }
+ }
+ my %args = @_;
+ my $error = $task->getError();
+ if ($error) {
+ if ($args{onError}) {
+ $args{onError}->($task, $error);
+ } else {
+ error("$error->{message}\n");
+ }
+ } elsif ($args{onSuccess}) {
+ $args{onSuccess}->($task);
+ }
+ }
}
}
Index: AI/CoreLogic.pm
===================================================================
--- AI/CoreLogic.pm (revision 7684)
+++ AI/CoreLogic.pm (working copy)
@@ -65,21 +65,21 @@
return if processClientSuspend();
Benchmark::begin("AI (part 1.1)") if DEBUG;
processLook();
- processTask('NPC');
+ $char->processTask('NPC');
processEquip();
processDrop();
processEscapeUnknownMaps();
Benchmark::end("AI (part 1.1)") if DEBUG;
Benchmark::begin("AI (part 1.2)") if DEBUG;
processDelayedTeleport();
- processTask("sitting");
- processTask("standing");
+ $char->processTask("sitting");
+ $char->processTask("standing");
AI::Attack::process();
Benchmark::end("AI (part 1.2)") if DEBUG;
Benchmark::begin("AI (part 1.3)") if DEBUG;
processSkillUse();
processAutoCommandUse();
- processTask("route", onError => sub {
+ $char->processTask("route", onError => sub {
my ($task, $error) = @_;
if (!($task->isa('Task::MapRoute') && $error->{code} == Task::MapRoute::TOO_MUCH_TIME())
&& !($task->isa('Task::Route') && $error->{code} == Task::Route::TOO_MUCH_TIME())) {
@@ -87,7 +87,7 @@
}
});
processTake();
- $char->processMove;
+ $char->processTask('move');
Benchmark::end("AI (part 1.3)") if DEBUG;
Benchmark::begin("AI (part 1.4)") if DEBUG;
@@ -722,57 +722,6 @@
}
}
-sub processTask {
- my $ai_name = shift;
- if (AI::action eq $ai_name) {
- my $task = AI::args;
- if ($task->getStatus() == Task::INACTIVE) {
- $task->activate();
- should($task->getStatus(), Task::RUNNING) if DEBUG;
- }
- if (DEBUG && $task->getStatus() != Task::RUNNING) {
- require Scalar::Util;
- require Data::Dumper;
- # Make sure redundant information is not included in the error report.
- if ($task->isa('Task::MapRoute')) {
- delete $task->{ST_subtask}{solution};
- } elsif ($task->isa('Task::Route') && $task->{ST_subtask}) {
- delete $task->{solution};
- }
- die "Task '" . $task->getName() . "' (class " . Scalar::Util::blessed($task) . ") has status " .
- Task::_getStatusName($task->getStatus()) .
- ", but should be RUNNING. Object details:\n" .
- Data::Dumper::Dumper($task);
- }
- $task->iterate();
- if ($task->getStatus() == Task::DONE) {
- # We can't just dequeue the last AI sequence. Perhaps the task
- # pushed a new AI sequence on the AI stack just before finishing.
- # For example, the Route task does that when it's stuck.
- # So, we must dequeue the correct sequence without affecting the
- # others.
- for (my $i = 0; $i < @AI::ai_seq; $i++) {
- if ($AI::ai_seq[$i] eq $ai_name) {
- splice(@AI::ai_seq, $i, 1);
- splice(@AI::ai_seq_args, $i, 1);
- last;
- }
- }
- my %args = @_;
- my $error = $task->getError();
- if ($error) {
- if ($args{onError}) {
- $args{onError}->($task, $error);
- } else {
- error("$error->{message}\n");
- }
- } elsif ($args{onSuccess}) {
- $args{onSuccess}->($task);
- }
- }
- }
-}
-
sub processTake {
##### TAKE #####
@@ -802,7 +751,7 @@
my (%vec, %pos);
getVector(\%vec, $item->{pos}, $myPos);
moveAlongVector(\%pos, $myPos, \%vec, $dist - 1);
- move($pos{x}, $pos{y});
+ $char->move(@pos{qw(x y)});
} else {
my $pos = $item->{pos};
message TF("Routing to (%s, %s) to take %s (%s), distance %s\n", $pos->{x}, $pos->{y}, $item->{name}, $item->{binID}, $dist);
@@ -2022,7 +1971,7 @@
getVector(\%vec, $player->{pos_to}, $char->{pos_to});
moveAlongVector(\%pos, $char->{pos_to}, \%vec, $dist - $config{followDistanceMin});
$timeout{ai_sit_idle}{time} = time;
- $messageSender->sendMove($pos{x}, $pos{y});
+ $char->sendMove(@pos{qw(x y)});
}
}
}
@@ -2157,7 +2106,7 @@
getVector(\%vec, $pos, $char->{pos_to});
moveAlongVector(\%pos_to, $char->{pos_to}, \%vec, $dist);
$timeout{ai_sit_idle}{time} = time;
- move($pos_to{x}, $pos_to{y});
+ $char->move(@pos_to{qw(x y)});
$pos->{x} = int $pos_to{x};
$pos->{y} = int $pos_to{y};
@@ -2174,7 +2123,7 @@
} elsif ($args->{'lost_stuck'}) {
if ($args->{'follow_lost_portalID'} eq "") {
moveAlongVector($ai_v{'temp'}{'pos'}, $chars[$config{'char'}]{'pos_to'}, $args->{'ai_follow_lost_vec'}, $config{'followLostStep'} / ($args->{'lost_stuck'} + 1));
- move($ai_v{'temp'}{'pos'}{'x'}, $ai_v{'temp'}{'pos'}{'y'});
+ $char->move(@{$ai_v{temp}{pos}}{qw(x y)});
}
} else {
my $portalID = $args->{follow_lost_portalID};
@@ -2187,7 +2136,7 @@
}
} else {
moveAlongVector($ai_v{'temp'}{'pos'}, $chars[$config{'char'}]{'pos_to'}, $args->{'ai_follow_lost_vec'}, $config{'followLostStep'});
- move($ai_v{'temp'}{'pos'}{'x'}, $ai_v{'temp'}{'pos'}{'y'});
+ $char->move(@{$ai_v{temp}{pos}}{qw(x y)});
}
}
}
@@ -2814,7 +2763,7 @@
my (%vec, %pos);
getVector(\%vec, $items{$ID}{pos}, $myPos);
moveAlongVector(\%pos, $myPos, \%vec, $dist - 1);
- move($pos{x}, $pos{y});
+ $char->move(@pos{qw(x y)});
} else {
my $item = $items{$ID};
my $pos = $item->{pos};
Index: AI/Attack.pm
===================================================================
--- AI/Attack.pm (revision 7684)
+++ AI/Attack.pm (working copy)
@@ -396,7 +396,7 @@
} elsif (!$cleanMonster) {
# Drop target if it's already attacked by someone else
message T("Dropping target - you will not kill steal others\n"), "ai_attack";
- $messageSender->sendMove($realMyPos->{x}, $realMyPos->{y});
+ $char->sendMove(@{$realMyPos}{qw(x y)});
AI::dequeue;
if ($config{teleportAuto_dropTargetKS}) {
message T("Teleporting due to dropping attack target\n"), "teleport";
@@ -456,9 +456,9 @@
if ($config{attackChangeTarget} == 1) {
# Restart attack from processAutoAttack
AI::dequeue;
- ai_route($field->baseName, $best_spot->{x}, $best_spot->{y}, LOSSubRoute => 1);
+ $char->route(undef, @{$best_spot}{qw(x y)}, LOSSubRoute => 1);
} else {
- ai_route($field->baseName, $best_spot->{x}, $best_spot->{y});
+ $char->route(undef, @{$best_spot}{qw(x y)});
}
} else {
warning TF("%s; no acceptable place to stand\n", $msg);
@@ -523,7 +523,7 @@
#message "Time spent: " . (time - $begin) . "\n";
#debug_showSpots('runFromTarget', \@blocks, $bestBlock);
$args->{avoiding} = 1;
- move($bestBlock->{x}, $bestBlock->{y}, $ID);
+ $char->move(@{$bestBlock}{qw(x y)}, $ID);
} elsif ($realMonsterDist > $args->{attackMethod}{maxDistance}
&& timeOut($args->{ai_attack_giveup}, 0.5)) {
@@ -537,7 +537,7 @@
debug "Target distance $dist is >$args->{attackMethod}{maxDistance}; moving to target: " .
"from ($myPos->{x},$myPos->{y}) to ($pos->{x},$pos->{y})\n", "ai_attack";
- my $result = ai_route($field->baseName, $pos->{x}, $pos->{y},
+ my $result = $char->route(undef, @{$pos}{qw(x y)},
maxRouteTime => $config{'attackMaxRouteTime'},
attackID => $ID,
noMapRoute => 1,
@@ -569,7 +569,7 @@
# Our recorded position might be out of sync, so try to unstuck
$args->{unstuck}{time} = time;
debug("Attack - trying to unstuck\n", "ai_attack");
- move($myPos->{x}, $myPos->{y});
+ $char->move(@{$myPos}{qw(x y)});
$args->{unstuck}{count}++;
}
Index: AI/Slave.pm
===================================================================
--- AI/Slave.pm (revision 7684)
+++ AI/Slave.pm (working copy)
@@ -136,7 +136,7 @@
# auto-follow
if (
$slave->{slave_AI} == AI::AUTO
- && AI::action eq "move"
+ && (AI::action eq "move" || AI::action eq "route")
&& !$char->{sitting}
&& !AI::args->{mapChanged}
&& !AI::args->{time_move} != $char->{time_move}
@@ -148,7 +148,7 @@
) {
$slave->clear('move', 'route');
if (!checkLineWalkable($slave->{pos_to}, $char->{pos_to})) {
- $slave->slave_route($char->{pos_to}{x}, $char->{pos_to}{y});
+ $slave->route(undef, @{$char->{pos_to}}{qw(x y)});
$slave->args->{follow_route} = 1 if $slave->action eq 'route';
debug sprintf("Slave follow route (distance: %.2f)\n", $slave->distance()), 'homunculus';
@@ -231,8 +231,14 @@
return unless $slave->{slave_AI};
return if $slave->processClientSuspend;
$slave->processAttack;
- $slave->processRouteAI;
- $slave->processMove;
+ $slave->processTask('route', onError => sub {
+ my ($task, $error) = @_;
+ if (!($task->isa('Task::MapRoute') && $error->{code} == Task::MapRoute::TOO_MUCH_TIME())
+ && !($task->isa('Task::Route') && $error->{code} == Task::Route::TOO_MUCH_TIME())) {
+ error("$error->{message}\n");
+ }
+ });
+ $slave->processTask('move');
return unless $slave->{slave_AI} == AI::AUTO;
$slave->processAutoAttack;
}
@@ -255,50 +261,6 @@
$slave->sendMove ($pos->{x}, $pos->{y});
}
-sub slave_route {
- my $slave = shift;
- my $map = $field->baseName;
- my $x = shift;
- my $y = shift;
- my %param = @_;
- debug "Slave on route to: " .$field->descString(). ": $x, $y\n", "route";
-
- my %args;
- $x = int($x) if ($x ne "");
- $y = int($y) if ($y ne "");
- $args{'dest'}{'map'} = $map;
- $args{'dest'}{'pos'}{'x'} = $x;
- $args{'dest'}{'pos'}{'y'} = $y;
- $args{'maxRouteDistance'} = $param{maxRouteDistance} if exists $param{maxRouteDistance};
- $args{'maxRouteTime'} = $param{maxRouteTime} if exists $param{maxRouteTime};
- $args{'attackOnRoute'} = $param{attackOnRoute} if exists $param{attackOnRoute};
- $args{'distFromGoal'} = $param{distFromGoal} if exists $param{distFromGoal};
- $args{'pyDistFromGoal'} = $param{pyDistFromGoal} if exists $param{pyDistFromGoal};
- $args{'attackID'} = $param{attackID} if exists $param{attackID};
- $args{'noSitAuto'} = $param{noSitAuto} if exists $param{noSitAuto};
- $args{'noAvoidWalls'} = $param{noAvoidWalls} if exists $param{noAvoidWalls};
- $args{notifyUponArrival} = $param{notifyUponArrival} if exists $param{notifyUponArrival};
- $args{'tags'} = $param{tags} if exists $param{tags};
- $args{'time_start'} = time;
-
- if (!$param{'_internal'}) {
- $args{'solution'} = [];
- $args{'mapSolution'} = [];
- } elsif (exists $param{'_solution'}) {
- $args{'solution'} = $param{'_solution'};
- }
-
- # Destination is same map and isn't blocked by walls/water/whatever
- my $pos = calcPosition($slave);
- require Task::Route;
- if ($param{'_internal'} || (Task::Route->getRoute(\@{$args{solution}}, $field, $pos, $args{dest}{pos}, !$args{noAvoidWalls}))) {
- # Since the solution array is here, we can start in "Route Solution Ready"
- $args{'stage'} = 'Route Solution Ready';
- debug "Slave route Solution Ready\n", "route";
- $slave->queue("route", \%args);
- }
-}
-
##### ATTACK #####
sub processAttack {
my $slave = shift;
@@ -524,7 +486,7 @@
my $msg = TF("%s has no LOS from (%d, %d) to target (%d, %d)", $slave, $realMyPos->{x}, $realMyPos->{y}, $realMonsterPos->{x}, $realMonsterPos->{y});
if ($best_spot) {
message TF("%s; moving to (%s, %s)\n", $msg, $best_spot->{x}, $best_spot->{y}), 'homunculus_attack';
- $slave->slave_route($best_spot->{x}, $best_spot->{y});
+ $slave->route(undef, @{$best_spot}{qw(x y)});
} else {
warning TF("%s; no acceptable place to stand\n", $msg);
$slave->dequeue;
@@ -609,7 +571,7 @@
debug "Slave target distance $dist is >$args->{attackMethod}{maxDistance}; moving to target: " .
"from ($myPos->{x},$myPos->{y}) to ($pos->{x},$pos->{y})\n", "ai_attack";
- my $result = $slave->slave_route($pos->{x}, $pos->{y},
+ my $result = $slave->route(undef, @{$pos}{qw(x y)},
distFromGoal => $args->{attackMethod}{distance},
maxRouteTime => $config{$slave->{configPrefix}.'attackMaxRouteTime'},
attackID => $ID,
@@ -689,186 +651,6 @@
#Benchmark::end("ai_homunculus_attack") if DEBUG;
}
-####### ROUTE #######
-sub processRouteAI {
- my $slave = shift;
-
- if ($slave->action eq "route" && $slave->args->{suspended}) {
- $slave->args->{time_start} += time - $slave->args->{suspended};
- $slave->args->{time_step} += time - $slave->args->{suspended};
- delete $slave->args->{suspended};
- }
-
- if ($slave->action eq "route" && $field->baseName && $slave->{pos_to}{x} ne '' && $slave->{pos_to}{y} ne '') {
- my $args = $slave->args;
-
- if ( $args->{maxRouteTime} && timeOut($args->{time_start}, $args->{maxRouteTime})) {
- # We spent too much time
- debug "Slave route - we spent too much time; bailing out.\n", "route";
- $slave->dequeue;
-
- } elsif ($field->baseName ne $args->{dest}{map} || $args->{mapChanged}) {
- debug "Slave map changed: $field->baseName $args->{dest}{map}\n", "route";
- $slave->dequeue;
-
- } elsif ($args->{stage} eq '') {
- my $pos = calcPosition($slave);
- $args->{solution} = [];
- if (Task::Route->getRoute($args->{solution}, $field, $pos, $args->{dest}{pos})) {
- $args->{stage} = 'Route Solution Ready';
- debug "Slave route Solution Ready\n", "route";
- } else {
- debug "Something's wrong; there is no path to ".$field->baseName."($args->{dest}{pos}{x},$args->{dest}{pos}{y}).\n", "debug";
- $slave->dequeue;
- }
-
- } elsif ($args->{stage} eq 'Route Solution Ready') {
- my $solution = $args->{solution};
- if ($args->{maxRouteDistance} > 0 && $args->{maxRouteDistance} < 1) {
- # Fractional route motion
- $args->{maxRouteDistance} = int($args->{maxRouteDistance} * scalar(@{$solution}));
- }
- splice(@{$solution}, 1 + $args->{maxRouteDistance}) if $args->{maxRouteDistance} && $args->{maxRouteDistance} < @{$solution};
-
- # Trim down solution tree for pyDistFromGoal or distFromGoal
- if ($args->{pyDistFromGoal}) {
- my $trimsteps = 0;
- $trimsteps++ while ($trimsteps < @{$solution}
- && distance($solution->[@{$solution} - 1 - $trimsteps], $solution->[@{$solution} - 1]) < $args->{pyDistFromGoal}
- );
- debug "Slave route - trimming down solution by $trimsteps steps for pyDistFromGoal $args->{'pyDistFromGoal'}\n", "route";
- splice(@{$args->{'solution'}}, -$trimsteps) if ($trimsteps);
- } elsif ($args->{distFromGoal}) {
- my $trimsteps = $args->{distFromGoal};
- $trimsteps = @{$args->{'solution'}} if $trimsteps > @{$args->{'solution'}};
- debug "Slave route - trimming down solution by $trimsteps steps for distFromGoal $args->{'distFromGoal'}\n", "route";
- splice(@{$args->{solution}}, -$trimsteps) if ($trimsteps);
- }
-
- undef $args->{mapChanged};
- undef $args->{index};
- undef $args->{old_x};
- undef $args->{old_y};
- undef $args->{new_x};
- undef $args->{new_y};
- $args->{time_step} = time;
- $args->{stage} = 'Walk the Route Solution';
-
- } elsif ($args->{stage} eq 'Walk the Route Solution') {
-
- my $pos = calcPosition($slave);
- my ($cur_x, $cur_y) = ($pos->{x}, $pos->{y});
-
- unless (@{$args->{solution}}) {
- # No more points to cover; we've arrived at the destination
- if ($args->{notifyUponArrival}) {
- message TF("%s destination reached.\n", $slave), "success";
- } else {
- debug "Slave destination reached.\n", "route";
- }
- $slave->dequeue;
-
- } elsif ($args->{old_x} == $cur_x && $args->{old_y} == $cur_y && timeOut($args->{time_step}, 3)) {
- # We tried to move for 3 seconds, but we are still on the same spot,
- # decrease step size.
- # However, if $args->{index} was already 0, then that means
- # we were almost at the destination (only 1 more step is needed).
- # But we got interrupted (by auto-attack for example). Don't count that
- # as stuck.
- my $wasZero = $args->{index} == 0;
- $args->{index} = int($args->{index} * 0.8);
- if ($args->{index}) {
- debug "Slave route - not moving, decreasing step size to $args->{index}\n", "route";
- if (@{$args->{solution}}) {
- # If we still have more points to cover, walk to next point
- $args->{index} = @{$args->{solution}} - 1 if $args->{index} >= @{$args->{solution}};
- $args->{new_x} = $args->{solution}[$args->{index}]{x};
- $args->{new_y} = $args->{solution}[$args->{index}]{y};
- $args->{time_step} = time;
- $slave->move($args->{new_x}, $args->{new_y}, $args->{attackID});
- }
- } elsif (!$wasZero) {
- # We're stuck
- my $msg = TF("Slave is stuck at %s (%d,%d), while walking from (%d,%d) to (%d,%d).",
- $field->baseName, $slave->{pos_to}{x}, $slave->{pos_to}{y}, $cur_x, $cur_y, $args->{dest}{pos}{x}, $args->{dest}{pos}{y});
- $msg .= T(" Teleporting to unstuck.") if $config{$slave->{configPrefix}.'teleportAuto_unstuck'};
- $msg .= "\n";
- warning $msg, "route";
- useTeleport(1) if $config{$slave->{configPrefix}.'teleportAuto_unstuck'};
- $slave->dequeue;
- } else {
- $args->{time_step} = time;
- }
-
- } else {
- # We're either starting to move or already moving, so send out more
- # move commands periodically to keep moving and updating our position
- my $solution = $args->{solution};
- $args->{index} = $config{$slave->{configPrefix}.'route_step'} unless $args->{index};
- $args->{index}++ if ($args->{index} < $config{$slave->{configPrefix}.'route_step'});
-
- if (defined($args->{old_x}) && defined($args->{old_y})) {
- # See how far we've walked since the last move command and
- # trim down the soultion tree by this distance.
- # Only remove the last step if we reached the destination
- my $trimsteps = 0;
- # If position has changed, we must have walked at least one step
- $trimsteps++ if ($cur_x != $args->{'old_x'} || $cur_y != $args->{'old_y'});
- # Search the best matching entry for our position in the solution
- while ($trimsteps < @{$solution}
- && distance( { x => $cur_x, y => $cur_y }, $solution->[$trimsteps + 1])
- < distance( { x => $cur_x, y => $cur_y }, $solution->[$trimsteps])
- ) {
- $trimsteps++;
- }
- # Remove the last step also if we reached the destination
- $trimsteps = @{$solution} - 1 if ($trimsteps >= @{$solution});
- #$trimsteps = @{$solution} if ($trimsteps <= $args->{'index'} && $args->{'new_x'} == $cur_x && $args->{'new_y'} == $cur_y);
- $trimsteps = @{$solution} if ($cur_x == $solution->[$#{$solution}]{x} && $cur_y == $solution->[$#{$solution}]{y});
- debug "Slave route - trimming down solution (" . @{$solution} . ") by $trimsteps steps\n", "route";
- splice(@{$solution}, 0, $trimsteps) if ($trimsteps > 0);
- }
-
- my $stepsleft = @{$solution};
- if ($stepsleft > 0) {
- # If we still have more points to cover, walk to next point
- $args->{index} = $stepsleft - 1 if ($args->{index} >= $stepsleft);
- $args->{new_x} = $args->{solution}[$args->{index}]{x};
- $args->{new_y} = $args->{solution}[$args->{index}]{y};
-
- # But first, check whether the distance of the next point isn't abnormally large.
- # If it is, then we've moved to an unexpected place. This could be caused by auto-attack,
- # for example.
- my %nextPos = (x => $args->{new_x}, y => $args->{new_y});
- if (distance(\%nextPos, $pos) > $config{$slave->{configPrefix}.'route_step'}) {
- debug "Slave route - movement interrupted: reset route\n", "route";
- $args->{stage} = '';
-
- } else {
- $args->{old_x} = $cur_x;
- $args->{old_y} = $cur_y;
- $args->{time_step} = time if ($cur_x != $args->{old_x} || $cur_y != $args->{old_y});
- debug "Slave route - next step moving to ($args->{new_x}, $args->{new_y}), index $args->{index}, $stepsleft steps left\n", "route";
- $slave->move($args->{new_x}, $args->{new_y}, $args->{attackID});
- }
- } else {
- # No more points to cover
- if ($args->{notifyUponArrival}) {
- message TF("%s destination reached.\n", $slave), "success";
- } else {
- debug "Slave destination reached.\n", "route";
- }
- $slave->dequeue;
- }
- }
-
- } else {
- debug "Unexpected slave route stage [$args->{stage}] occured.\n", "route";
- $slave->dequeue;
- }
- }
-}
-
sub processClientSuspend {
my $slave = shift;
##### CLIENT SUSPEND #####
Index: Task/Move.pm
===================================================================
--- Task/Move.pm (revision 7684)
+++ Task/Move.pm (working copy)
@@ -33,10 +33,11 @@
use Task::WithSubtask;
use base qw(Task::WithSubtask);
use Task::SitStand;
-use Globals qw(%timeout $char $net $messageSender);
+use Globals qw(%timeout $net);
use Plugins;
use Network;
use Log qw(warning debug);
+use Translation qw(T TF);
use Utils qw(timeOut);
use Utils::Exceptions;
@@ -72,12 +73,11 @@
my %args = @_;
my $self = $class->SUPER::new(@_, autostop => 1, autofail => 1, mutexes => MUTEXES);
- if ($args{x} == 0 || $args{y} == 0) {
+ unless ($args{actor}->isa('Actor') and $args{x} != 0 and $args{y} != 0) {
ArgumentException->throw(error => "Invalid arguments.");
}
- $self->{x} = $args{x};
- $self->{y} = $args{y};
+ $self->{$_} = $args{$_} for qw(actor x y);
$self->{retry}{timeout} = $args{retryTime} || 0.5;
$self->{giveup}{timeout} = $args{giveupTime} || $timeout{ai_move_giveup}{timeout} || 3;
@@ -125,29 +125,29 @@
return if ($net->getState() != Network::IN_GAME);
# If we're sitting, wait until we've stood up.
- if ($char->{sitting}) {
- debug "Move - trying to stand\n", "move";
- my $task = new Task::SitStand(mode => 'stand');
+ 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 - map change detected\n", "move";
+ debug "Move $self->{actor} - map change detected\n", "move";
$self->setDone();
# Stop if we've moved.
- } elsif ($char->{time_move} > $self->{start_time}) {
- debug "Move - done\n", "move";
+ } 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 - timeout\n", "move";
- $self->setError(TOO_LONG, "Tried too long to move");
+ 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 - (re)trying\n", "move";
- $messageSender->sendMove($self->{x}, $self->{y});
+ debug "Move $self->{actor} - (re)trying\n", "move";
+ $self->{actor}->sendMove(@{$self}{qw(x y)});
$self->{retry}{time} = time;
}
}
Index: Task/CheckPoints.pm
===================================================================
--- Task/CheckPoints.pm (revision 7684)
+++ Task/CheckPoints.pm (working copy)
@@ -72,6 +72,8 @@
$self->{index} += $self->{inc};
my $task = new Task::MapRoute(
+ # FIXME
+ actor => $char,
map => $point->{map},
x => $point->{x},
y => $point->{y},
Index: Task/SitStand.pm
===================================================================
--- Task/SitStand.pm (revision 7684)
+++ Task/SitStand.pm (working copy)
@@ -23,7 +23,7 @@
use Modules 'register';
use Task;
use base qw(Task);
-use Globals qw(%timeout $char $messageSender $net);
+use Globals qw(%timeout $net);
use Network;
use Skill;
use Translation qw(T);
@@ -52,11 +52,11 @@
my %args = @_;
my $self = $class->SUPER::new(@_, mutexes => MUTEXES);
- if ($args{mode} ne 'sit' && $args{mode} ne 'stand') {
- ArgumentException->throw("No mode specified.");
+ unless ($args{actor}->isa('Actor') and $args{mode} eq 'sit' || $args{mode} eq 'stand') {
+ ArgumentException->throw("Invalid arguments.");
}
- $self->{mode} = $args{mode};
+ $self->{$_} = $args{$_} for qw(actor mode);
$self->{wait}{timeout} = $args{wait};
$self->{retry}{timeout} = $timeout{ai_stand_wait}{timeout} || 1;
# $self->{sitSkill} = new Skill(handle => 'NV_BASIC');
@@ -92,18 +92,18 @@
$self->SUPER::iterate();
return unless ($net->getState() == Network::IN_GAME);
- if (($self->{mode} eq 'stand' && !$char->{sitting}) || ($self->{mode} eq 'sit' && $char->{sitting})) {
+ unless ($self->{mode} eq 'sit' xor $self->{actor}{sitting}) {
$self->setDone();
$timeout{ai_sit}{time} = $timeout{ai_sit_wait}{time} = 0;
- } elsif ($char->getSkillLevel(new Skill(handle => 'NV_BASIC')) < 3 && ($char->{jobID} == 0 || $char->{jobID} == 161)) { # Check NV_BASIC skill only for Novice and High Novice
+ } elsif ($self->{actor}->getSkillLevel(new Skill(handle => 'NV_BASIC')) < 3 && ($self->{actor}{jobID} == 0 || $self->{actor}{jobID} == 161)) { # Check NV_BASIC skill only for Novice and High Novice
$self->setError(NO_SIT_STAND_SKILL, T("Basic Skill level 3 is required in order to sit or stand."));
} elsif (timeOut($self->{wait}) && timeOut($self->{retry})) {
if ($self->{mode} eq 'stand') {
- $messageSender->sendAction(undef, 3);
+ $self->{actor}->sendStand;
} else {
- $messageSender->sendAction(undef, 2);
+ $self->{actor}->sendSit;
}
$self->{retry}{time} = time;
}
Index: Task/UseSkill.pm
===================================================================
--- Task/UseSkill.pm (revision 7684)
+++ Task/UseSkill.pm (working copy)
@@ -88,7 +88,7 @@
my %args = @_;
my $self = $class->SUPER::new(@_, manageMutexes => 1, mutexes => ['movement', 'skill']);
- if (!$args{skill}) {
+ unless ($args{actor}->isa('Actor') and $args{skill}) {
ArgumentException->throw("No skill argument given.");
}
@@ -301,8 +301,7 @@
if (!$self->getSubtask()) {
my $task = new Task::Chained(tasks => [
# TODO: equip here (merge with AI::CoreLogic::processSkillUse)
- # TODO: pass $self->{actor} to Task::SitStand
- new Task::SitStand(mode => 'stand')
+ new Task::SitStand(actor => $self->{actor}, mode => 'stand')
]);
$self->setSubtask($task);
$self->{preparationTask} = $task;
Index: Task/FollowActor.pm
===================================================================
--- Task/FollowActor.pm (revision 7684)
+++ Task/FollowActor.pm (working copy)
@@ -134,6 +134,8 @@
if (!$self->{task}) {
my $task = $self->{task} = new Task::Route(
+ # FIXME
+ actor => $char,
x => $interceptPoint->{x},
y => $interceptPoint->{y},
maxTime => 5);
Index: Task/MapRoute.pm
===================================================================
--- Task/MapRoute.pm (revision 7684)
+++ Task/MapRoute.pm (working copy)
@@ -84,7 +84,7 @@
# TODO: do we need a mutex 'npc' too?
my $self = $class->SUPER::new(@_, autostop => 1, autofail => 0, mutexes => ['movement']);
- if (!$args{map}) {
+ unless ($args{actor}->isa('Actor') and $args{map}) {
ArgumentException->throw(error => "Invalid arguments.");
}
@@ -96,6 +96,7 @@
}
}
+ $self->{actor} = $args{actor};
($self->{dest}{map}, undef) = Field::nameToBaseName(undef, $args{map}); # Hack to clean up InstanceID
# $self->{dest}{map} = $args{map};
$self->{dest}{pos}{x} = $args{x};
@@ -129,7 +130,8 @@
sub iterate {
my ($self) = @_;
return if (!$self->SUPER::iterate() || $net->getState() != Network::IN_GAME);
- return if (!$field || !defined $char->{pos_to}{x} || !defined $char->{pos_to}{y});
+ # FIXME: don't use global $field in tasks
+ return unless defined $field && defined $self->{actor}{pos_to} && defined $self->{actor}{pos_to}{x} && defined $self->{actor}{pos_to}{y};
# When the CalcMapRouter subtask finishes, a new Route task may be set as subtask.
# In that case we don't want to continue or this MapRoute task may end prematurely.
@@ -173,13 +175,12 @@
}
}
- } elsif (distance($char->{pos_to}, $self->{mapSolution}[0]{pos}) <= 10) {
+ } elsif (distance($self->{actor}{pos_to}, $self->{mapSolution}[0]{pos}) <= 10) {
my ($from,$to) = split /=/, $self->{mapSolution}[0]{portal};
- if ($char->{zeny} >= $portals_lut{$from}{dest}{$to}{cost}) {
+ if ($self->{actor}{zeny} >= $portals_lut{$from}{dest}{$to}{cost}) {
# We have enough money for this service.
$self->{substage} = 'Waiting for Warp';
- $self->{old_x} = $char->{pos_to}{x};
- $self->{old_y} = $char->{pos_to}{y};
+ @{$self}{qw(old_x old_y)} = @{$self->{actor}{pos_to}}{qw(x y)};
$self->{old_map} = $field->baseName;
my $task = new Task::TalkNPC(
x => $self->{mapSolution}[0]{pos}{x},
@@ -198,11 +199,12 @@
debug "MapRoute - We spent too much time; bailing out.\n", "route";
$self->setError(TOO_MUCH_TIME, "Too much time spent on route traversal.");
- } elsif ( Task::Route->getRoute(\@solution, $field, $char->{pos_to}, $self->{mapSolution}[0]{pos}) ) {
+ } elsif ( Task::Route->getRoute(\@solution, $field, $self->{actor}{pos_to}, $self->{mapSolution}[0]{pos}) ) {
# NPC is reachable from current position
# >> Then "route" to it
debug "Walking towards the NPC\n", "route";
my $task = new Task::Route(
+ actor => $self->{actor},
x => $self->{mapSolution}[0]{pos}{x},
y => $self->{mapSolution}[0]{pos}{y},
maxTime => $self->{maxTime},
@@ -215,7 +217,7 @@
} else {
# Error, NPC is not reachable from current pos
debug "CRITICAL ERROR: NPC is not reachable from current location.\n", "route";
- error TF("Unable to walk from %s (%s,%s) to NPC at (%s,%s).\n", $field->baseName, $char->{pos_to}{x}, $char->{pos_to}{y}, $self->{mapSolution}[0]{pos}{x}, $self->{mapSolution}[0]{pos}{y}), "route";
+ error TF("Unable to walk from %s (%s,%s) to NPC at (%s,%s).\n", $field->baseName, @{$self->{actor}{pos_to}}{qw(x y)}, $self->{mapSolution}[0]{pos}{x}, $self->{mapSolution}[0]{pos}{y}), "route";
shift @{$self->{mapSolution}};
}
@@ -224,7 +226,7 @@
my $distFromGoal = $self->{pyDistFromGoal}
? $self->{pyDistFromGoal}
: ($self->{distFromGoal} ? $self->{distFromGoal} : 0);
- if ( $distFromGoal + 2 > distance($char->{pos_to}, $self->{mapSolution}[0]{pos})) {
+ if ( $distFromGoal + 2 > distance($self->{actor}{pos_to}, $self->{mapSolution}[0]{pos})) {
# We need to specify +2 because sometimes the exact spot is occupied by someone else
shift @{$self->{mapSolution}};
@@ -233,10 +235,11 @@
debug "We spent too much time; bailing out.\n", "route";
$self->setError(TOO_MUCH_TIME, "Too much time spent on route traversal.");
- } elsif ( Task::Route->getRoute(\@solution, $field, $char->{pos_to}, $self->{mapSolution}[0]{pos}) ) {
+ } elsif ( Task::Route->getRoute(\@solution, $field, $self->{actor}{pos_to}, $self->{mapSolution}[0]{pos}) ) {
# X,Y is reachable from current position
# >> Then "route" to it
my $task = new Task::Route(
+ actor => $self->{actor},
x => $self->{mapSolution}[0]{pos}{x},
y => $self->{mapSolution}[0]{pos}{y},
maxTime => $self->{maxTime},
@@ -249,7 +252,7 @@
} else {
warning TF("No LOS from %s (%s,%s) to Final Destination at (%s,%s).\n",
- $field->baseName, $char->{pos_to}{x}, $char->{pos_to}{y},
+ $field->baseName, @{$self->{actor}{pos_to}}{qw(x y)},
$self->{mapSolution}[0]{pos}{x},
$self->{mapSolution}[0]{pos}{y}), "route";
error TF("Cannot reach (%s,%s) from current position.\n",
@@ -261,11 +264,11 @@
} elsif ( $portals_lut{"$self->{mapSolution}[0]{map} $self->{mapSolution}[0]{pos}{x} $self->{mapSolution}[0]{pos}{y}"}{source} ) {
# This is a portal solution
- if ( distance($char->{pos_to}, $self->{mapSolution}[0]{pos}) < 2 ) {
+ if ( distance($self->{actor}{pos_to}, $self->{mapSolution}[0]{pos}) < 2 ) {
# Portal is within 'Enter Distance'
$timeout{ai_portal_wait}{timeout} = $timeout{ai_portal_wait}{timeout} || 0.5;
if ( timeOut($timeout{ai_portal_wait}) ) {
- $messageSender->sendMove(int($self->{mapSolution}[0]{'pos'}{'x'}), int($self->{mapSolution}[0]{'pos'}{'y'}) );
+ $self->{actor}->sendMove(map int, @{$self->{mapSolution}[0]{pos}}{qw(x y)});
$timeout{'ai_portal_wait'}{'time'} = time;
}
@@ -294,7 +297,7 @@
}
my $dist = new PathFinding(
- start => $char->{pos_to},
+ start => $self->{actor}{pos_to},
dest => $portal->{pos},
field => $field
)->runcount;
@@ -325,12 +328,13 @@
}
if ($walk) {
- if ( Task::Route->getRoute( \@solution, $field, $char->{pos_to}, $self->{mapSolution}[0]{pos} ) ) {
+ if ( Task::Route->getRoute( \@solution, $field, $self->{actor}{pos_to}, $self->{mapSolution}[0]{pos} ) ) {
# Portal is reachable from current position
# >> Then "route" to it
debug "Portal route within same map.\n", "route";
$self->{teleportTries} = 0;
my $task = new Task::Route(
+ actor => $self->{actor},
x => $self->{mapSolution}[0]{pos}{x},
y => $self->{mapSolution}[0]{pos}{y},
maxTime => $self->{maxTime},
@@ -341,7 +345,7 @@
} else {
warning TF("No LOS from %s (%s,%s) to Portal at (%s,%s).\n",
- $field->baseName, $char->{pos_to}{x}, $char->{pos_to}{y},
+ $field->baseName, @{$self->{actor}{pos_to}}{qw(x y)},
$self->{mapSolution}[0]{pos}{x}, $self->{mapSolution}[0]{pos}{y}),
"route";
error T("Cannot reach portal from current position\n"), "route";
@@ -356,8 +360,8 @@
my ($self) = @_;
my $task = new Task::CalcMapRoute(
sourceMap => $field->baseName,
- sourceX => $char->{pos_to}{x},
- sourceY => $char->{pos_to}{y},
+ sourceX => $self->{actor}{pos_to}{x},
+ sourceY => $self->{actor}{pos_to}{y},
map => $self->{dest}{map},
x => $self->{dest}{pos}{x},
y => $self->{dest}{pos}{y}
@@ -386,6 +390,7 @@
# to walk to.
if (@{$self->{mapSolution}} == 0 && defined($self->{dest}{pos}{x}) && defined($self->{dest}{pos}{y})) {
my $task = new Task::Route(
+ actor => $self->{actor},
x => $self->{dest}{pos}{x},
y => $self->{dest}{pos}{y},
maxTime => $self->{maxTime},
Index: Task/Route.pm
===================================================================
--- Task/Route.pm (revision 7684)
+++ Task/Route.pm (working copy)
@@ -27,7 +27,7 @@
use base qw(Task::WithSubtask);
use Task::Move;
-use Globals qw($char $field $net %config);
+use Globals qw($field $net %config);
use Log qw(message debug warning);
use Network;
use Field;
@@ -77,7 +77,7 @@
my %args = @_;
my $self = $class->SUPER::new(@_, autostop => 1, autofail => 0, mutexes => ['movement']);
- if ($args{x} == 0 || $args{y} == 0) {
+ unless ($args{actor}->isa('Actor') and $args{x} != 0 and $args{y} != 0) {
ArgumentException->throw(error => "Invalid arguments.");
}
@@ -89,10 +89,12 @@
}
}
+ $self->{actor} = $args{actor};
+ # FIXME: don't use global $field in tasks
$self->{dest}{map} = $field->baseName;
$self->{dest}{pos}{x} = $args{x};
$self->{dest}{pos}{y} = $args{y};
- if ($config{'route_avoidWalls'}) {
+ if ($config{$self->{actor}{configPrefix}.'route_avoidWalls'}) {
$self->{avoidWalls} = 1 if (!defined $self->{avoidWalls});
} else {$self->{avoidWalls} = 0;}
$self->{solution} = [];
@@ -147,11 +149,11 @@
sub iterate {
my ($self) = @_;
return unless ($self->SUPER::iterate() && $net->getState() == Network::IN_GAME);
- return unless ($field && defined($char->{pos_to}{x}) && defined($char->{pos_to}{y}));
+ return unless $field && defined $self->{actor}{pos_to} && defined $self->{actor}{pos_to}{x} && defined $self->{actor}{pos_to}{y};
if ( $self->{maxTime} && timeOut($self->{time_start}, $self->{maxTime})) {
# We spent too much time
- debug "Route - we spent too much time; bailing out.\n", "route";
+ debug "Route $self->{actor} - we spent too much time; bailing out.\n", "route";
$self->setError(TOO_MUCH_TIME, "Too much time spent on walking.");
} elsif ($field->baseName ne $self->{dest}{map} || $self->{mapChanged}) {
@@ -159,11 +161,11 @@
$self->setDone();
} elsif ($self->{stage} eq '') {
- my $pos = calcPosition($char);
+ my $pos = calcPosition($self->{actor});
my $begin = time;
if ($self->getRoute($self->{solution}, $field, $pos, $self->{dest}{pos}, $self->{avoidWalls})) {
$self->{stage} = 'Route Solution Ready';
- debug "Route Solution Ready!\n", "route";
+ debug "Route $self->{actor} Solution Ready!\n", "route";
if (time - $begin < 0.01) {
# Optimization: immediately go to the next stage if we
@@ -193,13 +195,13 @@
$trimsteps++ while ($trimsteps < @{$solution}
&& distance($solution->[@{$solution} - 1 - $trimsteps], $solution->[@{$solution} - 1]) < $self->{pyDistFromGoal}
);
- debug "Route - trimming down solution by $trimsteps steps for pyDistFromGoal $self->{pyDistFromGoal}\n", "route";
+ debug "Route $self->{actor} - trimming down solution by $trimsteps steps for pyDistFromGoal $self->{pyDistFromGoal}\n", "route";
splice(@{$self->{'solution'}}, -$trimsteps) if ($trimsteps);
} elsif ($self->{distFromGoal}) {
my $trimsteps = $self->{distFromGoal};
$trimsteps = @{$self->{solution}} if ($trimsteps > @{$self->{solution}});
- debug "Route - trimming down solution by $trimsteps steps for distFromGoal $self->{distFromGoal}\n", "route";
+ debug "Route $self->{actor} - trimming down solution by $trimsteps steps for distFromGoal $self->{distFromGoal}\n", "route";
splice(@{$self->{solution}}, -$trimsteps) if ($trimsteps);
}
@@ -219,15 +221,15 @@
}
} elsif ($self->{stage} eq 'Walk the Route Solution') {
- my $pos = calcPosition($char);
+ my $pos = calcPosition($self->{actor});
my ($cur_x, $cur_y) = ($pos->{x}, $pos->{y});
if (@{$self->{solution}} == 0) {
# No more points to cover; we've arrived at the destination
if ($self->{notifyUponArrival}) {
- message T("Destination reached.\n"), "success";
+ message TF("%s reached the destination.\n", $self->{actor}), "success";
} else {
- debug "Destination reached.\n", "route";
+ debug "$self->{actor} reached the destination.\n", "route";
}
$self->setDone();
@@ -241,7 +243,7 @@
my $wasZero = $self->{index} == 0;
$self->{index} = int($self->{index} * 0.8);
if ($self->{index}) {
- debug "Route - not moving, decreasing step size to $self->{index}\n", "route";
+ debug "Route $self->{actor} - not moving, decreasing step size to $self->{index}\n", "route";
if (@{$self->{solution}}) {
# If we still have more points to cover, walk to next point
$self->{index} = @{$self->{solution}} - 1 if $self->{index} >= @{$self->{solution}};
@@ -249,6 +251,7 @@
$self->{new_y} = $self->{solution}[$self->{index}]{y};
$self->{time_step} = time;
my $task = new Task::Move(
+ actor => $self->{actor},
x => $self->{new_x},
y => $self->{new_y});
$self->setSubtask($task);
@@ -258,12 +261,12 @@
# FIXME: this code looks ugly!
# We're stuck
my $msg = TF("Stuck at %s (%d,%d), while walking from (%d,%d) to (%d,%d).",
- $field->baseName, $char->{pos_to}{x}, $char->{pos_to}{y},
+ $field->baseName, @{$self->{actor}{pos_to}}{qw(x y)},
$cur_x, $cur_y, $self->{dest}{pos}{x}, $self->{dest}{pos}{y});
- $msg .= T(" Teleporting to unstuck.") if ($config{teleportAuto_unstuck});
+ $msg .= T(" Teleporting to unstuck.") if ($config{$self->{actor}{configPrefix}.'teleportAuto_unstuck'});
$msg .= "\n";
warning $msg, "route";
- Misc::useTeleport(1) if $config{teleportAuto_unstuck};
+ Misc::useTeleport(1) if $config{$self->{actor}{configPrefix}.'teleportAuto_unstuck'};
$self->setError(STUCK, T("Stuck during route."));
} else {
$self->{time_step} = time;
@@ -274,8 +277,8 @@
# move commands periodically to keep moving and updating our position
my $begin = time;
my $solution = $self->{solution};
- $self->{index} = $config{route_step} unless $self->{index};
- $self->{index}++ if (($self->{index} < $config{route_step})
+ $self->{index} = $config{$self->{actor}{configPrefix}.'route_step'} unless $self->{index};
+ $self->{index}++ if (($self->{index} < $config{$self->{actor}{configPrefix}.'route_step'})
&& ($self->{old_x} != $cur_x || $self->{old_y} != $cur_y));
if (defined($self->{old_x}) && defined($self->{old_y})) {
@@ -296,7 +299,7 @@
$trimsteps = @{$solution} - 1 if ($trimsteps >= @{$solution});
#$trimsteps = @{$solution} if ($trimsteps <= $self->{'index'} && $self->{'new_x'} == $cur_x && $self->{'new_y'} == $cur_y);
$trimsteps = @{$solution} if ($cur_x == $solution->[$#{$solution}]{x} && $cur_y == $solution->[$#{$solution}]{y});
- debug "Route - trimming down solution (" . @{$solution} . ") by $trimsteps steps\n", "route";
+ debug "Route $self->{actor} - trimming down solution (" . @{$solution} . ") by $trimsteps steps\n", "route";
splice(@{$solution}, 0, $trimsteps) if ($trimsteps > 0);
}
@@ -311,16 +314,17 @@
# If it is, then we've moved to an unexpected place. This could be caused by auto-attack,
# for example.
my %nextPos = (x => $self->{new_x}, y => $self->{new_y});
- if (distance(\%nextPos, $pos) > $config{route_step}) {
- debug "Route - movement interrupted: reset route\n", "route";
+ if (distance(\%nextPos, $pos) > $config{$self->{actor}{configPrefix}.'route_step'}) {
+ debug "Route $self->{actor} - movement interrupted: reset route\n", "route";
$self->{stage} = '';
} else {
$self->{old_x} = $cur_x;
$self->{old_y} = $cur_y;
$self->{time_step} = time if ($cur_x != $self->{old_x} || $cur_y != $self->{old_y});
- debug "Route - next step moving to ($self->{new_x}, $self->{new_y}), index $self->{index}, $stepsleft steps left\n", "route";
+ debug "Route $self->{actor} - next step moving to ($self->{new_x}, $self->{new_y}), index $self->{index}, $stepsleft steps left\n", "route";
my $task = new Task::Move(
+ actor => $self->{actor},
x => $self->{new_x},
y => $self->{new_y});
$self->setSubtask($task);
@@ -334,9 +338,9 @@
} else {
# No more points to cover
if ($self->{notifyUponArrival}) {
- message T("Destination reached.\n"), "success";
+ message TF("%s reached the destination.\n", $self->{actor}), "success";
} else {
- debug "Destination reached.\n", "route";
+ debug "$self->{actor} reached the destination.\n", "route";
}
$self->setDone();
}
Index: AI.pm
===================================================================
--- AI.pm (revision 7684)
+++ AI.pm (working copy)
@@ -475,41 +475,8 @@
AI::queue("items_take", \%args);
}
-sub ai_route {
- my $map = shift;
- my $x = shift;
- my $y = shift;
- my %args = @_;
- debug "On route to: $maps_lut{$map.'.rsw'}($map): $x, $y\n", "route";
+sub ai_route { $char->route(@_) }
- # I can't use 'use' because of circular dependencies.
- require Task::Route;
- require Task::MapRoute;
-
- my $task;
- my @params = (
- x => $x,
- y => $y,
- maxDistance => $args{maxRouteDistance},
- maxTime => $args{maxRouteTime},
- distFromGoal => $args{distFromGoal},
- pyDistFromGoal => $args{pyDistFromGoal},
- avoidWalls => !$args{noAvoidWalls},
- notifyUponArrival => $args{notifyUponArrival}
- );
- if ($args{noMapRoute} || !defined($map)) {
- $task = new Task::Route(@params);
- } else {
- $task = new Task::MapRoute(map => $map, @params);
- }
- $task->{attackID} = $args{attackID};
- $task->{attackOnRoute} = $args{attackOnRoute};
- $task->{noSitAuto} = $args{noSitAuto};
- $task->{LOSSubRoute} = $args{LOSSubRoute};
-
- AI::queue("route", $task);
-}
-
#sellAuto for items_control - chobit andy 20030210
sub ai_sellAutoCheck {
foreach my $item (@{$char->inventory->getItems()}) {
@@ -680,11 +647,9 @@
debug "Targeting for Gather: $items{$ID}{name} ($items{$ID}{binID})\n";
}
-sub move { $char->move(@_) }
-
sub sit {
require Task::SitStand;
- my $task = new Task::SitStand(mode => 'sit', wait => $timeout{ai_sit_wait}{timeout});
+ my $task = new Task::SitStand(actor => $char, mode => 'sit', wait => $timeout{ai_sit_wait}{timeout});
AI::queue("sitting", $task);
if (defined $config{sitAuto_look} && !$config{sitAuto_look_from_wall}) {
Misc::look($config{sitAuto_look});
@@ -712,7 +677,7 @@
sub stand {
require Task::SitStand;
- my $task = new Task::SitStand(mode => 'stand', wait => $timeout{ai_stand_wait}{timeout});
+ my $task = new Task::SitStand(actor => $char, mode => 'stand', wait => $timeout{ai_stand_wait}{timeout});
AI::queue("standing", $task);
}
Index: Actor/You.pm
===================================================================
--- Actor/You.pm (revision 7684)
+++ Actor/You.pm (working copy)
@@ -356,6 +356,8 @@
$messageSender->sendMove(@{Utils::calcPosition($self)}{qw(x y)});
}
+sub sendSit { $messageSender->sendAction(undef, 2) }
+sub sendStand { $messageSender->sendAction(undef, 3) }
sub sendMove { $messageSender->sendMove(@_[1, 2]) }
1;