I found myself having to #findspell and #cast despite having the correct classes of bots in my group, and I wanted a way to make it seem more legitimate....
I don't know how big the appetite for having this would be so I am posting it here and not attempting to commit anything...
The following is some code you can add to your bots.cpp for the ability to beg for buffs from your currently grouped or targetted Bot character.
Syntax:
#bot cast <spell name> [target]
Spell name is wrapped in quotes
Target is an optional keyword to indicate you want the spell casted on your current target.
Examples:
#bot cast Virtue
#bot cast "Spirit of Wolf"
#bot cast "Circle of Great Divide"
#bot cast "Divine Intervention" target
What it does from a programming POV:
Finds the spell, then iterates group members and attempts to find someone whose classes spellbook has it (sufficient level is also checked). If you have an ungrouped bot (which you own) targetted, it will also search that bot's spellbook.
Self-only spells still work self-only, so if you do #bot cast "Illusion: Dark Elf" your enchanter will turn him/herself into a DE....
Future development
- add checks for item clickies from bot inventory
- allowing the pseudo activation of AAs....
Known issues
- if the bot is currently casting it will say "casting" but actually fail.
- if the bot is unable to cast, it will fail but not explain why.
Place this somewhere in the massive list of ifchecks for #bot found in bot.cpp:
Code:
// 2014-01-02 beg for buffs
// seveian
if ((!strcasecmp(sep->arg[1], "cast")) && (c->IsGrouped())) {
Mob *provider;
Mob *target;
uint32 providerClass = 0;
int spell_id = -1;
Group *g = c->GetGroup();
if (g) {
char sName[64];
char sCriteria[64];
strcpy(sCriteria, sep->arg[2]);
strupr(sCriteria);
for (int i = 0; i < SPDAT_RECORDS; i++) {
if (spells[i].name[0] != 0 && strlen(spells[i].name) > 1) {
strcpy(sName, spells[i].name);
strupr(sName);
if (strcmp(sName, sCriteria) == 0) {
spell_id = spells[i].id;
break;
}
}
}
if (spell_id < 1) {
c->Message(15, "Unable to find any known spell with that name.");
return;
}
target = c->CastToMob();
if (strcmp(sep->arg[3], "") != 0) {
// indicated we want to direct the cast at current target
// 2014-01-03
if (strcasecmp(sep->arg[3], "TARGET") == 0) {
if (c->GetTarget()) {
target = c->GetTarget()->CastToMob();
}
}
}
// If we have an owned bot targetted, we should also search its spellbook.
// 2014-01-03
if (c->GetTarget() && c->GetTarget()->IsBot() && c->GetTarget()->CastToBot()->GetBotOwner() == c) {
if (spells[spell_id].classes[c->GetTarget()->GetClass() - 1] <= c->GetTarget()->GetLevel()) {
provider = c->GetTarget()->CastToMob();
providerClass = c->GetTarget()->GetClass();
}
}
// If we already found a provider, skip the search via group members
if (providerClass < 1) {
for (int i = 0; i < MAX_GROUP_MEMBERS; i++) {
if (g->members[i] && g->members[i]->IsBot()) {
if (spells[spell_id].classes[g->members[i]->GetClass() - 1] <= g->members[i]->GetLevel()) {
provider = g->members[i]->CastToMob();
providerClass = g->members[i]->GetClass();
break;
}
}
}
}
if (providerClass < 1) {
c->Message(15, "Unfortunately, noone has the ability to cast that spell.");
return;
}
else {
char temp[100];
sprintf(temp, "Casting %s on %s...", spells[spell_id].name, target->GetName());
provider->Say(temp);
provider->CastSpell(spell_id, target->GetID(), 1, -1, -1);
return;
}
}
}