Task::TalkNPC, moving to the NPC if not near

Wrote new code? Fixed a bug? Want to discuss technical stuff? Feel free to post it here.

Moderator: Moderators

Message
Author
iMikeLance
Moderators
Moderators
Posts: 208
Joined: 01 Feb 2010, 17:37
Noob?: No
Location: Brazil - MG
Contact:

Task::TalkNPC, moving to the NPC if not near

#1 Post by iMikeLance »

As requested here: http://www.openkore.com/index.php/Talknpc

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 {


sofax222
Developers
Developers
Posts: 214
Joined: 24 Nov 2010, 03:08
Noob?: Yes

Re: Task::TalkNPC, moving to the NPC if not near

#2 Post by sofax222 »

The "sub cmdTalkNPC" in Commands.pm.
Sometimes, the

Code: Select all

} elsif ($args =~ /^(\d+) (\d+) (\S+) (.+)$/) {
will conflict with

Code: Select all

} elsif ($args =~ /^(\d+) (\d+) (.+)$/) {
...
So, I think the

Code: Select all

} elsif ($args =~ /^(\d+) (\d+) (\S+) (.+)$/) {
should be changed to{

Code: Select all

} elsif ($args =~ /^(\d+) (\d+) (\w{3,}) (.+)$/) {

sofax222
Developers
Developers
Posts: 214
Joined: 24 Nov 2010, 03:08
Noob?: Yes

Re: Task::TalkNPC, moving to the NPC if not near

#3 Post by sofax222 »

In the Task/TalkNPC.pm,
The code lines

Code: Select all

	if (($field->baseName eq $self->{map}) && (distance($self->{npc}{pos}, $char->{pos_to}) < 10)) {
		$self->{stage} = 'Not Started';
	}
should be changed to

Code: Select all

	if (($field->baseName eq $self->{map}) && (distance($self->{npc}{pos}, $char->{pos_to}) < 10)) {
		$self->{stage} = 'Not Started';
		$self->{time} = time;
	}
It should be reset the time !!

Post Reply