Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Bots

Development::Bots Forum for bots.

Reply
 
Thread Tools Display Modes
  #1  
Old 02-12-2013, 01:36 AM
c0ncrete's Avatar
c0ncrete
Dragon
 
Join Date: Dec 2009
Posts: 719
Default IsEngaged() and GetOwnerID() fixes

changes:
- Mob::IsEngaged() now returns AggroCount() for Clients
- updated handling of #bot spawn and #bot summon commands
- complete re-write of IsEngaged() logic in Bot::AI_Process()
- Bot::AI_Process() now allows bots to engage hostile, charmed clients
- implemented Bot::GetOwnerID() so Perl interface will work with bots

Code:
Index: bot.cpp
===================================================================
--- bot.cpp (revision 2503)
+++ bot.cpp (working copy)
@@ -3579,34 +3579,35 @@
        return;
    }
 
-   if(!IsEngaged()) {
-       if(GetFollowID()) {
-           if(BotOwner && BotOwner->CastToClient()->AutoAttackEnabled() && BotOwner->GetTarget() &&
-               BotOwner->GetTarget()->IsNPC() && BotOwner->GetTarget()->GetHateAmount(BotOwner)) {
-                   AddToHateList(BotOwner->GetTarget(), 1);
-                   
-                   if(HasPet())
-                       GetPet()->AddToHateList(BotOwner->GetTarget(), 1);
-           }
-           else {
-               Group* g = GetGroup();
-
-               if(g) {
-                   for(int counter = 0; counter < g->GroupCount(); counter++) {
-                       if(g->members[counter]) {
-                           if(g->members[counter]->IsEngaged() && g->members[counter]->GetTarget()) {
-                               AddToHateList(g->members[counter]->GetTarget(), 1);
-
-                               if(HasPet())
-                                   GetPet()->AddToHateList(g->members[counter]->GetTarget(), 1);
-
-                               break;
-                           }
-                       }
+   // if bot not currently engaged, determine if bot should engage anything
+   // NOTE: has been changed to allow bots to target hostile, charmed clients
+   if (!IsEngaged() && GetFollowID()) {
+       Mob *target = 0;
+       // if owner is engaged with an AI-controlled mob, get owner's target
+       if (BotOwner && BotOwner->CastToClient()->AutoAttackEnabled()) {
+           target = BotOwner->GetTarget();
+           if (target && !target->GetHateAmount(BotOwner)) { target = 0; }
+       }
+       // if group member is engaged with an AI-controlled mob, get member's target
+       else {
+           Group* group = GetGroup();
+           if (group) {
+               for (int i = 0; i < MAX_GROUP_MEMBERS; i++) {
+                   Mob* member = group->members[i];
+                   if (!member || !member->IsEngaged()) { continue; }
+                   if (!member->IsClient() || member->CastToClient()->AutoAttackEnabled() ) {
+                       Mob *target = member->GetTarget();
+                       if (target && target->GetHateAmount(member)) { break; }
+                       else if (target) { target = 0; }
                    }
                }
            }
        }
+       // engage target, if found
+       if (target) {
+           AddToHateList(target, 1);
+           if (HasPet()) { GetPet()->AddToHateList(target, 1); }
+       }
    }
 
    if(IsEngaged())
@@ -12317,7 +12316,7 @@
        }
 
        if(c->GetFeigned()) {
-           c->Message(0, "You can't summon bots while you are feigned.");
+           c->Message(0, "You can't spawn bots while you are feigned.");
            return;
        }
 
@@ -12325,7 +12324,7 @@
            BotRaids *br = entity_list.GetBotRaidByMob(c->CastToMob());
            if(br) {
                if(br->GetBotRaidAggro()) {
-                   c->Message(15, "You can't summon bots while you are engaged.");
+                   c->Message(15, "You can't spawn bots while you are engaged.");
                    return;
                }
            }
@@ -12333,22 +12332,21 @@
 
        if(c->IsGrouped()) {
            Group *g = entity_list.GetGroupByClient(c);
+           if (!g)
+               return;
            for (int i=0; i<MAX_GROUP_MEMBERS; i++) {
-               if(g && g->members[i] && !g->members[i]->qglobal && (g->members[i]->GetAppearance() != eaDead) 
-                   && (g->members[i]->IsEngaged() || (g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount()))) {
-                   c->Message(0, "You can't summon bots while you are engaged.");
+               Mob* member = g->members[i];
+               if (!member || member->qglobal)
                    return;
-               }
-               if(g && g->members[i] && g->members[i]->qglobal) {
+               if (member->IsEngaged() && member->GetAppearance() != eaDead) {
+                   c->Message(0, "You can't spawn bots while you are engaged.");
                    return;
                }
            }
        }
-       else {
-           if(c->GetAggroCount() > 0) {
-               c->Message(0, "You can't spawn bots while you are engaged.");
-               return;
-           }
+       else if (c->IsEngaged()) {
+           c->Message(0, "You can't spawn bots while you are engaged.");
+           return;
        }
 
        Mob* TempBotMob = entity_list.GetMobByBotID(botId);
@@ -15022,21 +15020,17 @@
                // Skip invalid group members.
                if(!g->members[i]) { continue; }
 
-               // Fail if current group member is client and has aggro
-               // OR has a popuplated hate list (assume bot).
-               if((g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount())
-               ||  g->members[i]->IsEngaged()) {
+               // Fail if current group member is engaged.
+               if(g->members[i]->IsEngaged()) {
                    c->Message(0, "You can't spawn bots while your group is engaged.");
                    return;
                }
            }
        }
        // Fail if ungrouped client has aggro.
-       else {
-           if(c->GetAggroCount() > 0) {
-               c->Message(0, "You can't spawn bots while you are engaged.");
-               return;
-           }
+       else if(c->IsEngaged()) {
+           c->Message(0, "You can't spawn bots while you are engaged.");
+           return;
        }
 
        // Parse botgroup name.
Index: bot.h
===================================================================
--- bot.h   (revision 2503)
+++ bot.h   (working copy)
@@ -427,6 +427,7 @@
    // "GET" Class Methods
    uint32 GetBotID() const { return _botID; }
    uint32 GetBotOwnerCharacterID() { return _botOwnerCharacterID; }
+    inline virtual uint16 GetOwnerID() const { return _botOwner ? _botOwner->GetID() : 0; }
    uint32 GetBotSpellID() { return npc_spells_id; }
    Mob* GetBotOwner() { return this->_botOwner; }
    uint32 GetBotArcheryRange();
Index: mob.cpp
===================================================================
--- mob.cpp (revision 2503)
+++ mob.cpp (working copy)
@@ -4477,3 +4477,14 @@
    }
    return false; 
 }
+
+bool Mob::IsEngaged() {
+
+    return (
+        IsClient() && !IsAIControlled()
+        // non-charmed client checks aggro count
+        ? CastToClient()->GetAggroCount() > 0
+        // npc, bot, merc, or charmed client checks hate list
+        : !hate_list.IsEmpty()
+    );
+}
Index: mob.h
===================================================================
--- mob.h   (revision 2503)
+++ mob.h   (working copy)
@@ -399,7 +399,7 @@
     Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);}
     Mob* GetHateRandom() { return hate_list.GetRandom();}
     Mob* GetHateMost() { return hate_list.GetMostHate();}
-    bool IsEngaged() { return(!hate_list.IsEmpty()); }
+    bool IsEngaged();
     bool HateSummon();
     void FaceTarget(Mob* MobToFace = 0);
     void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime(); 
@@ -415,6 +415,7 @@
     bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
     inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
     inline const uint32 LastChange() const { return pLastChange; }
@@ -586,7 +587,7 @@
     bool IsAnimation() const { return(typeofpet == petAnimation); }
     bool IsCharmed() const { return(typeofpet == petCharmed); }
     void SetOwnerID(uint16 NewOwnerID);
-    inline uint16 GetOwnerID() const { return ownerid; }
+    inline virtual uint16 GetOwnerID() const { return ownerid; }
     inline virtual bool HasOwner() { if(GetOwnerID()==0){return false;} return( entity_list.GetMob(GetOwnerID()) != 0); }
     inline virtual bool IsPet() { return(HasOwner() && !IsMerc()); }
     inline bool HasPet() const { if(GetPetID()==0){return false;} return (entity_list.GetMob(GetPetID()) != 0);}
compiled and tested.

$mob->IsEngaged() will now return true if $mob is a Client.
$mob->GetOwnerID() will now return owner's entity id if $mob is a Bot.

i had to re-write part of Bot::Process_AI() because the change to Mob::IsEngaged() was causing bots to run off and engage whatever the client had aggroed and targeted when it got within a certain range (may have been LoS, as i was on top of an incline), regardless if auto-attack enabled or not. the other parts that were changed were just streamlining logic by using the new IsEngaged(), and correcting a couple of message typos.

i'd probably look into adding IsEngaged() checks to the bot's idle casting logic (for heals/buffs) as well. as it stands, if you are idle and something is beating on you and you get healed or buffed by a bot, the casting bot aggros the aggressor, and then any other bots in the group follow suit. this obviously would allow for afk exp in some areas, and that's no fun!
__________________
I muck about @ The Forge.
say(rand 99>49?'try '.('0x'.join '',map{unpack 'H*',chr rand 256}1..2):'incoherent nonsense')while our $Noport=1;
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 01:30 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3