Not perfect, we should use random "dist from target". With an additional option of manually setting distance when creating the task, the routing part from autostorage and autosell routines will become obsolete.
Should make talknpc less prone to errors and make macros easier to write, with less "do move".
talknpc should also have an option to specify NPC by it's index or regex search with a warning for multiple matches.
Please, test even if you're not a dev!
Code: Select all
Index: AI.pm
===================================================================
--- AI.pm (revision 8828)
+++ AI.pm (working copy)
@@ -630,7 +630,7 @@
# Talks to an NPC.
sub ai_talkNPC {
require Task::TalkNPC;
- AI::queue("NPC", new Task::TalkNPC(x => $_[0], y => $_[1], sequence => $_[2]));
+ AI::queue("NPC", new Task::TalkNPC(map => $_[0], x => $_[1], y => $_[2], sequence => $_[3]));
}
sub attack { $char->attack(@_) }
Index: AI/CoreLogic.pm
===================================================================
--- AI/CoreLogic.pm (revision 8830)
+++ AI/CoreLogic.pm (working copy)
@@ -1207,7 +1207,7 @@
error T("Something is wrong with storageAuto_npc_type in your config.\n");
}
- ai_talkNPC($args->{npc}{pos}{x}, $args->{npc}{pos}{y}, $config{'storageAuto_npc_steps'});
+ ai_talkNPC($field->baseName, $args->{npc}{pos}{x}, $args->{npc}{pos}{y}, $config{'storageAuto_npc_steps'});
}
delete $ai_v{temp}{storage_opened};
@@ -1492,7 +1492,7 @@
my $realpos = {};
getNPCInfo($config{"sellAuto_npc"}, $realpos);
- ai_talkNPC($realpos->{pos}{x}, $realpos->{pos}{y}, $config{sellAuto_npc_steps} || 's e');
+ ai_talkNPC($field->baseName, $realpos->{pos}{x}, $realpos->{pos}{y}, $config{sellAuto_npc_steps} || 's e');
return;
}
@@ -1708,7 +1708,7 @@
my $realpos = {};
getNPCInfo($config{"buyAuto_$args->{index}"."_npc"}, $realpos);
- ai_talkNPC($realpos->{pos}{x}, $realpos->{pos}{y}, $config{"buyAuto_$args->{index}"."_npc_steps"} || 'b e');
+ ai_talkNPC($field->baseName, $realpos->{pos}{x}, $realpos->{pos}{y}, $config{"buyAuto_$args->{index}"."_npc_steps"} || 'b e');
return;
}
Index: Commands.pm
===================================================================
--- Commands.pm (revision 8828)
+++ Commands.pm (working copy)
@@ -4785,16 +4785,24 @@
sub cmdTalkNPC {
my (undef, $args) = @_;
-
- my ($x, $y, $sequence) = $args =~ /^(\d+) (\d+) (.+)$/;
- unless (defined $x) {
+ my ($map, $x, $y, $sequence);
+ if ($args =~ /^(\S+) (\d+) (\d+) (.+)$/) {
+ ($map, $x, $y, $sequence) = $args =~ /^(\S+) (\d+) (\d+) (.+)$/;
+ message TF("Talking to NPC at (%s %d, %d) using sequence: %s\n", $map, $x, $y, $sequence);
+ } elsif ($args =~ /^(\d+) (\d+) (\S+) (.+)$/) {
+ ($x, $y, $map, $sequence) = $args =~ /^(\d+) (\d+) (\S+) (.+)$/;
+ message TF("Talking to NPC at (%s %d, %d) using sequence: %s\n", $map, $x, $y, $sequence);
+ } elsif ($args =~ /^(\d+) (\d+) (.+)$/) {
+ ($x, $y, $sequence) = $args =~ /^(\d+) (\d+) (.+)$/;
+ $map = $field->baseName;
+ message TF("Talking to NPC at (%d, %d) using sequence: %s\n", $x, $y, $sequence);
+ } else {
error T("Syntax Error in function 'talknpc' (Talk to an NPC)\n" .
- "Usage: talknpc <x> <y> <sequence>\n");
+ "Usage: talknpc [<map>] <x> <y> <sequence>\n");
return;
}
-
- message TF("Talking to NPC at (%d, %d) using sequence: %s\n", $x, $y, $sequence);
- main::ai_talkNPC($x, $y, $sequence);
+ # TODO: validate received map arg
+ main::ai_talkNPC($map, $x, $y, $sequence);
}
sub cmdTank {
Index: Task/MapRoute.pm
===================================================================
--- Task/MapRoute.pm (revision 8833)
+++ Task/MapRoute.pm (working copy)
@@ -183,6 +183,7 @@
@{$self}{qw(old_x old_y)} = @{$self->{actor}{pos_to}}{qw(x y)};
$self->{old_map} = $field->baseName;
my $task = new Task::TalkNPC(
+ map => $field->baseName,
x => $self->{mapSolution}[0]{pos}{x},
y => $self->{mapSolution}[0]{pos}{y},
sequence => $self->{mapSolution}[0]{steps});
Index: Task/TalkNPC.pm
===================================================================
--- Task/TalkNPC.pm (revision 8832)
+++ Task/TalkNPC.pm (working copy)
@@ -21,7 +21,7 @@
use Modules 'register';
use Task;
use base qw(Task);
-use Globals qw($char %timeout $npcsList $monstersList %ai_v $messageSender %config @storeList $net %talk);
+use Globals qw($char %timeout $npcsList $monstersList %ai_v $messageSender %config @storeList $net %talk $field);
use Log qw(message debug error);
use Utils;
use Commands;
@@ -69,8 +69,9 @@
my %args = @_;
my $self = $class->SUPER::new(@_, mutexes => MUTEXES);
- $self->{x} = $args{x};
- $self->{y} = $args{y};
+ $self->{map} = $args{map};
+ $self->{npc}{pos}{x} = $args{x};
+ $self->{npc}{pos}{y} = $args{y};
$self->{sequence} = $args{sequence};
$self->{sequence} =~ s/^ +| +$//g;
@@ -93,7 +94,7 @@
my ($self) = @_;
$self->SUPER::activate(); # Do not forget to call this!
$self->{time} = time;
- $self->{stage} = 'Not Started';
+ $self->{stage} = 'Route';
$self->{mapChanged} = 0;
}
@@ -102,9 +103,20 @@
my ($self) = @_;
$self->SUPER::iterate(); # Do not forget to call this!
return unless ($net->getState() == Network::IN_GAME);
+ my $npcpos = (x => $self->{x}, y => $self->{y});
+
+
my $timeResponse = ($config{npcTimeResponse} >= 5) ? $config{npcTimeResponse}:5;
- if ($self->{stage} eq 'Not Started') {
+ if ($self->{stage} eq 'Route') {
+ $char->route ($self->{map}, $self->{npc}{pos}{x}, $self->{npc}{pos}{y},
+ attackOnRoute => 1,
+ distFromGoal => 9);
+
+ if (($field->baseName eq $self->{map}) && (distance($self->{npc}{pos}, $char->{pos_to}) < 10)) {
+ $self->{stage} = 'Not Started';
+ }
+ } elsif ($self->{stage} eq 'Not Started') {
if (!timeOut($char->{time_move}, $char->{time_move_calc} + 0.2)) {
# Wait for us to stop moving before talking.
return;
@@ -111,7 +123,7 @@
} elsif (timeOut($self->{time}, $timeResponse)) {
$self->setError(NPC_NOT_FOUND, TF("Could not find an NPC at location (%d,%d).",
- $self->{x}, $self->{y}));
+ $self->{npc}{pos}{x}, $self->{npc}{pos}{y}));
} else {
my $target = $self->findTarget($npcsList);
@@ -319,7 +331,7 @@
my ($self, $actorList) = @_;
foreach my $actor (@{$actorList->getItems()}) {
my $pos = ($actor->isa('Actor::NPC')) ? $actor->{pos} : $actor->{pos_to};
- if ($pos->{x} == $self->{x} && $pos->{y} == $self->{y}) {
+ if ($pos->{x} == $self->{npc}{pos}{x} && $pos->{y} == $self->{npc}{pos}{y}) {
if (defined $actor->{name}) {
return $actor;
} else {