From bf8369b6a3fac05819719afa08e36c6212e93f07 Mon Sep 17 00:00:00 2001 From: Allanon Date: Fri, 17 Apr 2015 21:27:36 -0700 Subject: [PATCH 1/8] big refactor --- plugins/buffplease.pl | 756 ++++++++++++++++++------------------------ 1 file changed, 321 insertions(+), 435 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index 6284642..e0933d8 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -1,4 +1,4 @@ -package Buff; +package OpenKore::Plugins::BuffPlease; # Perl includes use strict; @@ -11,459 +11,345 @@ package Buff; use Network; use Globals; use Match; +use Utils qw( min timeOut ); +use Log qw( message warning error ); +use Time::HiRes qw( time ); -our $buff ||= { - # This value is used to determine who will be buffed - # 'all' buffs anyone who asks - # 'guild' only buffs people in the following list of guilds - 'permission' => 'all', - 'guilds' => ['RagnaStats', 'RagnaStats.com'], - - # Use this to map what skills are triggered by the chat - 'aliases' => { - 'Blessing' => '(?:all|full) buff|bless|buff', - 'Increase AGI' => '(?:all|full) buff|\bagi\b|buff', - 'Sanctuary' => 'sanc', - 'High Heal' => 'high|highness|\bhh\b', - 'Ruwach' => 'sight', - 'Impositio Manus' => '(?:all|full) buff|impo', - 'Kyrie Eleison' => '\bKE\b|Kyrie|\bKy\b', - 'Resurrection' => 'res\b|resu', - 'Status Recovery' => '(?:all|full) buff|status|recovery', - 'Assumptio' => '(?:all|full) buff|assu|buff', - 'Safety Wall' => 'wall', - 'Magnificat' => '\bmag\b|magni', - 'Secrament' => '(?:all|full) buff|secra|sacra|sacrement', - 'Cantocandidus' => 'canto', - 'Clementia' => 'clem', - 'PRAEFATIO' => 'prae', - 'Odins Power' => 'odin', 'odins', - 'Renovatio' => '(?:all|full) buff|reno\b', - 'Full Chemical Protection' => 'fcp', - 'Endow Blaze' => '(?:flame|fire) endow|endow (?:fire|flame)', - 'Endow Tsunami' => '(?:ice|water) endow|endow (?:ice|water)', - 'Endow Tornado' => 'wind endow|endow wind', - 'Endow Quake' => '(?:earth|ground) endow|endow (?:earth|ground)', - 'Magic Strings' => 'string|strings' - }, - - # These skills will never be used - 'ignore' => { - 'Teleport' => 1, - 'Warp Portal' => 1, - 'Classical Pluck' => 1, - }, - - # Messages to make fun of people who say plz - 'wit' => [ - "You mean please?", - "Don't you mean please?", - "You meant to say 'please', right?", - "Please check your dictionary.", - "Say please~", - "Plz doesn't cut it.", - "Pls isn't very polite.", - "Just say please :3", - "Please works better.", - "lrn2spell", - "P-l-e-a-s-e", - "Just say please?", - "This would be a lot easier if you said 'please'.", - "Saying please goes a long way.", - "Some day you'll learn... (to say please)", - "Have you tried saying please?", - "Where are your manners? Please try again.", - "Say please first~", - "Please please please!", - "What's so hard about saying please?", - ] - }; - -our $commandUser ||= {}; -our $commandQueue ||= {}; - -Plugins::register("Buff Please?", "Buff people when they ask", \&unload); -my $hooks = Plugins::addHooks(['mainLoop_post', \&loop], - ['packet/skills_list', \&parseSkills], - ['packet/skill_cast', \&parseSkill], - ['packet/skill_used_no_damage', \&parseSkill], - ['packet/actor_status_active', \&parseStatus], - - ["packet_pubMsg", \&parseChat], - ["packet_partyMsg", \&parseChat], - ["packet_guildMsg", \&parseChat], - ["packet_selfChat", \&parseChat], - ["packet_privMsg", \&parseChat], - - ['packet/actor_exists', \&parseActor], - ['packet/actor_info', \&parseInfo]); - - -sub unload -{ - Plugins::delHooks($hooks); +our $buff = { + + # This value is used to determine who will be buffed + # 'all' buffs anyone who asks + # 'guild' only buffs people in the following list of guilds + 'permission' => 'all', + 'guilds' => [ 'RagnaStats', 'RagnaStats.com' ], + + # Use this to map what skills are triggered by the chat + 'aliases' => { + 'Blessing' => '(?:all|full) buff|bless|buff', + 'Increase AGI' => '(?:all|full) buff|\bagi\b|buff', + 'Sanctuary' => 'sanc', + 'High Heal' => 'high|highness|\bhh\b', + 'Ruwach' => 'sight', + 'Impositio Manus' => '(?:all|full) buff|impo', + 'Kyrie Eleison' => '\bKE\b|Kyrie|\bKy\b', + 'Resurrection' => 'res\b|resu', + 'Status Recovery' => '(?:all|full) buff|status|recovery', + 'Assumptio' => '(?:all|full) buff|assu|buff', + 'Safety Wall' => 'wall', + 'Magnificat' => '\bmag\b|magni', + 'Secrament' => '(?:all|full) buff|secra|sacra|sacrement', + 'Cantocandidus' => 'canto', + 'Clementia' => 'clem', + 'PRAEFATIO' => 'prae', + 'Odins Power' => 'odin', + 'Renovatio' => '(?:all|full) buff|reno\b', + 'Full Chemical Protection' => 'fcp', + 'Endow Blaze' => '(?:flame|fire) endow|endow (?:fire|flame)', + 'Endow Tsunami' => '(?:ice|water) endow|endow (?:ice|water)', + 'Endow Tornado' => 'wind endow|endow wind', + 'Endow Quake' => '(?:earth|ground) endow|endow (?:earth|ground)', + 'Magic Strings' => 'string|strings' + }, + + # These skills will never be used + 'ignore' => { + 'Teleport' => 1, + 'Warp Portal' => 1, + 'Classical Pluck' => 1, + }, + + # Messages to make fun of people who say plz + 'wit' => [ + "You mean please?", + "Don't you mean please?", + "You meant to say 'please', right?", + "Please check your dictionary.", + "Say please~", + "Plz doesn't cut it.", + "Pls isn't very polite.", + "Just say please :3", + "Please works better.", + "lrn2spell", + "P-l-e-a-s-e", + "Just say please?", + "This would be a lot easier if you said 'please'.", + "Saying please goes a long way.", + "Some day you'll learn... (to say please)", + "Have you tried saying please?", + "Where are your manners? Please try again.", + "Say please first~", + "Please please please!", + "What's so hard about saying please?", + ], +}; + +our $requests ||= []; +our $commands ||= []; +our $users ||= {}; +our $guilds ||= {}; +our $last_skill = ''; +our $timeout = { time => 0, timeout => 0 }; + +my $please_regex = qr/p+(?:l+|w+)e+a+s+e*|p+w+e+s+e/i; +my $plz_regex = qr/\b(?:p+l+z+|p+l+s+|p+l+o+x+)\b/i; + +Plugins::register( "Buff Please?", "Buff people when they ask", \&unload ); +my $hooks = Plugins::addHooks( + [ 'mainLoop_post', \&loop ], + [ 'packet/skill_use_location', \&skillUsed ], + [ 'packet/skill_used_no_damage', \&skillUsed ], + [ 'packet/actor_status_active', \&parseStatus ], + [ "packet_pubMsg", \&parseChat ], + [ "packet_partyMsg", \&parseChat ], + [ "packet_guildMsg", \&parseChat ], + [ "packet_selfChat", \&parseChat ], + [ "packet_privMsg", \&parseChat ], +); + +sub unload { + Plugins::delHooks( $hooks ); +} + +sub check_config { + # Validate aliases values. Do the regular expressions compile? + # Validate aliases and ignore keys. Do the skills actually exist? + # Validate permission. Valid values are "all" and "guild". } sub in_array { - my ($arr,$search_for) = @_; - foreach my $value (@$arr) { + my ( $arr, $search_for ) = @_; + foreach my $value ( @$arr ) { return 1 if $value eq $search_for; } return 0; } -sub loop -{ - # This is where we periodically loop through the requested commands. - my $time = Time::HiRes::time(); - - if(scalar keys %{$commandQueue}) - { - while(my($userName, $queue) = each(%{$commandQueue})) - { - # If the request is older than 30 seconds... delete - if($commandUser->{$userName}->{time} < $time - 30) { - delete($commandQueue->{$userName}); - } - else - { - # Have they said please within 30 seconds? - if($commandUser->{$userName}->{please} > $time - 30) { - my $command = shift(@{$commandQueue->{$userName}}); - push(@{$buff->{commands}}, $command); - } - - # Have they said plz within 30 seconds? - elsif($commandUser->{$userName}->{plz} > $time - 30) { - # Set the timeout to 7 seconds from now - $commandUser->{$userName}->{plzTimeout} = $time + 7; - delete($commandUser->{$userName}->{plz}); - - my $randomPhrase = $buff->{wit}->[rand @{$buff->{wit}}]; - Commands::run("c $randomPhrase"); - } - - # If the user queue is empty, we don't need to store an empty value. - unless(@{$commandQueue->{$userName}}) { - delete($commandQueue->{$userName}); - } - } - } - } - - if($buff->{commands} and @{$buff->{commands}} and $buff->{time} < $time) - { - # Check every 0.1 seconds - $buff->{time} = $time + 0.1; - - # It took 5 seconds to cast a skill? It might have gotten interrupted. - if($buff->{lastSkill}->{timeout} + 5 < $time) - { - unless($char->statusesString =~ /EFST_POSTDELAY/) - { - my $command = shift(@{$buff->{commands}}); - my $player = ($command->{user} eq $char->{name}) ? 1 : Match::player($command->{user}, 1); - - # Remember this skill as the last skill we casted - $buff->{lastSkill} = {'timeout' => $time, - 'skill' => $command->{skill}}; - - if($buff->{permission} eq 'guild') - { - unless(in_array($buff->{guilds}, $player->{guild}->{name})) - { - next; - } - } - - # Ensure the player still exists before casting - if($player) - { - # Sanitize usernames by adding slashes - my $sanitized = $command->{user}; - $sanitized =~ s/'/\\'/g; - $sanitized =~ s/;/\\;/g; - Commands::run("$command->{type} $command->{skill} '$sanitized'"); - } - else - { - $buff->{lastSkill}->{timeout} = $time - 5; - } - } - } - } -} +sub next_request { + my $time = time; -sub parseSkills -{ - # Got a skills list? - for my $handle (@skillsID) - { - # Code repurposed from the openkore source - my $skill = new Skill(handle => $handle); - - if($char->{skills}{$handle}{lv}) - { - my $skillID = $char->{skills}{$handle}{ID}; - - $buff->{skillsAvailable}->{$skillID} = { - 'name' => $skill->getName(), - 'level' => $char->getSkillLevel($skill), - 'range' => $char->{skills}{$handle}{range}, - 'sp' => $char->{skills}{$handle}{sp} - }; - - # Don't add ignored skills to the skills list! - unless($buff->{ignore}->{$skill->getName()}) - { - $buff->{skills}->{$skillID} = $skill->getName(); - - # Append aditional aliases if this skill has any - if($buff->{aliases}->{$skill->getName()}) { - $buff->{skills}->{$skillID} .= "|".$buff->{aliases}->{$skill->getName()}; - } - } - } - } -} + # Delete requests older than 30 seconds. + @$requests = grep { + if ( $time - $_->{created_at} > 30 ) { + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because it is too old [%.1f seconds].\n", $_->{skill}, $_->{user}, $time - $_->{created_at}; + 0; + } else { + 1; + } + } @$requests; + + while ( @$commands or @$requests ) { + if ( !@$commands ) { + + # Users must have said "please" within 30 seconds to be acceptable. + my @acceptable = grep { $time - $users->{ $_->{user} }->{pleased_at} < 30 } @$requests; -sub parseSkill -{ - my($hook, $args) = @_; - my $time = Time::HiRes::time(); - - # Am I the one casting? Or is the skill kyrie (because kyrie doesn't tell me I finished casting)? - if($args->{sourceID} eq $accountID or ($args->{skillID} == 73 and $buff->{lastSkill}->{skill} == 73)) - { - if($hook eq 'packet/skill_cast') - { - # Get the skill delay and wait that long before trying to do anything else - $buff->{time} = $time + (($args->{wait}) / 1000); - } - elsif($hook eq 'packet/skill_used_no_damage') - { - my $actor = Actor::get($args->{targetID}); - - # Skill 28 is heal - if($args->{skillID} == 28) - { - $commandUser->{$actor->{name}}->{lastHeal} = $time; - - # If the player requested to be healed for a specific amount (heal 10k please) - if($commandUser->{$actor->{name}}->{healFor} > 0) - { - $commandUser->{$actor->{name}}->{healFor} -= $args->{amount}; - - # If they still need more heals... - if($commandUser->{$actor->{name}}->{healFor} > 0) { - - $commandUser->{$actor->{name}}->{please} = $time; - $commandUser->{$actor->{name}}->{time} = $time; - - # Add heal to the queue again - if($actor->{name} eq $char->{name}) { - unshift(@{$commandQueue->{$actor->{name}}}, {'type' => 'ss', 'skill' => 28, 'user' => $actor->{name}}); - } - else { - unshift(@{$commandQueue->{$actor->{name}}}, {'type' => 'sp', 'skill' => 28, 'user' => $actor->{name}}); - } - } - } - } - - # Skill casting complete, we don't need to remember the last skill anymore - if($args->{skillID} == $buff->{lastSkill}->{skill}) { - delete($buff->{lastSkill}); - } - } - } + # No commands and no acceptable requests, we're done. + return if !@acceptable; + + # Order requests by the last time we fulfilled a request by that user, to make sure everybody gets a fair chance. + @acceptable = sort { $users->{ $b->{user} }->{buffed_at} <=> $users->{ $a->{user} }->{buffed_at} || $a->{created_at} <=> $b->{created_at} } @acceptable; + + # Take the first request. + my $req = shift @acceptable; + @$requests = grep { $_ ne $req } @$requests; + push @$commands, $req; + } + + my $req = shift @$commands; + message sprintf "[buffplease] Accepting request to use skill [%s] on user [%s].\n", $req->{skill}, $req->{user}; + return $req; + } + + return; } -sub parseStatus -{ - my($hook, $args) = @_; - my $time = Time::HiRes::time(); - - # Is this my status? - if($args->{ID} eq $accountID) - { - # Status type is: EFST_POSTDELAY - if($args->{type} == 46) - { - if($args->{tick}) - { - # Get the skill cooldown and wait that long before trying to do anything else - $buff->{time} = $time + (($args->{tick}) / 1000); - } - } - } +# This is where we periodically loop through the requested commands. +sub loop { + return if !$config{buffPlease}; + return if !timeOut( $timeout ); + + # Check at most every 0.1 seconds. + $timeout = { time => time, timeout => 0.1 }; + + while ( my $req = next_request() and $char->statusesString !~ /EFST_POSTDELAY/ ) { + + # Ensure the player still exists before casting. + my $player = $req->{user} eq $char->{name} ? $char : Match::player( $req->{user}, 1 ); + if ( !$player ) { + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because they disappeared.\n", $req->{skill}, $req->{user}; + next; + } + + # Make sure we have the skill. + my $skill = Skill->new( idn => $req->{skill} ); + if ( !$skill ) { + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because we don't have that skill.\n", $req->{skill}, $req->{user}; + next; + } + + # Obey permissions. + if ( $buff->{permission} eq 'guild' && !in_array( $buff->{guilds}, $player->{guild}->{name} ) ) { + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because they are not in a whitelisted guild.\n", $req->{skill}, $req->{user}; + next; + } + + # Assume the cast failed after five seconds. + $timeout->{timeout} = 5; + + # Remember this skill as the last skill we cast. + $last_skill = $req->{skill}; + + message "[buffplease] Using skill [$skill] on user [$player].\n"; + my $skillTask = Task::UseSkill->new( + actor => $char, + target => $player, + actorList => $playersList, + skill => $skill, + ); + $taskManager->add( Task::ErrorReport->new( task => $skillTask ) ); + + # TODO: Target this code specifically at Blessing, because skills with EFST_POSTDELAY don't have this problem. + # Force the task to immediately try to cast the skill. + # This speeds up cast time by about 0.5 seconds when casting Blessing then Heal on iRO. + # $skillTask->castSkill; + + last; + } } -sub parseChat -{ - my($hook, $args) = @_; - my $time = Time::HiRes::time(); - my $chat = Storable::dclone($args); - - # selfChat returns slightly different arguements, let's fix that - if($hook eq 'packet_selfChat') - { - $chat->{Msg} = $chat->{msg}; - $chat->{MsgUser} = $chat->{user}; - } - - # Sanitize potential regex in messages. - $chat->{Msg} =~ s/[-\\.,_*+?^\$\[\](){}!=|]/\\$&/g; - - # Loop through the list of available skills - while(my($skillID, $skillName) = each(%{$buff->{skills}})) - { - # Remove whitespace from skill names, Gravity is not to be trusted! - $skillName =~ s/^\s+//; - $skillName =~ s/\s+$//; - - # If the skill name occurs in this user's message - if($chat->{Msg} =~ /$skillName/i) { - # Match the string following a skill name - $chat->{Msg} =~ m/(?:$skillName)(?:\w+)?(?:\s+)?([^\s"']+|".+"|'.+')/i; - - # Save it and strip quotes - my $potentialPlayer = $1; - $potentialPlayer =~ s/["']//g; - - - - # Make sure it's defined and not please - if($potentialPlayer and $potentialPlayer !~ /p+(l|w)+e+a+s+(e+)?|p+w+e+s+e/i) - { - my $player = Match::player($potentialPlayer, 1); - my $playerName = ''; - - # Is it a player? - if($player) { - $playerName = $player->{name}; - } - - # Is it me? - elsif($char->{name} =~ /^$potentialPlayer/i) { - $playerName = $char->{name}; - } - - # Cast on the requested player - - if($playerName) { - $chat->{MsgUser} = $playerName; - } - } - - $commandUser->{$chat->{MsgUser}}->{time} = $time; - - # If you're the one asking for something, you need to use skill self (ss) - if($chat->{MsgUser} eq $char->{name}) { - unshift(@{$commandQueue->{$chat->{MsgUser}}}, {'type' => 'ss', 'skill' => $skillID, 'user' => $chat->{MsgUser}}); - } - - # Otherwise use skill on a player (sp) - else { - unshift(@{$commandQueue->{$chat->{MsgUser}}}, {'type' => 'sp', 'skill' => $skillID, 'user' => $chat->{MsgUser}}); - } - } - } - - # Please? - if($chat->{Msg} =~ /p+ ?(l|w)+ ?e+ ?a+ ?s+ ?(e+)?|p+w+e+s+e/i) - { - $commandUser->{$chat->{MsgUser}}->{please} = $time; - } - - # Plz? - if($chat->{Msg} =~ /\b(p+l+z+|p+l+s+|p+l+o+x+)\b/i) - { - # Unless this person has already been corrected. - if($commandUser->{$chat->{MsgUser}}->{plzTimeout} < $time) { - $commandUser->{$chat->{MsgUser}}->{plz} = $time; - } - } - - # Heal 10k, 4000, etc. - if($chat->{Msg} =~ /([0-9,]+)\s*([kx]\s)?/i) - { - my $hp = $1; - my $modifier = $2; - - $hp =~ s/,//; - - if($modifier) { - $hp *= 1000 - } - - # Most people don't have more than 30,000 HP - if($hp > 30000) { - $hp = 30000; - } - - $commandUser->{$chat->{MsgUser}}->{healFor} = $hp; - } - - # HEAL ME MORE!!! - if($chat->{Msg} =~ /more/i) - { - # If this user has already been healed in the past 10 seconds - if($commandUser->{$chat->{MsgUser}}->{lastHeal} + 10 > $time) - { - $commandUser->{$chat->{MsgUser}}->{please} = $time; - $commandUser->{$chat->{MsgUser}}->{time} = $time; - - if($chat->{MsgUser} eq $char->{name}) { - unshift(@{$commandQueue->{$chat->{MsgUser}}}, {'type' => 'ss', 'skill' => 28, 'user' => $chat->{MsgUser}}); - } - else { - unshift(@{$commandQueue->{$chat->{MsgUser}}}, {'type' => 'sp', 'skill' => 28, 'user' => $chat->{MsgUser}}); - } - - # Someone asking for more probably wants a couple heals - if($commandUser->{$chat->{MsgUser}}->{healFor} < 5000) { - $commandUser->{$chat->{MsgUser}}->{healFor} = 5000; - } - } - } - - if($chat->{Msg} =~ /debug/i) - { -# print(Dumper($buff->{skillsAvailable})); - print(Dumper($commandQueue)); - print(Dumper($commandUser)); - print(Dumper($buff)); -# print(Dumper($char)); - } +sub skillUsed { + my ( undef, $args ) = @_; + + # Kyrie doesn't tell me I finished casting. + return if $args->{sourceID} ne $accountID and $args->{skillID} != 73; + return if $args->{skillID} != $last_skill; + + $timeout->{timeout} = 0; + + my $time = time; + + my $actor = Actor::get( $args->{targetID} ); + + # Skill 28 is heal + if ( $args->{skillID} == 28 ) { + $users->{ $actor->{name} }->{lastHeal} = $time; + $users->{ $actor->{name} }->{healFor} -= $args->{amount}; + + # If the player requested to be healed for a specific amount (heal 10k please) and they still need more heals... + if ( $users->{ $actor->{name} }->{healFor} > 0 ) { + + # Extend their please. + $users->{ $actor->{name} }->{please} = $time; + + # Add heal to the queue again + unshift @$commands, { skill => 28, user => $actor->{name}, created_at => $time }; + warning sprintf "[buffplease] Still need to heal user [%s] for [%d]. Re-queuing heal.\n", $actor->{name}, $users->{ $actor->{name} }->{healFor}; + } + } } -sub parseActor -{ - my($hook, $args) = @_; - my $playerID = unpack('V', $args->{ID}); - my $guildID = unpack('V', $args->{guildID}); - my $time = Time::HiRes::time(); - - $buff->{player}->{$playerID} = $guildID; - - unless($buff->{guild}->{$guildID}) - { - $messageSender->sendGetPlayerInfo($args->{ID}); - } +sub parseStatus { + my ( undef, $args ) = @_; + + return if $args->{ID} ne $accountID; + + # Status type 46 is EFST_POSTDELAY + return if $args->{type} != 46; + return if !$args->{tick}; + + # Get the skill cooldown and wait that long before trying to do anything else + $timeout = { time => time, timeout => $args->{tick} / 1000 }; } -sub parseInfo -{ - my($hook, $args) = @_; - - if($args->{guildName}) - { - my $playerID = unpack('V', $args->{ID}); - my $guildID = $buff->{player}->{$playerID}; - - $buff->{guild}->{$guildID} = $args->{guildName}; - } +sub parseChat { + my ( $hook, $args ) = @_; + + my $msg = $hook eq 'packet_selfChat' ? $args->{msg} : $args->{Msg}; + my $user = $hook eq 'packet_selfChat' ? $args->{user} : $args->{MsgUser}; + + my $nreq = @$requests; + + # Loop through the list of available skills + my @requests; + foreach my $skillID ( keys %Skill::DynamicInfo::skills ) { + my $skillName = Skill->new( idn => $skillID ); + + # Trim whitespace from skill names, Gravity is not to be trusted! + $skillName =~ s/^\s+|\s+$//g; + + next if $buff->{ignore}->{$skillName}; + + $skillName .= "|$buff->{aliases}->{$skillName}" if $buff->{aliases}->{$skillName}; + + # If the skill name occurs in this user's message + next if $msg !~ /$skillName/i; + + # Match the string following a skill name + $msg =~ m/(?:$skillName)\w*\s*(?:"([^"]+)"|'([^']+)'|(\S+))/i; + + # Save it + my $potentialPlayer = $1 || $2 || $3; + + # Make sure it's defined and not please + my $skillUser = $user; + if ( $potentialPlayer and $potentialPlayer !~ $please_regex ) { + if ( my $player = Match::player( $potentialPlayer, 1 ) ) { + $skillUser = $player->{name}; + } elsif ( $char->{name} =~ /^\Q$potentialPlayer\E/i ) { + $skillUser = $char->{name}; + } + } + + message sprintf "[buffplease] Adding request to use skill [%s] on user [%s].\n", $skillID, $skillUser; + push @$requests, { skill => $skillID, user => $skillUser, created_at => time }; + } + + # Please? + $users->{$user}->{pleased_at} = time if $msg =~ $please_regex; + + # Heal 10k, 4000, etc. + if ( $msg =~ /([0-9,]+)\s*([kx]\s)?/i ) { + my ( $hp, $modifier ) = ( $1, $2 ); + + $hp =~ s/,//g; + + $hp *= 1000 if $modifier; + + # Most people don't have more than 30,000 HP + $hp = min( $hp, 30000 ); + + $users->{$user}->{healFor} = $hp; + } + + # HEAL ME MORE!!! + # If this user has already been healed in the past 10 seconds + if ( $msg =~ /\bmore\b/i && !timeOut( $users->{$user}->{lastHeal}, 10 ) ) { + + # Extend their please. + $users->{$user}->{please} = time; + + push @$requests, { skill => 28, user => $user, created_at => time }; + + # Someone asking for more probably wants a couple heals + if ( $users->{$user}->{healFor} < 5000 ) { + $users->{$user}->{healFor} = 5000; + } + } + + # Plz? + # Unless this person has already been corrected. + if ( $nreq != @$requests and $msg =~ $plz_regex and timeOut( $users->{$user}->{plzed_at}, 30 ) ) { + $users->{$user}->{plzed_at} = time; + my $randomPhrase = $buff->{wit}->[ rand @{ $buff->{wit} } ]; + Commands::run( "c $randomPhrase" ); + } + + if ( $msg =~ /debug/i ) { + print( Dumper( $requests ) ); + print( Dumper( $commands ) ); + print( Dumper( $users ) ); + print( Dumper( $buff ) ); + } } 1; From c0439e772c38aa190dee1d283eb9fb2e97c1c4e6 Mon Sep 17 00:00:00 2001 From: Allanon Date: Sat, 18 Apr 2015 15:45:31 -0700 Subject: [PATCH 2/8] add help, add commands (queue list and validate) --- plugins/buffplease.pl | 83 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index e0933d8..61c7d5d 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -11,7 +11,7 @@ package OpenKore::Plugins::BuffPlease; use Network; use Globals; use Match; -use Utils qw( min timeOut ); +use Utils qw( min timeOut parseArgs swrite formatNumber ); use Log qw( message warning error ); use Time::HiRes qw( time ); @@ -106,14 +106,88 @@ package OpenKore::Plugins::BuffPlease; [ "packet_privMsg", \&parseChat ], ); +my $cmds = Commands::register( + [ + buffplease => [ # + 'Auto-buff when people say please', + [ list => 'show buff queue' ], + [ validate => 'validate plugin configuration' ] + ], + \&command, + ] +); + sub unload { Plugins::delHooks( $hooks ); + Commands::unregister( $cmds ); +} + +sub command { + my ( undef, $args ) = @_; + + my ( $cmd, @args ) = parseArgs( $args ); + if ( $cmd eq 'list' ) { + list(); + } elsif ( $cmd eq 'validate' ) { + validate(); + } else { + error "[buffplease] Unknown command.\n"; + Commands::helpIndent( 'buffplease', $Commands::customCommands{buffplease}{desc} ); + } } -sub check_config { +sub list { + my $time = time; + + my $fmt = '@> @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<< @>>>>>'; + + my @lines; + + push @lines, "== [buffplease] Pending Requests ============\n"; + push @lines, swrite( $fmt, [ '', 'User', 'Skill', 'Amount' ] ); + my @sorted = sort { $a->{created_at} <=> $b->{created_at} } @$requests; + foreach ( 0 .. $#sorted ) { + my $req = $sorted[$_]; + my $amount = ''; + if ( $req->{skill} == 28 && $users->{ $req->{user} }->{healFor} > 0 ) { + $amount = formatNumber( $users->{ $req->{user} }->{healFor} ); + } + push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); + } + push @lines, "(none)\n" if !@$requests; + + push @lines, "== [buffplease] Accepted Requests ===========\n"; + foreach ( 0 .. $#$commands ) { + my $req = $commands->[ $_ - 1 ]; + push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName ] ); + } + + message join '', @lines; +} + +sub validate { + # Validate aliases values. Do the regular expressions compile? + foreach ( sort keys %{ $buff->{aliases} } ) { + next if eval {qr{$buff->{aliases}->{$_}}}; + error "[buffplease] Alias key [$_] has an invalid regular expression.\n"; + } + # Validate aliases and ignore keys. Do the skills actually exist? + foreach ( sort keys %{ $buff->{aliases} } ) { + next if Skill::lookupIDNByName( $_ ); + error "[buffplease] Alias key [$_] is not a valid skill name!\n"; + } + foreach ( sort keys %{ $buff->{ignore} } ) { + next if Skill::lookupIDNByName( $_ ); + error "[buffplease] Ignore key [$_] is not a valid skill name!\n"; + } + # Validate permission. Valid values are "all" and "guild". + my $valid_permissions = [qw( all guild )]; + if ( !in_array( $valid_permissions, $buff->{permission} ) ) { + error "[buffplease] Permission [$buff->{permission}] is invalid. Valid permissions are: @$valid_permissions\n"; + } } sub in_array { @@ -279,7 +353,8 @@ sub parseChat { next if $buff->{ignore}->{$skillName}; - $skillName .= "|$buff->{aliases}->{$skillName}" if $buff->{aliases}->{$skillName}; + # Add alias matches if the alias is a valid regex. + $skillName .= "|$buff->{aliases}->{$skillName}" if $buff->{aliases}->{$skillName} && eval { qr/$buff->{aliases}->{$skillName}/ }; # If the skill name occurs in this user's message next if $msg !~ /$skillName/i; @@ -308,7 +383,7 @@ sub parseChat { $users->{$user}->{pleased_at} = time if $msg =~ $please_regex; # Heal 10k, 4000, etc. - if ( $msg =~ /([0-9,]+)\s*([kx]\s)?/i ) { + if ( $msg =~ /([0-9,]+)\s*([kx]\b)?/i ) { my ( $hp, $modifier ) = ( $1, $2 ); $hp =~ s/,//g; From 72a68dd9a573a676d98791e5974143d45c27b2e7 Mon Sep 17 00:00:00 2001 From: Allanon Date: Sat, 18 Apr 2015 16:07:38 -0700 Subject: [PATCH 3/8] reformat "buffplease list" --- plugins/buffplease.pl | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index 61c7d5d..b6be4d1 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -139,27 +139,31 @@ sub command { sub list { my $time = time; - my $fmt = '@> @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<< @>>>>>'; + my $fmt = '[buffplease] @> @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<< @>>>>>'; my @lines; - push @lines, "== [buffplease] Pending Requests ============\n"; - push @lines, swrite( $fmt, [ '', 'User', 'Skill', 'Amount' ] ); - my @sorted = sort { $a->{created_at} <=> $b->{created_at} } @$requests; - foreach ( 0 .. $#sorted ) { - my $req = $sorted[$_]; - my $amount = ''; - if ( $req->{skill} == 28 && $users->{ $req->{user} }->{healFor} > 0 ) { - $amount = formatNumber( $users->{ $req->{user} }->{healFor} ); + if ( @$requests ) { + push @lines, "[buffplease] == Pending Requests ==========================\n"; + push @lines, swrite( $fmt, [ '', 'User', 'Skill', 'Amount' ] ); + my @sorted = sort { $a->{created_at} <=> $b->{created_at} } @$requests; + foreach ( 0 .. $#sorted ) { + my $req = $sorted[$_]; + my $amount = $req->{skill} == 28 && $users->{ $req->{user} }->{healFor} > 0 ? formatNumber( $users->{ $req->{user} }->{healFor} ) : ''; + push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); } - push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); + } else { + push @lines, "[buffplease] No pending requests.\n"; } - push @lines, "(none)\n" if !@$requests; - push @lines, "== [buffplease] Accepted Requests ===========\n"; - foreach ( 0 .. $#$commands ) { - my $req = $commands->[ $_ - 1 ]; - push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName ] ); + if ( @$commands ) { + push @lines, "[buffplease] == Accepted Requests =========================\n"; + push @lines, swrite( $fmt, [ '', 'User', 'Skill', 'Amount' ] ); + foreach ( 0 .. $#$commands ) { + my $req = $commands->[ $_ - 1 ]; + my $amount = $req->{skill} == 28 && $users->{ $req->{user} }->{healFor} > 0 ? formatNumber( $users->{ $req->{user} }->{healFor} ) : ''; + push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); + } } message join '', @lines; From d7aa8991c742cf996db79cf646cea858786a8f97 Mon Sep 17 00:00:00 2001 From: Allanon Date: Sat, 18 Apr 2015 16:09:12 -0700 Subject: [PATCH 4/8] remove unused $guilds --- plugins/buffplease.pl | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index b6be4d1..3830892 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -86,7 +86,6 @@ package OpenKore::Plugins::BuffPlease; our $requests ||= []; our $commands ||= []; our $users ||= {}; -our $guilds ||= {}; our $last_skill = ''; our $timeout = { time => 0, timeout => 0 }; From 8a4d743ac3447fb969fc6d3b0ff02fe0efcc3643 Mon Sep 17 00:00:00 2001 From: Allanon Date: Sat, 18 Apr 2015 20:43:20 -0700 Subject: [PATCH 5/8] push the definition of "please" and "pls" into the config --- plugins/buffplease.pl | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index 3830892..331be1e 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -23,6 +23,12 @@ package OpenKore::Plugins::BuffPlease; 'permission' => 'all', 'guilds' => [ 'RagnaStats', 'RagnaStats.com' ], + # What qualifies as "please"? + 'please' => [ qw( please pwease pwese onegai ), 'por favor' ], + + # What qualifies as "plz"? + 'plz' => [ qw( plz pls plox ) ], + # Use this to map what skills are triggered by the chat 'aliases' => { 'Blessing' => '(?:all|full) buff|bless|buff', @@ -89,8 +95,8 @@ package OpenKore::Plugins::BuffPlease; our $last_skill = ''; our $timeout = { time => 0, timeout => 0 }; -my $please_regex = qr/p+(?:l+|w+)e+a+s+e*|p+w+e+s+e/i; -my $plz_regex = qr/\b(?:p+l+z+|p+l+s+|p+l+o+x+)\b/i; +my $please_regex = list_to_regex( @{ $buff->{please} } ); +my $plz_regex = list_to_regex( @{ $buff->{plz} } ); Plugins::register( "Buff Please?", "Buff people when they ask", \&unload ); my $hooks = Plugins::addHooks( @@ -233,7 +239,7 @@ sub next_request { } my $req = shift @$commands; - message sprintf "[buffplease] Accepting request to use skill [%s] on user [%s].\n", $req->{skill}, $req->{user}; + message sprintf "[buffplease] Accepting request to use skill [%s] on user [%s] (last please was %.1f seconds ago).\n", $req->{skill}, $req->{user}, $time - $users->{ $req->{user} }->{pleased_at}; return $req; } @@ -430,4 +436,15 @@ sub parseChat { } } +# Case-insensitive, every letter must be repeated 1+ times, match on word boundaries. +# list_to_regex( 'plz', 'pls' ) => '\b(?i:p+l+z+|p+l+s+)\b' +sub list_to_regex { + '\b(?i:' . join( + '|', + map { + join '', map {"$_+"} split //, $_ + } @_ + ) . ')\b'; +} + 1; From ce1a04c876c1fd9af9d1e00ae0fda087c12f0af3 Mon Sep 17 00:00:00 2001 From: Allanon Date: Sun, 19 Apr 2015 17:39:14 -0700 Subject: [PATCH 6/8] support more words that mean "more" --- plugins/buffplease.pl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index 331be1e..bf0aab4 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -29,6 +29,9 @@ package OpenKore::Plugins::BuffPlease; # What qualifies as "plz"? 'plz' => [ qw( plz pls plox ) ], + # What qualifies as "more"? + 'more' => [ qw( more +1 again ) ], + # Use this to map what skills are triggered by the chat 'aliases' => { 'Blessing' => '(?:all|full) buff|bless|buff', @@ -97,6 +100,7 @@ package OpenKore::Plugins::BuffPlease; my $please_regex = list_to_regex( @{ $buff->{please} } ); my $plz_regex = list_to_regex( @{ $buff->{plz} } ); +my $more_regex = list_to_regex( @{ $buff->{more} } ); Plugins::register( "Buff Please?", "Buff people when they ask", \&unload ); my $hooks = Plugins::addHooks( @@ -407,7 +411,7 @@ sub parseChat { # HEAL ME MORE!!! # If this user has already been healed in the past 10 seconds - if ( $msg =~ /\bmore\b/i && !timeOut( $users->{$user}->{lastHeal}, 10 ) ) { + if ( $msg =~ $more_regex && !timeOut( $users->{$user}->{lastHeal}, 10 ) ) { # Extend their please. $users->{$user}->{please} = time; @@ -442,7 +446,7 @@ sub list_to_regex { '\b(?i:' . join( '|', map { - join '', map {"$_+"} split //, $_ + join '', map {"\Q$_\E+"} split //, $_ } @_ ) . ')\b'; } From ce1169ec4ebb475b4e31595edbd05c4b668bbdca Mon Sep 17 00:00:00 2001 From: Allanon Date: Sun, 19 Apr 2015 18:12:23 -0700 Subject: [PATCH 7/8] separate requestor and target, and accept request if either one says please --- plugins/buffplease.pl | 57 ++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index bf0aab4..64fb81c 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -11,7 +11,7 @@ package OpenKore::Plugins::BuffPlease; use Network; use Globals; use Match; -use Utils qw( min timeOut parseArgs swrite formatNumber ); +use Utils qw( min max timeOut parseArgs swrite formatNumber ); use Log qw( message warning error ); use Time::HiRes qw( time ); @@ -158,8 +158,8 @@ sub list { my @sorted = sort { $a->{created_at} <=> $b->{created_at} } @$requests; foreach ( 0 .. $#sorted ) { my $req = $sorted[$_]; - my $amount = $req->{skill} == 28 && $users->{ $req->{user} }->{healFor} > 0 ? formatNumber( $users->{ $req->{user} }->{healFor} ) : ''; - push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); + my $amount = $req->{skill} == 28 && $users->{ $req->{target} }->{healFor} > 0 ? formatNumber( $users->{ $req->{target} }->{healFor} ) : ''; + push @lines, swrite( $fmt, [ $_, $req->{target}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); } } else { push @lines, "[buffplease] No pending requests.\n"; @@ -170,8 +170,8 @@ sub list { push @lines, swrite( $fmt, [ '', 'User', 'Skill', 'Amount' ] ); foreach ( 0 .. $#$commands ) { my $req = $commands->[ $_ - 1 ]; - my $amount = $req->{skill} == 28 && $users->{ $req->{user} }->{healFor} > 0 ? formatNumber( $users->{ $req->{user} }->{healFor} ) : ''; - push @lines, swrite( $fmt, [ $_, $req->{user}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); + my $amount = $req->{skill} == 28 && $users->{ $req->{target} }->{healFor} > 0 ? formatNumber( $users->{ $req->{target} }->{healFor} ) : ''; + push @lines, swrite( $fmt, [ $_, $req->{target}, Skill->new( idn => $req->{skill} )->getName, $amount ] ); } } @@ -217,7 +217,7 @@ sub next_request { # Delete requests older than 30 seconds. @$requests = grep { if ( $time - $_->{created_at} > 30 ) { - warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because it is too old [%.1f seconds].\n", $_->{skill}, $_->{user}, $time - $_->{created_at}; + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because it is too old [%.1f seconds].\n", $_->{skill}, $_->{target}, $time - $_->{created_at}; 0; } else { 1; @@ -227,14 +227,14 @@ sub next_request { while ( @$commands or @$requests ) { if ( !@$commands ) { - # Users must have said "please" within 30 seconds to be acceptable. - my @acceptable = grep { $time - $users->{ $_->{user} }->{pleased_at} < 30 } @$requests; + # User or target must have said "please" within 30 seconds to be acceptable. + my @acceptable = grep { $time - $users->{ $_->{user} }->{pleased_at} < 30 or $time - $users->{ $_->{target} }->{pleased_at} < 30 } @$requests; # No commands and no acceptable requests, we're done. return if !@acceptable; # Order requests by the last time we fulfilled a request by that user, to make sure everybody gets a fair chance. - @acceptable = sort { $users->{ $b->{user} }->{buffed_at} <=> $users->{ $a->{user} }->{buffed_at} || $a->{created_at} <=> $b->{created_at} } @acceptable; + @acceptable = sort { $users->{ $b->{target} }->{buffed_at} <=> $users->{ $a->{target} }->{buffed_at} || $a->{created_at} <=> $b->{created_at} } @acceptable; # Take the first request. my $req = shift @acceptable; @@ -243,7 +243,7 @@ sub next_request { } my $req = shift @$commands; - message sprintf "[buffplease] Accepting request to use skill [%s] on user [%s] (last please was %.1f seconds ago).\n", $req->{skill}, $req->{user}, $time - $users->{ $req->{user} }->{pleased_at}; + message sprintf "[buffplease] Accepting request to use skill [%s] on user [%s] (last please was %.1f seconds ago).\n", $req->{skill}, $req->{target}, $time - $users->{ $req->{target} }->{pleased_at}; return $req; } @@ -261,22 +261,22 @@ sub loop { while ( my $req = next_request() and $char->statusesString !~ /EFST_POSTDELAY/ ) { # Ensure the player still exists before casting. - my $player = $req->{user} eq $char->{name} ? $char : Match::player( $req->{user}, 1 ); + my $player = $req->{target} eq $char->{name} ? $char : Match::player( $req->{target}, 1 ); if ( !$player ) { - warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because they disappeared.\n", $req->{skill}, $req->{user}; + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because they disappeared.\n", $req->{skill}, $req->{target}; next; } # Make sure we have the skill. my $skill = Skill->new( idn => $req->{skill} ); if ( !$skill ) { - warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because we don't have that skill.\n", $req->{skill}, $req->{user}; + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because we don't have that skill.\n", $req->{skill}, $req->{target}; next; } # Obey permissions. if ( $buff->{permission} eq 'guild' && !in_array( $buff->{guilds}, $player->{guild}->{name} ) ) { - warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because they are not in a whitelisted guild.\n", $req->{skill}, $req->{user}; + warning sprintf "[buffplease] Ignoring request to use skill [%s] on user [%s] because they are not in a whitelisted guild.\n", $req->{skill}, $req->{target}; next; } @@ -326,10 +326,10 @@ sub skillUsed { if ( $users->{ $actor->{name} }->{healFor} > 0 ) { # Extend their please. - $users->{ $actor->{name} }->{please} = $time; + $users->{ $actor->{name} }->{pleased_at} = $time; # Add heal to the queue again - unshift @$commands, { skill => 28, user => $actor->{name}, created_at => $time }; + unshift @$commands, { skill => 28, user => $actor->{name}, target => $actor->{name}, created_at => $time }; warning sprintf "[buffplease] Still need to heal user [%s] for [%d]. Re-queuing heal.\n", $actor->{name}, $users->{ $actor->{name} }->{healFor}; } } @@ -354,6 +354,9 @@ sub parseChat { my $msg = $hook eq 'packet_selfChat' ? $args->{msg} : $args->{Msg}; my $user = $hook eq 'packet_selfChat' ? $args->{user} : $args->{MsgUser}; + # The target of this request, which may not be the message sender. + my $target = $user; + my $nreq = @$requests; # Loop through the list of available skills @@ -379,17 +382,16 @@ sub parseChat { my $potentialPlayer = $1 || $2 || $3; # Make sure it's defined and not please - my $skillUser = $user; if ( $potentialPlayer and $potentialPlayer !~ $please_regex ) { if ( my $player = Match::player( $potentialPlayer, 1 ) ) { - $skillUser = $player->{name}; + $target = $player->{name}; } elsif ( $char->{name} =~ /^\Q$potentialPlayer\E/i ) { - $skillUser = $char->{name}; + $target = $char->{name}; } } - message sprintf "[buffplease] Adding request to use skill [%s] on user [%s].\n", $skillID, $skillUser; - push @$requests, { skill => $skillID, user => $skillUser, created_at => time }; + message sprintf "[buffplease] Adding request to use skill [%s] on user [%s].\n", $skillID, $target; + push @$requests, { skill => $skillID, user => $user, target => $target, created_at => time }; } # Please? @@ -406,22 +408,21 @@ sub parseChat { # Most people don't have more than 30,000 HP $hp = min( $hp, 30000 ); - $users->{$user}->{healFor} = $hp; + $users->{$target}->{healFor} = $hp; } # HEAL ME MORE!!! # If this user has already been healed in the past 10 seconds - if ( $msg =~ $more_regex && !timeOut( $users->{$user}->{lastHeal}, 10 ) ) { + if ( $msg =~ $more_regex && !timeOut( $users->{$target}->{lastHeal}, 10 ) ) { # Extend their please. - $users->{$user}->{please} = time; + $users->{$target}->{pleased_at} = time; - push @$requests, { skill => 28, user => $user, created_at => time }; + message sprintf "[buffplease] Adding request to use skill [%s] on user [%s].\n", 28, $target; + push @$requests, { skill => 28, user => $user, target => $target, created_at => time }; # Someone asking for more probably wants a couple heals - if ( $users->{$user}->{healFor} < 5000 ) { - $users->{$user}->{healFor} = 5000; - } + $users->{$target}->{healFor} = max( $users->{$target}->{healFor}, 5000 ); } # Plz? From ad921af45f55991519b43de1bf86704503c6f53e Mon Sep 17 00:00:00 2001 From: Allanon Date: Fri, 1 May 2015 16:58:41 -0700 Subject: [PATCH 8/8] ignore requests when buffPlease config option is disabled, clearer errors --- plugins/buffplease.pl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/plugins/buffplease.pl b/plugins/buffplease.pl index 64fb81c..166c555 100755 --- a/plugins/buffplease.pl +++ b/plugins/buffplease.pl @@ -126,6 +126,8 @@ package OpenKore::Plugins::BuffPlease; ] ); +Misc::configModify( buffPlease => 0 ) if !exists $config{buffPlease}; + sub unload { Plugins::delHooks( $hooks ); Commands::unregister( $cmds ); @@ -179,28 +181,36 @@ sub list { } sub validate { + my @errors; + + if ( !$config{buffPlease} ) { + push @errors, "[buffplease] Not enabled. To enable: conf buffPlease 1\n"; + } # Validate aliases values. Do the regular expressions compile? foreach ( sort keys %{ $buff->{aliases} } ) { next if eval {qr{$buff->{aliases}->{$_}}}; - error "[buffplease] Alias key [$_] has an invalid regular expression.\n"; + push @errors, "[buffplease] Alias key [$_] has an invalid regular expression.\n"; } # Validate aliases and ignore keys. Do the skills actually exist? foreach ( sort keys %{ $buff->{aliases} } ) { next if Skill::lookupIDNByName( $_ ); - error "[buffplease] Alias key [$_] is not a valid skill name!\n"; + push @errors, "[buffplease] Alias key [$_] is not a valid skill name!\n"; } foreach ( sort keys %{ $buff->{ignore} } ) { next if Skill::lookupIDNByName( $_ ); - error "[buffplease] Ignore key [$_] is not a valid skill name!\n"; + push @errors, "[buffplease] Ignore key [$_] is not a valid skill name!\n"; } # Validate permission. Valid values are "all" and "guild". my $valid_permissions = [qw( all guild )]; if ( !in_array( $valid_permissions, $buff->{permission} ) ) { - error "[buffplease] Permission [$buff->{permission}] is invalid. Valid permissions are: @$valid_permissions\n"; + push @errors, "[buffplease] Permission [$buff->{permission}] is invalid. Valid permissions are: @$valid_permissions\n"; } + + error join '', @errors if @errors; + message "[buffplease] Validation complete. Found " . @errors . " errors.\n"; } sub in_array { @@ -351,6 +361,8 @@ sub parseStatus { sub parseChat { my ( $hook, $args ) = @_; + return if !$config{buffPlease}; + my $msg = $hook eq 'packet_selfChat' ? $args->{msg} : $args->{Msg}; my $user = $hook eq 'packet_selfChat' ? $args->{user} : $args->{MsgUser};