View Single Post
  #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