PDA

View Full Version : Bot clerics nuking and running oom on buffs


pfyon
04-18-2011, 06:31 PM
I threw this together to address my cleric bot nuking til oom during fights then having no mana to heal, and my char (a wizard) getting haste buffs and such which would make me wait longer between fights.


Index: zone/mob.h
================================================== =================
--- zone/mob.h (revision 187)
+++ zone/mob.h (working copy)
@@ -45,6 +45,10 @@
#define APPEAR_HEIGHT 0x001d
#define APPEAR_HP_TIC 0x0011

+#define ARCHETYPE_HYBRID 1
+#define ARCHETYPE_CASTER 2
+#define ARCHETYPE_MELEE 3
+
#define CON_GREEN 2
#define CON_LIGHTBLUE 18
#define CON_BLUE 4
@@ -655,6 +659,7 @@

// neotokyo: moved from client to use in NPC too
char GetCasterClass() const;
+ uint8 GetArchetype() const;
virtual sint32 CalcMaxMana();

inline virtual sint16 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; } // Quagmire - this is NOT the right math
Index: zone/botspellsai.cpp
================================================== =================
--- zone/botspellsai.cpp (revision 187)
+++ zone/botspellsai.cpp (working copy)
@@ -253,6 +253,29 @@
continue;
}

+ switch(tar->GetArchetype())
+ {
+ case ARCHETYPE_CASTER:
+ //TODO: probably more caster specific spell effects in here
+ if(IsEffectInSpell(selectedBotSpell.SpellId, SE_AttackSpeed) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ATK) ||
+ IsEffectInSpell(selectedBotSpell.SpellId, SE_STR) || IsEffectInSpell(selectedBotSpell.SpellId, SE_ReverseDS))
+ {
+ continue;
+ }
+ break;
+ case ARCHETYPE_MELEE:
+ //TODO: Include mana regen (breeze/clarity/etc), I don't know what spell effect it is
+ if(IsEffectInSpell(selectedBotSpell.SpellId, SE_IncreaseSpellHaste))
+ {
+ continue;
+ }
+ break;
+ case ARCHETYPE_HYBRID:
+ //Hybrids get all buffs
+ default:
+ break;
+ }
+
if(CheckSpellRecastTimers(this, itr->SpellIndex))
{

@@ -297,6 +320,12 @@
checked_los = true;
}

+ if(botClass == CLERIC && this->GetManaRatio() <= 50.0f)
+ {
+ //If we're at 50% mana or below, don't nuke as a cleric
+ break;
+ }
+
if(botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == NECROMANCER || botClass == PALADIN || botClass == RANGER || botClass == DRUID || botClass == CLERIC) {
if(tar->GetBodyType() == BT_Undead || tar->GetBodyType() == BT_SummonedUndead || tar->GetBodyType() == BT_Vampire)
botSpell = GetBestBotSpellForNukeByTargetType(this, ST_Undead);
Index: zone/mob.cpp
================================================== =================
--- zone/mob.cpp (revision 187)
+++ zone/mob.cpp (working copy)
@@ -663,6 +663,53 @@
}
}

+uint8 Mob::GetArchetype() const {
+ switch(class_)
+ {
+ case PALADIN:
+ case RANGER:
+ case SHADOWKNIGHT:
+ case BARD:
+ case BEASTLORD:
+ case PALADINGM:
+ case RANGERGM:
+ case SHADOWKNIGHTGM:
+ case BARDGM:
+ case BEASTLORDGM:
+ return ARCHETYPE_HYBRID;
+ break;
+ case CLERIC:
+ case DRUID:
+ case SHAMAN:
+ case NECROMANCER:
+ case WIZARD:
+ case MAGICIAN:
+ case ENCHANTER:
+ case CLERICGM:
+ case DRUIDGM:
+ case SHAMANGM:
+ case NECROMANCERGM:
+ case WIZARDGM:
+ case MAGICIANGM:
+ case ENCHANTERGM:
+ return ARCHETYPE_CASTER;
+ break;
+ case WARRIOR:
+ case MONK:
+ case ROGUE:
+ case BERSERKER:
+ case WARRIORGM:
+ case MONKGM:
+ case ROGUEGM:
+ case BERSERKERGM:
+ return ARCHETYPE_MELEE;
+ break;
+ default:
+ return ARCHETYPE_HYBRID;
+ break;
+ }
+}
+
void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) {
app->SetOpcode(OP_NewSpawn);
app->size = sizeof(NewSpawn_Struct);


This diff is against r1886, with some small modifications (I don't think any affect this diff, but correct me if you find otherwise).

It makes clerics stop nuking if they are at 50% mana or below. It also adds Mob::GetArchetype() which returns ARCHETYPE_MELEE, ARCHETYPE_CASTER, or ARCHETYPE_HYBRID. Bots will check against a list of spell effects before buffing the target to avoid giving unneeded buffs (eg clarity to a melee, or haste to a caster) to the char.

Right now I only implemented SE_AttackSpeed, SE_Atk, SE_STR, and SE_ReverseDS for casters, and SE_IncreaseSpellHaste for melees. Hybrids get all buffs.

I am hoping someone who knows more about the different spell effects could fill in the other buffs.

Possible future improvements: make the cleric sit and med if it's safe instead of just standing there when they're below 50% mana.

louis1016
04-28-2011, 08:16 PM
This is awesome. Something like this should really be put into the main eqemu code

Sneg
05-02-2011, 05:53 PM
We can make our bots on Desdemona not cast nukes orDots. Somebody helped us with the code. As soon as ven gets time I will ask for it to be posted on here. I hope with all of us we can get some nice bot code going.


Thanks
Protector
(GM/Dev for the Desdemona Server)

initium
05-03-2011, 12:08 AM
I like what you've done with the ARCHTYPEs. I had been considering doing something similar, but I wouldn't have time to start for a few weeks and I don't know enough C, so I couldn't do much more than pseudo-code anyway. That being said, I thought I'd throw this idea out there in case anyone was interested until I have time to work on it further:

The idea is roughly similar to ARCHTYPE changes, but it allows for a little more fine tuning from the client. Basically, I though it would be nice to have bot commands that lets the user assign roles in the group. For example:

#bot group assign tank OR #bot group assign healer (or maybe better: #bot group assign primehealer/secondhealer)

The AI could then take these roles into consideration. Let's say you have a group with a cleric and a druid. If you assign the cleric as primary healer and the druid as the secondary healer, the druid could spend more mana nuking and not worry as much about heals, while the cleric will always be sure to save some mana for heals. (for example, maybe the secondary healer will nule to 25% mana but the primary healer will never nuke below 50m) Or a group might want to have the cleric heal while the shaman debuffs, etc.

It might also be helpful to assign melee roles. If there's a primary tank, other melee bots would be careful not to steal aggro. This might also make enchanters easier to code. If the chanter has been given the crowd control role (or maybe it has that role by default), it can try to mez any aggro'd mobs except the one the assigned Tank is targeting. It could also help healing - primary healer focuses on primary tank while secondary healer heals other group members.

Like I said, in a couple weeks I'll gladly try to work out some of the AI (although most of my experience is with monks), but since the ARCHETYPEs mentioned in this thread were somewhat similar, I thought I'd throw this out there now

bad_captain
05-03-2011, 04:32 PM
bot group roles are are already at least partially in the code, there's just no support for them (yet). An idea i had for them was limiting buffs based on role (like the archtype idea), but would have required a database change, instead of hard coding spell ids. Limiting by spell effects might be okay, but there are so many combinations of spell effects, it may not be the best solution. I don't know. I.E. Higher levels of Yaulp contains haste, so a cleric wouldn't cast it on themselves. I'm sure there are other examples..


I have been having some pc problems, but think they are at least temporarily fixed, so I might be able to work on some more things soon.

louis1016
05-03-2011, 07:35 PM
it seems as of rev1888, the patch posted no longer works properly (on new server setups)

can someone update it?

pfyon
05-03-2011, 09:06 PM
Hmm, I was able to update up to 1888 with the patched code without issues...

louis1016
05-05-2011, 01:27 AM
I must be doing something wrong then. When I try to load the patch for my source code with tortisesvn, the mob.h and botspellsai.cpp seem to patch correctly but when it comes to mob.cpp I get the following error:

"The patch seems outdated! The file line
}
and the patchline
elseif (ns->spawn.class_= =BARDGM)
do not match!"


I havent made any changes myself to the mob.cpp file so I dont understand what the problem is. Any insight would be very appreciated.

lerxst2112
05-05-2011, 02:05 AM
It won't automatically apply to 1888 since it was made from 1886 and 1887 added ~10 lines to mob.cpp. It's a simple change though, just open mob.cpp, go to line 675 which should be right before Mob::CreateSpawnPacket and add the Mob::GetArchetype() function there right above it.

If you really wanted to, you could change the line in the patch file like this:

--- zone/mob.cpp (revision 187)
+++ zone/mob.cpp (working copy)
@@ -673,6 +673,53 @@

And it will apply too.