reactOnNPC v.2.0.2 by hakore
Moderator: Moderators
Re: reactOnNPC v.1.1.1 by hakore
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.
[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.
Re: reactOnNPC v.1.1.1 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...
Re: reactOnNPC v.1.1.1 by hakore
[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.
[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.
Re: reactOnNPC v.1.1.1 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:
macros.txt:
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\?/
}
Code: Select all
macro delayed_npc_react {
pause 3
do npc_react
}
Whatever...
Re: reactOnNPC v.1.1.1 by hakore
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:
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);
Re: reactOnNPC v.1.1.1 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.
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...
Re: reactOnNPC v.1.1.1 by hakore
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.
- 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.
Re: reactOnNPC v.1.1.1 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.
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?
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;
Whatever...
Re: reactOnNPC v.1.1.1 by hakore
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:
And I had to use this kind of code (the numbers are in Portuguese):
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...
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
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: _ _ _ \.$/
}
Re: reactOnNPC v.1.1.1 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?
Meanwhile, can you test the new version and release it on the first post when there are no problems?
Whatever...