After some fooling around with some concepts, this is where I ended up. All of this was done without any source code modification. I intentionally added notes where things did not work as you might expect. I had to kludge together some logic because bots don't return owner-related information correctly via Perl for such reasons. All required "QnD" plugins included.
in <EQEMU_DIR>\plugins\MySQL.pl
Code:
# USAGE: plugin::SelectHashref($dbh, $sql);
# NOTE: (weakly) coded to only allow for SELECT statements
sub SelectHashref {
my ($dbh, $sql) = @_;
return () unless $dbh && (ref $dbh) =~ /^DBI/; # validate DBI handle
return () unless $dbh->ping; # validate connection
return () unless $sql && $sql =~ /^SELECT /; # validate sql query
my $sth = $dbh->prepare($sql);
$sth->execute();
return $sth->fetchrow_hashref();
}
in <EQEMU_DIR>\plugins\Bots.pl
Code:
# USAGE: plugin::GetGroupedBots($client)
sub GetGroupedBots {
my @b;
if (my $g = shift->GetGroup()) {
for (my $i = 0; $i < 6; $i++) {
next unless my $m = $g->GetMember($i);
next if $m->IsClient() ||
$m->IsNPC() ||
$m->IsPet();
push(@b, $m);
}
}
return @b;
}
in <EQEMU_DIR>\quests\global\global_player.pl
Code:
sub EVENT_SAY {
$text =~ /#pingme/ ? plugin::Debug("PING") : # making sure this works
$text =~ /#healme/ ? BotHealMe() : # scripted 'bot heal' command
return;
}
sub BotHealMe {
foreach my $bot (plugin::GetGroupedBots($client)) {
# HasOwner() always returns 1 for a bot
return unless $bot && $bot->HasOwner();
# GetOwner() causes script to fail
# my $botOwner = $bot->GetOwner();
# GetOwnerID() always returns 0 for a bot
# this behavior is reflected in #showstats
my $ownerID = $bot->GetOwnerID();
my $botName = $bot->GetCleanName();
plugin::Debug("$botName is probably a bot.");
# returns value of bot_data.bot_id from database if mob is a bot
# NOTE: corresponding value will not exist in npc_types.id
my $botID = $bot->GetNPCTypeID();
# returns entityID
my $botEntityID = $bot->GetID();
# get the info we need from the database
# correct owner_id is found here
my $dbh = plugin::LoadMysql();
my $sql = "SELECT * FROM bot_data WHERE bot_id = $botID LIMIT 1";
my $res = plugin::SelectHashref($dbh, $sql);
# debugging vomit
foreach my $key (keys %$res) {
my $val = $res->{$key};
plugin::Debug("$key => $val");
}
# will not despawn a bot because
# the server expects nullptr or NPC as owner
# quest::depop($botID);
# will not spawn a bot because
# the server gets nullptr if npc_types.id not found
# quest::spawn2($botID,0,0,$x,$y,$z,$h);
# EXAMPLES OF LOGIC THAT MIGHT GO HERE
# 1. verify bot ownership
# 2. determine best available spell for situation
# 3. cast selected spell (see methods below)
# GetClass()
# GetCasterLevel()
# GetSpellIDFromSlot()
# IsBeneficialAllowed()
# CheckLoS()
# CastSPell()
# IsCasting()
# InterruptSpell()
# SpellFinished()
# CastingSpellID()
# NOTE: this should get a list of all spells available to a bot
#
# my $botLevel = $bot->GetLevel();
# my $sql = "SELECT * FROM bot_spells_entries WHERE npc_spells_id = (
# SELECT spells_id FROM bot_data WHERE bot_id = $botID LIMIT 1
# ) AND ($botLevel BETWEEN minlevel AND maxlevel)";
}
}