reactOnNPC v.2.0.2 by hakore

Other plugins for extending OpenKore's functionality. This forum is only for posting new plugins and commenting on existing plugins. For support, use the Support forum.

Moderator: Moderators

Message
Author
GSMikami
Noob
Noob
Posts: 4
Joined: 25 May 2008, 18:56
Noob?: Yes

Re: reactOnNPC v.1.1.1 by hakore

#101 Post by GSMikami »

Hello I' m trying to make a bot completing the training ground but when we just spawn in the game, we have to talk to a NPC who ask us a few questions, for a same question, the responses can change places.

[reactOnNPC] NPC message saved (0): "[Valkyrie]".
Valkyrie#nub: [Valkyrie]
[reactOnNPC] NPC message saved (1): "^0000FFCan you tell me which one is the 10th month of the year?^000000 ".
Valkyrie#nub: Can you tell me which one is the 10th month of the year?
[reactOnNPC] onNPCAction type is: continue.
[reactOnNPC] Conditions for reactOnNPC_0 not met.
Valkyrie#nub: Auto-continuing talking
[reactOnNPC] onNPCAction type is: responses.
[reactOnNPC] Matching "[Valkyrie]" to "[Valkyrie]" (0)... ok.
[reactOnNPC] Matching "Can you tell me which one is the 10th month of the year? " to "Can you tell me which one is the 10th month of the year?" (1)... doesn't match.
[reactOnNPC] One or more lines doesn't match for "reactOnNPC_0" (1).
----------Responses-----------
# Response
0 July
1 August
2 December
3 March
4 October
5 Cancel Chat
-------------------------------
Valkyrie#nub: Type 'talk resp #' to choose a response.
[reactOnNPC] onNPCAction type is: close.
[reactOnNPC] Conditions for reactOnNPC_0 not met.
Valkyrie#nub: Done talking


It seems they putted a space after the "?", I also tried to add a space in my config.txt just after my msg_1, but the plugin don' t take consideration of the space I added. Or maybe it' s the ^0000FF & ^000000 they added before & after the question?

With the debug I can see:

MSG_0 matchs
MSG_1 doesn' t match just because of a space?

reactOnNPC talk resp @resp(October) {
type responses
msg_0 [Valkyrie]
msg_1 Can you tell me which one is the 10th month of the year?
}


It isn' t triggered because of msg_1 not matching... How to solve this space problem?

Thank you for your light.

hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: reactOnNPC v.1.1.1 by hakore

#102 Post by hakore »

Try this:

Code: Select all

reactOnNPC talk resp @resp(/October/) {
	type responses
	msg_0 /^\[Valkyrie\]/
	msg_1 /^Can you tell me which one is the 10th month of the year\?/
}
Whatever...

GSMikami
Noob
Noob
Posts: 4
Joined: 25 May 2008, 18:56
Noob?: Yes

Re: reactOnNPC v.1.1.1 by hakore

#103 Post by GSMikami »

[reactOnNPC] onNPCAction type is: responses.
[reactOnNPC] Matching "[Valkyrie]" to "/^\[Valkyrie\]/" (0)... regexp ok.
[reactOnNPC] Matching "Can you tell me which one is the 10th month of the year? " to "/^Can you tell me which one is the 10th month of the year?\?/" (1)... regexp ok.
[reactOnNPC] Matching "March" to "/October/" ()... doesn't match.
[reactOnNPC] Matching "December" to "/October/" ()... doesn't match.
[reactOnNPC] Matching "July" to "/October/" ()... doesn't match.
[reactOnNPC] Matching "September" to "/October/" ()... doesn't match.
[reactOnNPC] Matching "October" to "/October/" ()... regexp ok.
[reactOnNPC] Reacting to NPC. Executing command "talk resp 4".
Error in function 'talk resp' (Respond to NPC)
Response 4 does not exist.

----------Responses-----------
# Response
0 March
1 December
2 July
3 September
4 October
5 Cancel Chat
-------------------------------
Valkyrie#nub: Type 'talk resp #' to choose a response.


Thank you hakore, now the reactonNPC is triggered but as you can see, it bugged when it executed the command "talk resp"
Maybe the command is running too early before the reponses choice? I didn' t see we can pause a moment before "talk resp" in the reactonNPC manual.

How to redeem?

Thank you for your light, sir.

hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: reactOnNPC v.1.1.1 by hakore

#104 Post by hakore »

You are right. I know about this issue some months ago. I'll try to work on it and update the plugin.

As a temporary solution, you can simply make a macro (see Macro Plugin) that pauses for a while before executing the command.

in config.txt, add:

Code: Select all

alias_npc_react
reactOnNPC conf alias_npc_react talk resp @resp(/October/);; macro delayed_npc_react {
   type responses
   msg_0 /^\[Valkyrie\]/
   msg_1 /^Can you tell me which one is the 10th month of the year\?/
}
macros.txt:

Code: Select all

macro delayed_npc_react {
	pause 3
	do npc_react
}
Whatever...

Mucilon
Cybernatic Entity
Cybernatic Entity
Posts: 249
Joined: 04 Apr 2008, 13:15
Noob?: Yes
Location: Brazil

Re: reactOnNPC v.1.1.1 by hakore

#105 Post by Mucilon »

hakore
I did this code some time ago to fix it, but don't remember why I didn't post it!
Normally it happens when there is a huge lag on the server...
This is a timeout code to the plugin, it must be inputed exactly before the line: Commands::run($cmd);
Like above:

Code: Select all

			#timeout code
			my $timeToWait = 5 + rand(10);
			message "[reactOnNPC] Answering to NPC: \"$cmd\" on $timeToWait seconds.\n", "success";
			my $currentTime = time;
			my $bool = 1;
			while ($bool) {
			  if (Utils::timeOut($currentTime,$timeToWait)) {
				 message "[reactOnNPC] I waited $timeToWait seconds...\n", "reactOnNPC";
				 $bool = 0;
			   }
			}
			Commands::run($cmd);

hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: reactOnNPC v.1.1.1 by hakore

#106 Post by hakore »

Yaiks... that's not the proper way to do it. X_X

If the wait time is small, maybe it could pass for a workaround, but the problem with that code is - it generally stops everything, AI and all, until you finally do the command.

The correct way is to store the command in a buffer which will be regularly checked by the plugin to see whether a certain amount of time has already elapsed since that command was queued. If enough time has passed, the command will be executed, otherwise, AI will resume and the command queue will be checked again on the next loop.

Such logic is used by the old reactOnKillSteal plugin (see the old forums), and the same system is roughly what drives the macro engine.
Whatever...

Mucilon
Cybernatic Entity
Cybernatic Entity
Posts: 249
Joined: 04 Apr 2008, 13:15
Noob?: Yes
Location: Brazil

Re: reactOnNPC v.1.1.1 by hakore

#107 Post by Mucilon »

I know that, I copied that code from the reactOnKillSteal plugin... and I think you are right, but I left it like this for 3 reasons:
- It was one of the firsts codes I changed...
- It work!
- And besides it stops everything, when you are reacting to a NPC (antibot), your char is frozen, so you won't do nothing anyway! So if the AI is stopped or not, won't make any difference.

A couple of months later I made a loopless timeout code on the kadiliman plugin, but not using the AI queue.

hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: reactOnNPC v.1.1.1 by hakore

#108 Post by hakore »

You got a point, anti-bot NPCs usually freeze you while talking to it. But like I said, that method stops everything, not only AI, but all Kore functions. There's a danger of getting out of sync if the delay was set high.

Anyways, I found the bug why the reaction was performed before the responses are "received". Apparently, the backward compatibility code for version 1.6 is screwed on Openkore SVN since the VERSION in SVN is not in the standard version format (e.g. 2.0.6). Therefore, the plugin uses the code for v.1.6.x instead of the new code. I have to remove that compatibility code now.

This is the new reactOnNPC source code (v.2.0.0). Simply added a "delay" attribute on the reactOnNPC block which will postpone execution of the command for the specified number of seconds. And I haven't edited the first post yet since this needs some testing first.

Code: Select all

# =======================
# reactOnNPC v.2.0.0
# =======================
# This plugin is licensed under the GNU GPL
# Copyright 2006 by hakore
#
# http://forums.openkore.com/viewtopic.php?f=34&t=198

package reactOnNPC;

use strict;
use Plugins;
use Globals;
use Utils;
use Commands;
use Log qw(message debug);

Plugins::register('reactOnNPC', "react on NPC messages", \&Unload);

my $hooks = (
	Plugins::addHooks(
            ['packet/npc_talk', \&onNPCTalk, undef],
            ['packet/npc_talk_close', \&onNPCAction, undef],
            ['packet/npc_talk_continue', \&onNPCAction, undef],
            ['packet/npc_talk_number', \&onNPCAction, undef],
            ['packet/npc_talk_responses', \&onNPCAction, undef],
            ['packet/npc_talk_text', \&onNPCAction, undef],
            ['mainLoop_pre', \&onCheckCmd, undef]
	)
);

my %reactOnNPC;
my @reactOnNPC;

sub Unload
{
	Plugins::delHooks($hooks);
};

sub onNPCTalk
{
	my (undef, $args) = @_;
	my $ID = unpack("V", substr($args->{RAW_MSG}, 4, 4));
	my $msg = unpack("Z*", substr($args->{RAW_MSG}, 8));

	$msg = I18N::bytesToString($msg);

	if (!defined %reactOnNPC || $reactOnNPC{action})
	{
		undef %reactOnNPC if defined %reactOnNPC;
		$reactOnNPC{index} = 0;
		$reactOnNPC{ID} = $ID;
		$reactOnNPC{msg}[$reactOnNPC{index}] = $msg;
	}
	else
	{
		$reactOnNPC{index}++;
		$reactOnNPC{msg}[$reactOnNPC{index}] = $msg;
	}
	debug "[reactOnNPC] NPC message saved ($reactOnNPC{index}): \"$msg\".\n", "reactOnNPC";
}

sub onNPCAction
{
	my $type = substr(shift, 16);
	$reactOnNPC{action} = $type;
	debug "[reactOnNPC] onNPCAction type is: $type.\n", "reactOnNPC";

	if ($type eq 'responses')
	{
		my $args = shift;
		my $msg = unpack("Z*", substr($args->{RAW_MSG}, 8));

		$msg = I18N::bytesToString($msg);

		undef @{$reactOnNPC{responses}};
		my @responses = split /:/, $msg;
		foreach (@responses) {
			push @{$reactOnNPC{responses}}, $_ if $_ ne "";
		}
	}
	
	my $i = 0;
	while (exists $config{"reactOnNPC_$i"}) {
		if (
			!$config{"reactOnNPC_$i"}
			|| !main::checkSelfCondition("reactOnNPC_$i")
			|| ($config{"reactOnNPC_${i}_type"} && $config{"reactOnNPC_${i}_type"} ne $type)
		) {
			debug "[reactOnNPC] Conditions for reactOnNPC_$i not met.\n", "reactOnNPC";
			$i++;
			next;
		}
		my $j = 0;
		my $ok = 1;
		while (exists $config{"reactOnNPC_${i}_msg_$j"})
		{
			my $msg;
			if (exists $reactOnNPC{msg}[$j])
			{
				$msg = $reactOnNPC{msg}[$j];
				# Remove RO color codes
				$msg =~ s/\^[a-fA-F0-9]{6}//g unless ($config{"reactOnNPC_${i}_useColors"});
			}

			if (!defined $msg || !match($j, $msg, $config{"reactOnNPC_${i}_msg_$j"}))
			{
				debug "[reactOnNPC] One or more lines doesn't match for \"reactOnNPC_$i\" ($j).\n", "reactOnNPC";
				$ok = 0;
				last;
			}
			$j++;
		}

		if ($ok)
		{
			my $cmd = $config{"reactOnNPC_$i"};
			$cmd =~ s/#(\d+)~(\d+)/$reactOnNPC{match}[$1][$2]/g;
			my $kws = 'eval|resp';
			while (my ($kw, $expr) = $cmd =~ /\@($kws)\(((?:(?!(?<!\@)\@$kws\().)+?)(?<!\@)\)/)
			{
				my $eval;
				my $eval_expr = $expr;
				$eval_expr =~ s/\@(?=[\@)])//g;
				if ($kw eq 'eval')
				{
					$eval = eval $eval_expr;
				}
				elsif ($kw eq 'resp')
				{
					$i = 0;
					foreach (@{$reactOnNPC{responses}}) {
						if (match(undef, $_, $eval_expr))
						{
							last;
						}
						$i++;
					}
					$eval = $i;
				}
				$expr = quotemeta $expr;
				$cmd =~ s/\@$kw\($expr\)/$eval/g;
			}
			if (my $delay = $config{"reactOnNPC_${i}_delay"})
			{
				my $params = {
					cmd => $cmd,
					time => time,
					timeout => $delay
				};
				debug "[reactOnNPC] React to NPC with delay. Execute command \"$cmd\" after $delay seconds.\n", "success";
				push @reactOnNPC, $params;
			}
			else
			{
				message "[reactOnNPC] Reacting to NPC. Executing command \"$cmd\".\n", "success";
				Commands::run($cmd);
			}
			last;
		}
		$i++;
	}
	undef %reactOnNPC if $type eq 'close';
}

sub onCheckCmd
{
	for (my $i = 0; $i < @reactOnNPC; $i++)
	{
		my $args = $reactOnNPC[$i];
		if (timeOut($args->{time}, $args->{timeout}))
		{
			message "[reactOnNPC] Reacting to NPC. Executing command \"".$args->{cmd}."\".\n", "success";
			Commands::run($args->{cmd});
		}
	}
}

sub match
{
	my ($line, $subject, $pattern) = @_;
	
	debug "[reactOnNPC] Matching \"$subject\" to \"$pattern\" ($line)... ", "reactOnNPC";
	if (my ($re, $ci) = $pattern =~ /^\/(.+?)\/(i?)$/)
	{
		if (($ci && $subject =~ /$re/i) || (!$ci && $subject =~ /$re/))
		{
			if (defined $line)
			{
				no strict;
				foreach my $index (1..$#-)
				{
					$reactOnNPC{match}[$line][$index] = ${$index};
				}
			}
			debug "regexp ok.\n", "reactOnNPC";
			return 1;
		}
	}
	elsif ($subject eq $pattern)
	{
		debug "ok.\n", "reactOnNPC";
		return 1;
	}
	debug "doesn't match.\n", "reactOnNPC";
}

return 1;
BTW, Mucilon, I read that you found a bug regarding the nesting of @eval and @resp substitution keywords? I can't seem to see such bug. When does it occur?
Whatever...

Mucilon
Cybernatic Entity
Cybernatic Entity
Posts: 249
Joined: 04 Apr 2008, 13:15
Noob?: Yes
Location: Brazil

Re: reactOnNPC v.1.1.1 by hakore

#109 Post by Mucilon »

Yep, I did find this bug, but at the time I didn't know perl... about 1,5 years ago.
I was trying to bot at a Brazilian server named RagnaBR and it used the kind of antibot where you must response a number related to a text which represents a number, like this:

Code: Select all

Unknown #110043755: [Autentication]
Unknown #110043755: Type using the menu:
Unknown #110043755: Type: 4 5 6
Unknown #110043755: Code: _ _ _ .
Unknown #110043755: Tried 1 of 3
Unknown #110043755: You still have 120 seconds.
Existe um NPC: Unknown #110043755 (129, 126) (ID 110043755) - (0)
----------Answers-----------
# Answer
0 ô.Né or Š*ïX
1 f[Îvè or š+.ê'.Vë N
2 n.ì*nË or Z.êR Ò
3 f.õú+R or *t+hr..ëé
4 t-W.ô or Ë.Îg.hT
5 Cancel Chat
And I had to use this kind of code (the numbers are in Portuguese):

Code: Select all

reactOnNPC talk resp @resp(@@eval(
my $test = #2~1;
return ('/[zž].?.?[eêéèë3].?.?r.?.?[oôóòöõø0]/i'@) if($test == 0@);
return ('/[uûúùü].?.?m/i'@) if ($test == 1@); 
return ('/[dÐ].?.?[oôóòöõø0].?.?[iîíì\|1].?.?[sš\$]/i'@) if ($test == 2@); 
return ('/[t†].?.?r.?.?[eêéèë3].?.?[sš\$]/i'@) if ($test == 3@); 
return ('/q.?.?[uûúùü].?.?[aâáàäãåª].?.?[t†].?.?r.?.?[oôóòöõø0]/i'@) if ($test == 4@); 
return ('/[c¢ç].?.?[iîíì\|1].?.?[nñ].?.?[c¢ç].?.?[oôóòöõø0]/i'@) if ($test == 5@); 
return ('/[sš\$].?.?[eêéèë3].?.?[iîíì\|1].?.?[sš\$]/i'@) if ($test == 6@); 
return ('/[sš\$].?.?[eêéèë3].?.?[t†].?.?[eêéèë3]/i'@) if ($test == 7@); 
return ('/[oôóòöõø0].?.?[iîíì\|1].?.?[t†].?.?[oôóòöõø0]/i'@) if ($test == 8@); 
return ('/[nñ].?.?[oôóòöõø0].?.?v.?.?[eêéèë3]/i'@) if ($test == 9@);@)) {
	type responses
	msg_0 [Autentication]
	msg_1 Type using the Menu:
	msg_2 /Type:\s(\d)\s(\d)\s(\d)$/
	msg_3 /Code: _ _ _ \.$/
}
With this code, the plugin just don't return a answer, I used a lot of 'message' commands to see what the plugin was generating at the middle of your code, and I change it to only execute nesting commands, so I could use it on this server. After this I never look it back to try to make it generic...

[The extension pl has been deactivated and can no longer be displayed.]


hakore
Super Moderators
Super Moderators
Posts: 200
Joined: 16 May 2008, 08:28
Noob?: No
Contact:

Re: reactOnNPC v.1.1.1 by hakore

#110 Post by hakore »

Thanks Mucilon. It's probably the regexp. I'll look in to that when I got the time.

Meanwhile, can you test the new version and release it on the first post when there are no problems?
Whatever...

Post Reply