(!empty($user->lang['CODE'])) ? $user->lang['CODE'] : ucwords(strtolower(str_replace('_', ' ', 'CODE'))):
package WizBot;
use strict;
use Globals;
use Plugins;
use Utils;
use Misc;
use Log qw(message error debug warning);
use Network::Send;
use Time::HiRes qw(gettimeofday tv_interval);
use Settings;
use FileParsers;
Plugins::register('wizbot', 'Wizard Bot', \&Unload, \&Reload);
my $hooks = Plugins::addHooks(
["AI_post", \&AI_post]
);
sub Reload { Unload(); }
sub Unload { Plugins::delHooks($hooks); }
our $tick_timeout;
our @aggressives;
sub AI_post {
return unless $AI;
return unless $config{wizbot};
return if $cities_lut{$field{name}.'.rsw'};
return unless AI::isIdle();
# Don't evaluate this loop too often
return unless tv_interval($tick_timeout) > 0.3;
$tick_timeout = [gettimeofday];
# Find a monster to attack
my $best_distance = 100;
my $best_monster;
@aggressives = ();
for my $ID (@monstersID) {
my $monster = $monsters{$ID};
next unless UNIVERSAL::isa($monster, 'Actor::Monster');
next if !checkMonsterCleanness($monster);
my $ctrl = mon_control($monster->{name});
next unless $ctrl->{attack_auto} > 0;
next unless checkLineWalkable($char->position, $monster->position);
my $d = $monster->distance;
if ($d < $best_distance) {
$best_monster = $monster;
$best_distance = $d;
}
if ($d <5>{pos}, 12);
next if positionNearPortal($item->{pos}, 10);
next unless checkLineWalkable($char->position, $item->{pos});
my $name = lc($item->{name});
next if $itemsPickup{$name} eq "0" || $itemsPickup{$name} == -1 ||
(!$itemsPickup{all} && !$itemsPickup{$name});
my $d = distance($char->position, $item->{pos});
if ($d <best_distance>equip if $sting;
my $bd = $target->blockDistance;
my $myPos = $char->position;
if ($bd > 10) {
my (%vec, %pos);
getVector(\%vec, $target->position, $myPos);
moveAlongVector(\%pos, $myPos, \%vec, $bd - 9);
sendMove($pos{x}, $pos{y});
message "$target is $bd blocks away; need to move closer to ($pos{x}, $pos{y})\n", 'wizbot';
$tick_timeout = [gettimeofday + 1.0];
return;
}
if (@aggressives >= 3) {
# Use an area attack
my $sg = 0;
for my $agg (@aggressives) {
$sg++ if $agg->{name} ne 'Seal';
}
if ($sg >= 3) {
skillArea($char->position, 'Storm Gust');
} else {
skillArea($char->position, 'Lord of Vermilion');
}
} else {
# Use a single-target attack
if ($target->{name} eq 'Galapago') {
skillTarget($target, 'Fire Bolt');
} else {
skillTarget($target, 'Jupitel Thunder');
}
}
}
sub take {
my ($item) = @_;
message "Going to take $item->{name} ($item->{binID})\n", 'wizbot';
my $myPos = $char->position;
my $bd = blockDistance($myPos, $item->{pos});
if ($bd > 1) {
my (%vec, %pos);
getVector(\%vec, $item->{pos}, $myPos);
moveAlongVector(\%pos, $myPos, \%vec, min($bd, 5));
message "Moving to ($pos{x}, $pos{y})\n", 'wizbot';
sendMove($pos{x}, $pos{y});
$tick_timeout = [gettimeofday + 1.0];
} else {
sendTake($net, $item->{ID});
}
}
sub skillArea {
my ($area, $skillName) = @_;
my $skill = new Skills(name => $skillName);
message "Casting $skillName on location ($area->{x}, $area->{y})\n", 'wizbot';
sendSkillUseLoc($net, $skill->id, 10, $area->{x}, $area->{y});
}
sub skillTarget {
my ($target, $skillName) = @_;
my $skill = new Skills(name => $skillName);
message "Casting $skillName on $target\n", 'wizbot';
sendSkillUse($net, $skill->id, 10, $target->{ID});
}
1;