EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Development (https://www.eqemulator.org/forums/forumdisplay.php?f=590)
-   -   Feign Death Reliability Fix - Pet Fix - Feign Memory Overhaul (https://www.eqemulator.org/forums/showthread.php?t=20826)

unicorn97211 06-19-2006 08:41 AM

Feign Death Reliability Fix - Pet Fix - Feign Memory Overhaul
 
Feign Reliability Fix

Feign was failing outside our control.

client_process.cpp

In Client::Process

Change

Code:

#ifdef REVERSE_AGGRO
        //At this point, we are still connected, everything important has taken
        //place, now check to see if anybody wants to aggro us.
        if(ret && scanarea_timer.Check()) {
                entity_list.CheckClientAggro(this);
        }
#endif

to

Code:

#ifdef REVERSE_AGGRO
        //At this point, we are still connected, everything important has taken
        //place, now check to see if anybody wants to aggro us.
        if(ret && scanarea_timer.Check()) {
                // Everhood 6/15/06 - only check prox agro if we are not feigned
                if(!feigned){
                        entity_list.CheckClientAggro(this);
                }
        }
#endif

client.h

Change

Code:

inline bool    GetFeigned()        { return(GetAppearance() != eaDead ? false : feigned); }
To

Code:

        // EverHood 6/16/06
        // this cures timing issues cuz dead animation isn't done but server side feigning is?
        inline bool    GetFeigned()        {return feigned; }

Feigned Owner Pet Aggro Fix

Now that pets don't die when we feign, this stops us from inheriting any hate the pet does while we are fiegned.

i.e. If someone trains my pet with 20 mobs and I feign, when my pet dies the mobs should return home. Pre-Fix when my pet died the mobs would begin attacking me even though I am feigned.

attack.cpp

In Mob::AddToHateList

Change

Code:

        if (owner) { // Other has a pet, add him and it
                hate_list.Add(other, hate, 0, bFrenzy, !iBuffTic);
                hate_list.Add(owner, 1, damage, false, !iBuffTic);
        }

To

Code:

        if (owner) { // Other is a pet, add him and it
                hate_list.Add(other, hate, 0, bFrenzy, !iBuffTic);
                // EverHood 6/12/06
                // Can't add a feigned owner to hate list
                if(!owner->CastToClient()->GetFeigned()){
                        hate_list.Add(owner, 1, damage, false, !iBuffTic);
                }
        }

Improved Feign Memory

The current feign memory only allows an NPC to remember a single attacker and the attacker was being remembered 100% of the time. When the NPCs feign memory was being processed, the dice were thrown and the attacker got a chance to be forgotten and if he lost the roll enough times the attacker was eventually removed from feign memory. This was a problem since Necro A could aggro then feign then Necro B could aggro and feign overwriting Necro A in the feign memory allowing Necro A to get up when he shouldn't be able to yet. This did not follow live feign memory functionality in any way.

I've replaced the single slot feign memory with a feign memory list to hold multiple attackers. I've changed the code so that when you feign, if the NPC is level 35+, the dice are thrown and there is a 3 in 5 chance you will be added to the NPCs feign memory list. When the NPC processes its feign memory, any attacker on it that has stood up will be added back to that NPCs hate list. If the NPC reaches it's guard point (spawn point) it will clear all attackers from it's feign memory. If the NPC is on a grid and reaches waypoint 1 it will clear all attackers from it's feign memory.

npc.h

Change
Code:

        void        SetFeignMemory(const char* num) {feign_memory = num;}

        inline const char*    GetFeignMemory()        { return feign_memory; }

To
Code:

        // EverHood 6/14/06
        // Mobs need to be able to remember more than one feigned attacker
        void        AddFeignMemory(Client* attacker);
        void        RemoveFromFeignMemory(Client* attacker);
        void        ClearFeignMemory();

Change
Code:

        const char*        feign_memory;
To
Code:

        // EverHood 6/14/06
        LinkedList<const char*> feign_memory_list;

npc.cpp

In NPC::Process

Change
Code:

        //Feign Death Memory
        if (forget_timer.Check() && strstr(GetFeignMemory(),"0") == NULL) {
                Client* remember_client = entity_list.GetClientByName(GetFeignMemory());
                if (remember_client != 0)
                {
                        if (!remember_client->CastToClient()->GetFeigned())
                        {
                                AddToHateList(remember_client,1);
                                SetFeignMemory("0");
                                forgetchance = 0;
                        }
                        else if (rand()%100 <= forgetchance)
                        {
                                SetFeignMemory("0");
                                forgetchance = 0;
                        }
                        else
                        {
                                forgetchance += 1;
                        }
                }
                else
                {
                        SetFeignMemory("0");
                }
        }

To
Code:

        // EverHood - 6/14/06
        // Improved Feign Death Memory
        if (forget_timer.Check()) {
                LinkedListIterator<const char*> iterator(feign_memory_list);
                iterator.Reset();
                while(iterator.MoreElements())
                {
                        Client* remember_client = entity_list.GetClientByName(iterator.GetData());
                        if (!remember_client->CastToClient()->GetFeigned())
                        {
                                AddToHateList(remember_client,1);
                                iterator.RemoveCurrent();
                                // Personal humor
                                Emote("realizes %s wasn't really dead",remember_client->GetName());
                        }
                        iterator.Advance();
                }               
        }

Add
Code:

        // EverHood 6/14/06 - Feign Death memory
        void  NPC::AddFeignMemory(Client* attacker) {
                feign_memory_list.Insert(attacker->CastToMob()->GetName());
                // Leaving this debug in is kinda interesting...
                Emote("is suspicious of %ss unexpected death.",attacker->GetName());
        }
        void  NPC::RemoveFromFeignMemory(Client* attacker){
                LinkedListIterator<const char*> iterator(feign_memory_list);
                iterator.Reset();
                while(iterator.MoreElements())
                {
                        if(iterator.GetData() == attacker->GetName()){
                                // Leaving this debug in is kinda interesting...
                                this->CastToMob()->Emote("loses interest in %s.",attacker->GetName());
                                iterator.RemoveCurrent();
                        }
                        iterator.Advance();
                }
        }
        void  NPC::ClearFeignMemory(){
                if(feign_memory_list.Count()>0){
                        feign_memory_list.Clear();
                        // Leaving this debug in is kinda interesting...
                        this->CastToMob()->Emote("is no longer suspicious of the dead.");
                }
        }

entity.cpp

Change
Code:

void EntityList::ClearFeignAggro(Mob* targ)
{
        LinkedListIterator<NPC*> iterator(npc_list);
        iterator.Reset();
        while(iterator.MoreElements())
        {
                if (iterator.GetData()->CastToNPC()->CheckAggro(targ))
                {
                        iterator.GetData()->CastToNPC()->RemoveFromHateList(targ);
                        if (iterator.GetData()->CastToMob()->GetLevel() >= 35)
                                iterator.GetData()->CastToNPC()->SetFeignMemory(targ->CastToMob()->GetName());
                }
                iterator.Advance();
        }
}

To
Code:

void EntityList::ClearFeignAggro(Mob* targ)
{
        LinkedListIterator<NPC*> iterator(npc_list);
        iterator.Reset();
        while(iterator.MoreElements())
        {
                if (iterator.GetData()->CastToNPC()->CheckAggro(targ))
                {
                        iterator.GetData()->CastToNPC()->RemoveFromHateList(targ);
                        if (iterator.GetData()->CastToMob()->GetLevel() >= 35)
                                // EverHood 6/14/06
                                // the mob that hated us is 35+ so 3 outta 5 chance
                                // he adds us to its feign memory.
                                if(((float)rand()/RAND_MAX)*100 < 40){
                                        iterator.GetData()->CastToNPC()->AddFeignMemory(targ->CastToClient());
                                }
                }
                iterator.Advance();
        }
}

MobAI.cpp

In NPC::AI_DoMovement

Change
Code:

                                {        // are we there yet? then stop
                                        mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
                                        SetWaypointPause();
                                        SetAppearance(eaStanding, false);
                                        SetMoving(false);
                                        SendPosition();
                                }

To
Code:

                                {        // are we there yet? then stop
                                        mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
                                        SetWaypointPause();
                                        SetAppearance(eaStanding, false);
                                        SetMoving(false);
                                        SendPosition();
                                        // EverHood - wipe feign memory since we reached our first waypoint
                                        if(cur_wp==1){
                                                ClearFeignMemory();
                                        }
                                }

Change
Code:

                        mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z);
                        moved=false;

To
Code:

                        mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z);
                        // EverHood 6/18/06- we are home so clear our feign memory
                        ClearFeignMemory();
                        moved=false;

Feign Memory 2 Minute Wipe

I saw no code to handle this. When a client is feigned for 2 minutes, clear client off all feign memory lists in zone and let client know it is clear to stand up.


Client.h

Change
Code:

        Timer        fishing_timer;
#ifdef REVERSE_AGGRO
        Timer        scanarea_timer;
#endif

To
Code:

        Timer        fishing_timer;
        // EverHood 6/16/06
        // our 2 min everybody forgets you timer
        Timer        forget_timer;
#ifdef REVERSE_AGGRO
        Timer        scanarea_timer;
#endif

client.cpp

In Client::Client

Change
Code:

        fishing_timer(8000),
#ifdef REVERSE_AGGRO
        scanarea_timer(AIClientScanarea_delay),
#endif

To
Code:

        fishing_timer(8000),
        // EverHood 6/16/06
        forget_timer(120000),
#ifdef REVERSE_AGGRO
        scanarea_timer(AIClientScanarea_delay),
#endif

client_process.cpp

In Client::Process

Change
Code:

                OnDisconnect(true);
        }
       
       
        return ret;
}

To
Code:

                OnDisconnect(true);
        }
        // EverHood Feign Death 2 minutes and zone forgets you
        if (forget_timer.Check()) {
                forget_timer.Disable();
                entity_list.ClearZoneFeignAggro(this);
                Message(0,"Your enemies have forgotten your aggressions.");
        }
       
        return ret;
}

entity.h

Change
Code:

        void        ClearFeignAggro(Mob* targ);
        bool        Fighting(Mob* targ);

to
Code:

        void        ClearFeignAggro(Mob* targ);
        // Everhood 6/17/06
        void        ClearZoneFeignAggro(Client* targ);
        bool        Fighting(Mob* targ);

entity.cpp

Add
Code:

// EverHood 6/17/06
void EntityList::ClearZoneFeignAggro(Client* targ)
{
        LinkedListIterator<NPC*> iterator(npc_list);
        iterator.Reset();
        while(iterator.MoreElements())
        {
                iterator.GetData()->RemoveFromFeignMemory(targ);
                iterator.Advance();
        }
}


unicorn97211 06-19-2006 08:43 AM

Continued...
 
At the moment there are a couple issues left...

I can't be sure, but I didn't see any code to handle feign death actually failing. I saw nothing to generate the "player has fallen to the ground" message to a client which is what you see on live when a feign has failed. As it stands it appears feign will succeed 100% of the time. Feign failure chance should be based on skill for monks and for necro/sk it should be based on which feign death spell they cast, the higher level the feign spell, the lower the chance of failure.

When a mob is snared and I feign, he is able to walk. On live when a mob is snared with any necro snare Dooming Darkness or higher, an NPC cannot walk. The NPC can run at the reduced speed but the reduction in walkspeed from the snare should put the NPCs walkspeed at 0 or less leaving the NPC in essence rooted. I don't know if this is because walkspeeds in the database are too high or if the snare speed reduction is not high enough or if the speed reduction is not being applied to walkspeed etc. Perhaps FatherNitWit can point me in the right direction :)

fathernitwit 06-19-2006 12:23 PM

please make a unified diff of this so I can look at it for inclusion.

feign should be based on skill when it is not cast by a spell, see:
Client::Handle_OP_FeignDeath

as for snare, the spells apply a percent decrease in movement speed:
http://lucy.allakhazam.com/spell.htm...52&source=Live
and as such, will never result in a true 0 walk speed... Can you provide a 3rd party source to back up your claim of no walking when snared?

mattmeck 06-19-2006 01:07 PM

The only way a necro's snare acts as a root is when the mob is super low on HP 10% or less. Otherwise it went to the redused percentage.

rojadruid 06-19-2006 02:39 PM

Quote:

Originally Posted by mattmeck
The only way a necro's snare acts as a root is when the mob is super low on HP 10% or less. Otherwise it went to the redused percentage.

That is correct I play a necro on live. when the mob gets to 10% or lower then it stops moving.

unicorn97211 06-19-2006 05:31 PM

Quote:

Originally Posted by mattmeck
The only way a necro's snare acts as a root is when the mob is super low on HP 10% or less. Otherwise it went to the redused percentage.

This is true during combat however I think you are mistaking runspeed for walkspeed. Mobs never walk during combat they run to you. When fleeing they don't walk away, they run away from you. When running away from you unsnared they do suffer a negative runspeed and slow to a near walk which is probably a switch from running to walking at low hps.

What I am referring to is when a mob is snared during combat but then loses all hate and attempts to return home (or to its grid) at which point the mob is walking not running. Therefore walkspeed - snare reduction = stopped mob.

This is very very easy to reproduce on live. Log on a necro that is high enough level to use at least Dooming Darkness (lower level snares don't mitigate speed enough). Cast Dooming on any mob and snare it. After it walks to you (mob is actually running but snare reduces runspeed to a walk) feign death. You will notice that the mob will stand there NOT moving an inch until Dooming wears off at which point it will walk NOT run home. This happens with any mob including those buffed with SoW and uber fast running mobs in OOW like Ukun.

Also I would think just about any experienced player knows that groups have a designated snarer in groups to stop runners because a snared fleeing mob can't move. So again this is walkspeed being mitigated to 0.

This is key to split pulling. You see two mobs standing next to each other. You snare one and they both come at you, one running, one walking. You feign and the unsnared mob walks back home while the snared mob can't move and stays put. Once the unsnared mob reaches home and forgets all about you, you stand up, the snared mob remembers you either via feign memory or a tick of dmg from the snare and resumes it's attack only now his buddy is back home and out of aggro range leaving you with a single pull.

Any experienced Necro or SK who has done any split pulling can verify this.

On a side note, how many hps a mob has to get down to before it flees isn't a fixed percentage per say. My observation on live is that a mob will flee when the mobs hps reach a certain ratio to your own. I noticed this because while soloing with my necro, if I was buffed with conviction mobs would begin to flee with a higher amount of hps than they would if I were only self buffed.

If I were still subscribed to live I would do a series of screenshots to demonstrate both these points but for now I'll rely on the experienced necros in these forums to back me up since it's doubtful anyone here knows of the legendary necro Bodob of Club Fu on Bristlebane haha.

I started reading up on how to use TortoiseCVS to do a diff so hopefully I'll be able to post one shortly for Fathernitwit to review.

unicorn97211 06-19-2006 05:40 PM

Just hypothesizing here, but perhaps on live the amount snare mitigates runspeed is applied to walkspeed as follows:

Mob has a runspeed of 100 and walkspeed of 50 (just to make the math simple)

Snare is 50%. This would reduce his runspeed to 50 and as it sits now would reduce his walkspeed to 25.

My thinking is that because snare reduced runspeed by a value of 50, it also reduces walkspeed by a value of 50 therefore if the mob were to attemp to walk while snared his walkspeed would be 0.

Just trying to figure out how a percentage reduction could cause the behavior observed on live.

mattmeck 06-19-2006 06:47 PM

I use to fear kite and dot / FD kill on live for 6 years, mobs do walk back to there camp when snared and the necro is FD'd.



To test this so I didnt blindly state it from memory I logged on and tried it,

here is how it went.
Code:

Cast darkness,

hit harmshield,

waited for mob to smack me a few times

hit FD,

Mob stood there for a few seconds "corpse camping" then started to walk back to camp,

I stood up,

He came after me again,

I hit FD,

He stood there for a few seconds then started walking back.

Darkness wore off,

I stood up and he kept walking.

There ARE some NPC's that will continue to corpse camp for a long wile after they kill someone, and this includes when a necro FD's however this is NOT normal behavior.

mattmeck 06-19-2006 06:57 PM

tested on veeshan with a 70 necro in FG by the way.

wize_one 06-19-2006 10:49 PM

with my sk, pull with snare.. FD let other mobs path back, the one that is snared is locked in place.. once others are back at spawn point stand and snared mob follows you.

TekNoir 06-20-2006 01:47 AM

My account on Live is no longer active so I cannot possibly test any of this, but from memory as a necro...

When I would snare and then FD, mobs with a static spawn point would linger a moment (a predictable amount of time according to the specific mob involved) and then return. Occasionally there are specific mobs that want to "hold hands" for a little (or a lot) longer before they give up.

A relevant instance of this, from memory, was hunting the guards in Felwithe, specifically the first split. Snare one (with Dooming Darkness). Both guards always came. FD in the entrance hall once they were nearly on top of you. They both linger a moment and then they both turn to leave, but one of them moves far faster then the other. (Note: Occasionally the snared mob would stay just a little longer than the unsnared mob before attempting to return to spawn.) This enabled one to be back at spawn before the other ever reaches halfway back. Stand. Kill the snared one who immediately comes back for you and you've got your mobs split.

Having said all of that, I have also had instances where static spawn mobs still taking damage would refuse to go back at all. They wouldn't attack me, but they'd just stand there for quite some time after their buddies had all gone back home. They would usually return to spawn after my snare ran out. I believe (and have absolutely no facts to back this hypothesis up) that this phenomenon is related to the fact that our snares are also DOTs and that they stick around because of the damage and not because of the snare itself. Or maybe a combination of the two? But this was a rare occurrence on static spawned mobs. Nearly all of them after a period of time give up and go back home.

The same cannot be said for "roaming" mobs. Don't confuse this with "patrolling" mobs. Roaming mobs nearly always stayed right on top of me after a snare followed by a FD. This was useful for soloing in places like the Grey where most of the mobs around the perimeter of the zone roam around. I could snare one and it (usually a few) would come running. I could FD and whichever mob I had snared would stay put while after a few moments its friends would begin to roam around again. The bad thing is that the roaming mobs don't like to forget you as easily as patrolling or static spawned mobs, so I usually had to wait until my snare had worn off to stand back up and even then the mob's friends would sometimes come back to haunt me, seemingly from clear across the zone even!

Patrolling mobs would sometimes stay with me, but most often not and they tended to be a little slower than the other types of mobs about returning to their patrol when snared. They behaved much like statically spawned mobs.

From memory, there were also entire zones (or segments of a zone) that seemed to behave just a little different from what I would expect. Mobs that took significantly longer to forget about me or mobs that liked to cuddle longer than what I would expect. There are places where "mob mentality" rules and no matter what you do, you're coming home with multiples. It was all very complex and involved character level, pathing in that location, terrain (or line-of-sight), mob assist, and so on and so forth. There have been a million guides written up about the nuances of leveling whichever character in this or that particular place.

Anyhow. This is all from memory and having not played in a couple years that memory could be a little rusty. It will nonetheless give those who still have live accounts something more substantial to test on, rather than testing on a few mobs in very specific (unique) locations and calling it the night.

RangerDown 06-20-2006 02:02 PM

Quote:

believe (and have absolutely no facts to back this hypothesis up) that this phenomenon is related to the fact that our snares are also DOTs and that they stick around because of the damage and not because of the snare itself. Or maybe a combination of the two? But this was a rare occurrence on static spawned mobs.
While I'm not 100% certain either, I'm going to have to take the other side and say it's because of the snare. Most snares take enough speed off a mob that if it reduces to walk-speed, it's standing still. Once a mob is no longer chasing you, it slows back down to walk-speed. It can't return to its spawn point because it can't move when it's on walk speed with the snare still effective.

It made for a nice revenge when a monk tried to FD train a skeleton on me. I positioned myself on top of the monk, rooted the skeleton, cast Ensnare on it, then backed up and proceeded to sit and begin camping out. While the countdown was in progress, I informed the monk that once I was camped out of the picture, the skelly would be on walk speed, and my Ensnare would effectively make the skelly stand still. I then informed Mr. Monk that the Ensnare was 14 minutes long, so he'd best get comfortable. Ain't I a stinker :D

unicorn97211 06-21-2006 01:56 PM

Unified Diff
 
Code:

--- C:\Code\EQEmu800\zone\attack.cpp        Wed Jun 07 18:29:26 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\attack.cpp        Sun Jun 18 10:30:31 2006
@@ -1727,10 +1727,14 @@
       
        if (other == myowner)
                return;
-        if (owner) { // Other has a pet, add him and it
+        if (owner) { // Other is a pet, add him and it
                hate_list.Add(other, hate, 0, bFrenzy, !iBuffTic);
+                // EverHood 6/12/06
+                // Can't add a feigned owner to hate list
+                if(!owner->CastToClient()->GetFeigned()){
                hate_list.Add(owner, 1, damage, false, !iBuffTic);
        }
+        }
        else { // Other has no pet, add other
                hate_list.Add(other, hate, damage, false, !iBuffTic);
        }
@@ -1741,8 +1745,9 @@
                        myowner->hate_list.Add(other, 1, 0, bFrenzy);
        }
        if (!wasengaged) {
-                if(IsNPC() && other->CastToClient())
+                if(IsNPC() && other->CastToClient()){
                        parse->Event(EVENT_AGGRO, this->GetNPCTypeID(), 0, CastToNPC(), other);
+                }
                AI_Event_Engaged(other, iYellForHelp);
                adverrorinfo = 8293;
        }
@@ -2068,9 +2073,21 @@
                else
                        hate = damage; // normal aggro for everything else
               
-                mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, attacker->GetName());
-                // now add done damage to the hate list
+                // EverHood 6/12/06
+                if(attacker->IsClient()){
+                        // check if attacker is feigned
+                        if(attacker->CastToClient()->GetFeigned()){
+                                hate = -1; // no hate for feigned attackers
+                        }
+                }
+               
+                if(hate != -1){
+                        // attacker generated some hate so
+                        // add damage done by attacker to the hate list
+                        // mlog(COMBAT__HITS, "Generating %d hate towards %s", hate, attacker->GetName());
                AddToHateList(attacker, hate, damage, true, false, iBuffTic);
+                }
+
        }
   
        if(damage > 0) {
--- C:\Code\EQEmu800\zone\client.cpp        Fri May 12 19:35:58 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\client.cpp        Sun Jun 18 03:11:40 2006
@@ -143,6 +143,8 @@
        ooc_timer(1000),
        shield_timer(500),
        fishing_timer(8000),
+        // EverHood 6/16/06
+        forget_timer(120000),
 #ifdef REVERSE_AGGRO
        scanarea_timer(AIClientScanarea_delay),
 #endif
@@ -1763,13 +1765,25 @@
 }
 
 void Client::SetFeigned(bool in_feigned) {
+        feigned=in_feigned;
        if (in_feigned)
        {
+// EverHood 6/12/06
+// Live doesn't kill pets when owner feigns anymore
+// Hasn't since mobs quit agroing pets.
+// If you're worried necros will Feign and let pet solo
+// mobs turn this on in Features.h.
+// *Note: If a necro pet can solo an xp bearing mob while owner is FD
+//                  that mob needs it's stats bumped.
+#ifdef KILL_PET_ON_FEIGN
                SetPet(0);
+#endif
                SetHorseId(0);
                entity_list.ClearFeignAggro(this);
+                forget_timer.Start(120000);
+        }else{
+                forget_timer.Disable();
        }
-        feigned=in_feigned;
  }
 
 void Client::LogMerchant(Client* player, Mob* merchant, Merchant_Sell_Struct* mp, const Item_Struct* item, bool buying)
--- C:\Code\EQEmu800\zone\client.h        Wed Jun 07 18:29:26 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\client.h        Mon Jun 19 14:52:37 2006
@@ -512,7 +512,11 @@
        inline void        SetBecomeNPCLevel(int8 level) { npclevel = level; }
        bool        LootToStack(uint32 itemid);
        void        SetFeigned(bool in_feigned);
-        inline bool    GetFeigned()        { return(GetAppearance() != eaDead ? false : feigned); }
+        // EverHood 6/16/06
+        /// this cures timing issues cuz dead animation isn't done but server side feigning is?
+        inline bool    GetFeigned()        {return(feigned); }
+
+        //inline bool    GetFeigned()        { return(GetAppearance() != eaDead ? false : feigned); }
        EQStreamInterface* Connection() { return eqs; }
 #ifdef PACKET_PROFILER
        void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); }
@@ -768,11 +772,13 @@
        Timer        ooc_timer;
        Timer        shield_timer;
        Timer        fishing_timer;
+        // EverHood 6/16/06
+        // our 2 min everybody forgets you timer
+        Timer        forget_timer;
 #ifdef REVERSE_AGGRO
        Timer        scanarea_timer;
 #endif
        Timer        tribute_timer;
-       
 #ifdef PACKET_UPDATE_MANAGER
        UpdateManager update_manager;
 #endif
--- C:\Code\EQEmu800\zone\client_process.cpp        Mon Apr 17 06:59:14 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\client_process.cpp        Sun Jun 18 02:07:29 2006
@@ -534,8 +534,11 @@
        //At this point, we are still connected, everything important has taken
        //place, now check to see if anybody wants to aggro us.
        if(ret && scanarea_timer.Check()) {
+                // Everhood 6/15/06 - only check prox agro if we are not feigned
+                if(!feigned){
                entity_list.CheckClientAggro(this);
        }
+        }
 #endif       
       
        if (client_state != CLIENT_LINKDEAD && (client_state == CLIENT_ERROR || client_state == DISCONNECTED || client_state == CLIENT_KICKED || !eqs->CheckState(ESTABLISHED))) {
@@ -576,7 +579,12 @@
                }
                OnDisconnect(true);
        }
-       
+        // EverHood Feign Death 2 minutes and zone forgets you
+        if (forget_timer.Check()) {
+                forget_timer.Disable();
+                entity_list.ClearZoneFeignAggro(this);
+                Message(0,"Your enemies have forgotten your aggressions.");
+        }
       
        return ret;
 }
--- C:\Code\EQEmu800\zone\entity.cpp        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\entity.cpp        Sun Jun 18 09:54:40 2006
@@ -2475,8 +2475,24 @@
                {
                        iterator.GetData()->CastToNPC()->RemoveFromHateList(targ);
                        if (iterator.GetData()->CastToMob()->GetLevel() >= 35)
-                                iterator.GetData()->CastToNPC()->SetFeignMemory(targ->CastToMob()->GetName());
+                                // EverHood 6/14/06
+                                // the mob that hated us is 35+ so 3 outta 5 chance
+                                // he adds us to its feign memory
+                                if(((float)rand()/RAND_MAX)*100 < 40){
+                                        iterator.GetData()->CastToNPC()->AddFeignMemory(targ->CastToClient());
                }
+                }
+                iterator.Advance();
+        }
+}
+// EverHood 6/17/06
+void EntityList::ClearZoneFeignAggro(Client* targ)
+{
+        LinkedListIterator<NPC*> iterator(npc_list);
+        iterator.Reset();
+        while(iterator.MoreElements())
+        {
+                iterator.GetData()->RemoveFromFeignMemory(targ);
                iterator.Advance();
        }
 }
--- C:\Code\EQEmu800\zone\entity.h        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\entity.h        Sun Jun 18 02:07:29 2006
@@ -251,6 +251,8 @@
 
    void    Process();
        void        ClearFeignAggro(Mob* targ);
+        // Everhood 6/17/06
+        void        ClearZoneFeignAggro(Client* targ);
       
        bool        Fighting(Mob* targ);
        void    RemoveFromHateLists(Mob* mob, bool settoone = false);
--- C:\Code\EQEmu800\zone\MobAI.cpp        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\MobAI.cpp        Sun Jun 18 13:33:22 2006
@@ -942,6 +942,10 @@
                                        SetAppearance(eaStanding, false);
                                        SetMoving(false);
                                        SendPosition();
+                                        // EverHood - wipe feign memory since we reached our first waypoint
+                                        if(cur_wp==1){
+                                                ClearFeignMemory();
+                                        }
                                }
                                else
                                {        // not at waypoint yet, so keep moving
@@ -969,6 +973,8 @@
      {
                if(moved) {
                        mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z);
+                        // EverHood 6/18/06
+                        ClearFeignMemory();
                        moved=false;
                        SetMoving(false);
                        SendPosition();


unicorn97211 06-21-2006 01:57 PM

Unified Diff (Cont)
 
Code:

--- C:\Code\EQEmu800\zone\npc.cpp        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\npc.cpp        Mon Jun 19 14:52:37 2006
@@ -481,30 +481,22 @@
    if (IsStunned()||IsMezzed())
            return true;
 
-        //Feign Death Memory
-        if (forget_timer.Check() && strstr(GetFeignMemory(),"0") == NULL) {
-                Client* remember_client = entity_list.GetClientByName(GetFeignMemory());
-                if (remember_client != 0)
+        // EverHood - 6/14/06
+        // Improved Feign Death Memory
+        if (forget_timer.Check()) {
+                LinkedListIterator<const char*> iterator(feign_memory_list);
+                iterator.Reset();
+                while(iterator.MoreElements())
                {
+                        Client* remember_client = entity_list.GetClientByName(iterator.GetData());
                        if (!remember_client->CastToClient()->GetFeigned())
                        {
                                AddToHateList(remember_client,1);
-                                SetFeignMemory("0");
-                                forgetchance = 0;
+                                iterator.RemoveCurrent();
+                                // Personal humor
+                                Emote("realizes %s wasn't really dead",remember_client->GetName());
                        }
-                        else if (rand()%100 <= forgetchance)
-                        {
-                                SetFeignMemory("0");
-                                forgetchance = 0;
-                        }
-                        else
-                        {
-                                forgetchance += 1;
-                        }
-                }
-                else
-                {
-                        SetFeignMemory("0");
+                        iterator.Advance();
                }
        }
       
@@ -519,6 +511,32 @@
    return true;
 }
 
+        // EverHood 6/14/06 - FD memory
+        void  NPC::AddFeignMemory(Client* attacker) {
+                feign_memory_list.Insert(attacker->CastToMob()->GetName());
+                Emote("is suspicious of %ss unexpected death.",attacker->GetName());
+        }
+        void  NPC::RemoveFromFeignMemory(Client* attacker){
+                LinkedListIterator<const char*> iterator(feign_memory_list);
+                iterator.Reset();
+                while(iterator.MoreElements())
+                {
+                        if(iterator.GetData() == attacker->GetName()){
+                                // Leaving this debug in is kinda interesting...
+                                this->CastToMob()->Emote("loses interest in %s.",attacker->GetName());
+                                iterator.RemoveCurrent();
+                        }
+                        iterator.Advance();
+                }
+        }
+        void  NPC::ClearFeignMemory(){
+                if(feign_memory_list.Count()>0){
+                        feign_memory_list.Clear();
+                        // Leaving this debug in is kinda interesting...
+                        this->CastToMob()->Emote("is no longer suspicious of the dead.");
+                }
+        }
+
 int32 NPC::CountLoot() {
        return(itemlist.size());
 }
--- C:\Code\EQEmu800\zone\npc.h        Sun Mar 19 20:04:48 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\npc.h        Sun Jun 18 01:55:57 2006
@@ -161,7 +161,15 @@
    bool    IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);}
 
        void        SetNPCFactionID(sint32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }
-        void        SetFeignMemory(const char* num) {feign_memory = num;}
+        // EverHood 6/14/06
+        // Mobs need to be able to remember more than one feigned attacker
+        void        AddFeignMemory(Client* attacker);
+        void        RemoveFromFeignMemory(Client* attacker);
+        void        ClearFeignMemory();
+
+        void        SetFeignMemory(const char* num) {
+                feign_memory = num;
+        }
 
        inline const char*    GetFeignMemory()        { return feign_memory; }
 
@@ -251,7 +259,11 @@
       
        int16        max_dmg;
        int16        min_dmg;
+        // EverHood 6/14/06
+        LinkedList<const char*> feign_memory_list;
+
        const char*        feign_memory;
+
        int8    forgetchance;
       
        //pet crap:


unicorn97211 06-21-2006 02:01 PM

Above are the diffs for the Feign Death changes. I just resubscribed to live to do testing on the issue of "can snared mobs walk". I will be testing several mobs in several zones and will post my results. Should we start a seperate thread for this debate since it's not covered by the proposed fixes listed in this one? (The FD fixes in this thread do not effect movement speed in any way)

I used WinMerge for the first time to generate the unified diff so if I did something wrong , let me know.

fathernitwit 06-23-2006 01:46 PM

hey,

diffs look good.

A few comments on the code:
- where you do if(!owner->CastToClient()->GetFeigned()){, you need to be sure that owner is a client first, use if(owner->IsClient() && !owner->Cast....
- make the 120000 value part of the timer duration enum in features.h
- you should check feigned before you call scanarea_timer.Check... so put the check between 'ret and 'scanarea_timer.Check()', also call GetFeigned instead of using `feigned` directly.
- Please do not use the LinkedList data structure, we are doing everything we can to get rid of that, use the STL vector or list.. further, never store string pointers in a data structure like that unless you can garuntee the existence of that pointer until the list is cleared (which you cannot in this case). Use a STL string object in the future... BUT you should not be storing the character's name in the list anyhow, its use their ->CharacterID() and then use GetClientByCharID
- Do not use rand()/RAND_MAX, use MakeRandomInt/Float.
- Do not use CastToMob() unless you truely have a pointer to an Entity object (basically nowhere)... everything else is already derived from a Mob, and does not require a cast.
- Your use of CastToNPC() in ClearFeignAggro is unnescecary, your iterator is already an NPC *... casting is bad, avoid at all costs.
- In ClearFeignAggro, you need to either check to see if the object is a Client object before calling CastToClient for AddFeignMemory, or you need to make ClearFeignAggro take a Client *, and have its caller check it.
- please remove depricated functions, in particular SetFeignMemory and the feign_memory member variable)
- Please only send emotes/messages to the client when they match what live sends, if you add other things for debugging, please use the _log facility instead (use #logs to get messages in game)

unicorn97211 06-23-2006 02:56 PM

I'll work on these changes over the weekend and see how far I can get. Using the STL stuff will be something new to learn but the rest of it seems straightforward. Thanks for the feedback on my rusty c skills :)

Will post a new diff when I have another draft ready.

unicorn97211 06-25-2006 05:55 PM

Latest Diff
 
Here is the latest diffs after making the recommended changes.

Code:

--- C:\Code\EQEmu800\zone\attack.cpp        Wed Jun 07 18:29:26 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\attack.cpp        Sun Jun 25 22:25:28 2006
@@ -1727,10 +1727,18 @@
       
        if (other == myowner)
                return;
-        if (owner) { // Other has a pet, add him and it
+        if (owner) { // Other is a pet, add him and it
                hate_list.Add(other, hate, 0, bFrenzy, !iBuffTic);
+                // EverHood 6/12/06
+                // Can't add a feigned owner to hate list
+                if(owner->IsClient()){
+                        if(!owner->CastToClient()->GetFeigned()){
                hate_list.Add(owner, 1, damage, false, !iBuffTic);
        }
+                }else{
+                        hate_list.Add(owner, 1, damage, false, !iBuffTic);
+                }
+        }
        else { // Other has no pet, add other
                hate_list.Add(other, hate, damage, false, !iBuffTic);
        }
@@ -2068,9 +2077,21 @@
                else
                        hate = damage; // normal aggro for everything else
               
-                mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, attacker->GetName());
-                // now add done damage to the hate list
+                // EverHood 6/12/06
+                if(attacker->IsClient()){
+                        // check if attacker is feigned
+                        if(attacker->CastToClient()->GetFeigned()){
+                                hate = -1; // no hate for feigned attackers
+                        }
+                }
+               
+                if(hate != -1){
+                        // attacker generated some hate so
+                        // add damage done by attacker to the hate list
+                        // mlog(COMBAT__HITS, "Generating %d hate towards %s", hate, attacker->GetName());
                AddToHateList(attacker, hate, damage, true, false, iBuffTic);
+                }
+
        }
   
        if(damage > 0) {
--- C:\Code\EQEmu800\zone\client.cpp        Fri May 12 19:35:58 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\client.cpp        Sun Jun 25 17:55:21 2006
@@ -143,6 +143,8 @@
        ooc_timer(1000),
        shield_timer(500),
        fishing_timer(8000),
+        // EverHood 6/16/06
+        forget_timer(0),
 #ifdef REVERSE_AGGRO
        scanarea_timer(AIClientScanarea_delay),
 #endif
@@ -1763,13 +1765,25 @@
 }
 
 void Client::SetFeigned(bool in_feigned) {
+        feigned=in_feigned;
        if (in_feigned)
        {
+// EverHood 6/12/06
+// Live doesn't kill pets when owner feigns anymore
+// Hasn't since mobs quit agroing pets.
+// If you're worried necros will Feign and let pet solo
+// mobs turn this on in Features.h.
+// *Note: If a necro pet can solo an xp bearing mob while owner is FD
+//                  that mob needs it's stats bumped.
+#ifdef KILL_PET_ON_FEIGN
                SetPet(0);
+#endif
                SetHorseId(0);
                entity_list.ClearFeignAggro(this);
+                forget_timer.Start(FeignMemoryDuration);
+        }else{
+                forget_timer.Disable();
        }
-        feigned=in_feigned;
  }
 
 void Client::LogMerchant(Client* player, Mob* merchant, Merchant_Sell_Struct* mp, const Item_Struct* item, bool buying)
--- C:\Code\EQEmu800\zone\client.h        Wed Jun 07 18:29:26 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\client.h        Sun Jun 25 22:29:31 2006
@@ -512,7 +512,9 @@
        inline void        SetBecomeNPCLevel(int8 level) { npclevel = level; }
        bool        LootToStack(uint32 itemid);
        void        SetFeigned(bool in_feigned);
-        inline bool    GetFeigned()        { return(GetAppearance() != eaDead ? false : feigned); }
+        // EverHood 6/16/06
+        /// this cures timing issues cuz dead animation isn't done but server side feigning is?
+        inline bool    GetFeigned()        {return(feigned); }
        EQStreamInterface* Connection() { return eqs; }
 #ifdef PACKET_PROFILER
        void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); }
@@ -768,6 +770,9 @@
        Timer        ooc_timer;
        Timer        shield_timer;
        Timer        fishing_timer;
+        // EverHood 6/16/06
+        // our 2 min everybody forgets you timer
+        Timer        forget_timer;
 #ifdef REVERSE_AGGRO
        Timer        scanarea_timer;
 #endif
--- C:\Code\EQEmu800\zone\client_process.cpp        Mon Apr 17 06:59:14 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\client_process.cpp        Sun Jun 25 01:29:00 2006
@@ -533,7 +533,8 @@
 #ifdef REVERSE_AGGRO
        //At this point, we are still connected, everything important has taken
        //place, now check to see if anybody wants to aggro us.
-        if(ret && scanarea_timer.Check()) {
+        // Everhood 6/15/06 - only if client is not feigned
+        if(ret && !GetFeigned() && scanarea_timer.Check()) {
                entity_list.CheckClientAggro(this);
        }
 #endif       
@@ -576,7 +577,12 @@
                }
                OnDisconnect(true);
        }
-       
+        // EverHood Feign Death 2 minutes and zone forgets you
+        if (forget_timer.Check()) {
+                forget_timer.Disable();
+                entity_list.ClearZoneFeignAggro(this);
+                Message(0,"Your enemies have forgotten you!");
+        }
       
        return ret;
 }
--- C:\Code\EQEmu800\zone\entity.cpp        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\entity.cpp        Sun Jun 25 21:28:04 2006
@@ -2471,12 +2471,31 @@
        iterator.Reset();
        while(iterator.MoreElements())
        {
-                if (iterator.GetData()->CastToNPC()->CheckAggro(targ))
+                if (iterator.GetData()->CheckAggro(targ))
                {
-                        iterator.GetData()->CastToNPC()->RemoveFromHateList(targ);
-                        if (iterator.GetData()->CastToMob()->GetLevel() >= 35)
-                                iterator.GetData()->CastToNPC()->SetFeignMemory(targ->CastToMob()->GetName());
+                        iterator.GetData()->RemoveFromHateList(targ);
+                        // EverHood 6/24/06
+                        // For client targets if the mob that hated us is 35+
+                        // there is a 3 outta 5 chance he adds us to feign memory
+                        if(targ->IsClient()){
+                                if (iterator.GetData()->GetLevel() >= 35){
+                                        if(MakeRandomInt(1,100)<=60){
+                                                iterator.GetData()->AddFeignMemory(targ->CastToClient());
                }
+                                }
+                        }
+                }
+                iterator.Advance();
+        }
+}
+// EverHood 6/17/06
+void EntityList::ClearZoneFeignAggro(Client* targ)
+{
+        LinkedListIterator<NPC*> iterator(npc_list);
+        iterator.Reset();
+        while(iterator.MoreElements())
+        {
+                iterator.GetData()->RemoveFromFeignMemory(targ);
                iterator.Advance();
        }
 }
--- C:\Code\EQEmu800\zone\entity.h        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\entity.h        Sun Jun 18 02:07:29 2006
@@ -251,6 +251,8 @@
 
    void    Process();
        void        ClearFeignAggro(Mob* targ);
+        // Everhood 6/17/06
+        void        ClearZoneFeignAggro(Client* targ);
       
        bool        Fighting(Mob* targ);
        void    RemoveFromHateLists(Mob* mob, bool settoone = false);
--- C:\Code\EQEmu800\zone\features.h        Sat Mar 18 21:09:26 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\features.h        Sun Jun 25 22:35:20 2006
@@ -207,7 +207,8 @@
        AIassistcheck_delay = 3000,                //now often a fighting NPC will yell for help
        ClientProximity_interval = 1000,
        Tribute_duration = 600000,
-        ZoneTimerResolution = 3                        //sleep time between zone main loop runs (milliseconds)
+        ZoneTimerResolution = 3,                        //sleep time between zone main loop runs (milliseconds)
+        FeignMemoryDuration = 120000 // EverHood - Duration player must feign death to clear zonewide agro.
 };
 
 enum {        //some random constants
@@ -262,7 +263,7 @@
 #define MIN_FACTION -1500
 
 //The Level Cap:
-#define LEVEL_CAP 65                //hard cap is 127
+#define LEVEL_CAP 70        //hard cap is 127
 
 //the square of the maximum range at whihc you could possibly use NPC services (shop, tribute, etc)
 #define USE_NPC_RANGE2 200*200                //arbitrary right now
--- C:\Code\EQEmu800\zone\MobAI.cpp        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\MobAI.cpp        Sun Jun 25 21:55:28 2006
@@ -938,16 +938,30 @@
                                if (cur_wp_x == GetX() && cur_wp_y == GetY())
                                {        // are we there yet? then stop
                                        mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid());
                                        SetWaypointPause();
                                        SetAppearance(eaStanding, false);
                                        SetMoving(false);
                                        SendPosition();
+                                        // EverHood - wipe feign memory since we reached our first waypoint
+                                        if(cur_wp==1){
+                                                ClearFeignMemory();
+                                        }
                                }
@@ -969,6 +983,8 @@
      {
                if(moved) {
                        mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z);
+                        // EverHood 6/18/06
+                        ClearFeignMemory();
                        moved=false;
                        SetMoving(false);
                        SendPosition();


unicorn97211 06-25-2006 05:56 PM

Diffs (Cont)
 
Code:

--- C:\Code\EQEmu800\zone\npc.cpp        Wed May 31 21:13:32 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\npc.cpp        Sun Jun 25 01:29:00 2006
@@ -233,8 +233,6 @@
        pet_spell_id = 0;
       
        delaytimer = false;
-    feign_memory = "0";
-        forgetchance = 0;
        attack_event = false;
        attack_speed = d->attack_speed;
 
@@ -481,30 +479,19 @@
    if (IsStunned()||IsMezzed())
            return true;
 
-        //Feign Death Memory
-        if (forget_timer.Check() && strstr(GetFeignMemory(),"0") == NULL) {
-                Client* remember_client = entity_list.GetClientByName(GetFeignMemory());
-                if (remember_client != 0)
+        // EverHood - 6/14/06
+        // Improved Feign Death Memory
+        if (forget_timer.Check() && !feign_memory_list.empty()) {
+                std::list<int32>::iterator RememberedCharID;
+                for (RememberedCharID=feign_memory_list.begin(); RememberedCharID != feign_memory_list.end(); RememberedCharID++)
+                {
+                        Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID);
+                        if (!remember_client->GetFeigned())
                {
-                        if (!remember_client->CastToClient()->GetFeigned())
-                        {
-                                AddToHateList(remember_client,1);
-                                SetFeignMemory("0");
-                                forgetchance = 0;
-                        }
-                        else if (rand()%100 <= forgetchance)
-                        {
-                                SetFeignMemory("0");
-                                forgetchance = 0;
-                        }
-                        else
-                        {
-                                forgetchance += 1;
-                        }
+                                AddToHateList(remember_client->CastToMob(),1);
+                                feign_memory_list.remove(*RememberedCharID);
+                                break;
                }
-                else
-                {
-                        SetFeignMemory("0");
                }
        }
       
@@ -519,6 +506,22 @@
    return true;
 }
 
+        // EverHood 6/14/06 - FD memory
+        void  NPC::AddFeignMemory(Client* attacker) {
+                feign_memory_list.push_back(attacker->CharacterID());
+        }
+        void  NPC::RemoveFromFeignMemory(Client* attacker){
+                if(!feign_memory_list.empty()){
+                        int32 attacker_charid = attacker->CharacterID();
+                        feign_memory_list.remove(attacker_charid);
+                }
+        }
+        void  NPC::ClearFeignMemory(){
+                if(!feign_memory_list.empty()){
+                        feign_memory_list.clear();
+                }
+        }
+
 int32 NPC::CountLoot() {
        return(itemlist.size());
 }
--- C:\Code\EQEmu800\zone\npc.h        Sun Mar 19 20:04:48 2006
+++ C:\EQEmuSP\Source\0.7.0\zone\npc.h        Sun Jun 25 01:29:00 2006
@@ -161,9 +161,11 @@
    bool    IsOnHatelist(Mob*p) { return hate_list.IsOnHateList(p);}
 
        void        SetNPCFactionID(sint32 in) { npc_faction_id = in; database.GetFactionIdsForNPC(npc_faction_id, &faction_list, &primary_faction); }
-        void        SetFeignMemory(const char* num) {feign_memory = num;}
-
-        inline const char*    GetFeignMemory()        { return feign_memory; }
+        // EverHood 6/14/06
+        // Mobs need to be able to remember more than one feigned attacker
+        void        AddFeignMemory(Client* attacker);
+        void        RemoveFromFeignMemory(Client* attacker);
+        void        ClearFeignMemory();
 
        float  org_x, org_y, org_z, org_heading;
       
@@ -251,8 +253,8 @@
       
        int16        max_dmg;
        int16        min_dmg;
-        const char*        feign_memory;
-        int8    forgetchance;
+        // EverHood 6/14/06
+        std::list<int32> feign_memory_list;
       
        //pet crap:
        int16        pet_spell_id;


fathernitwit 06-28-2006 01:31 PM

ok,

Looks good. I got this in, untested, so grab the next build with it mentioned in the changelog and test it for me.

I made a few changes.
- I fixed an iterator delete bug, you cannot remove an element from any STL container and expect the iterator which pointed to that element to stay valid. Each container has its own erase-while-iterating rules and trick.
- I also changed it from a list to a set, just to ensure uniqueness.
- I moved everything up into Mob so in theory charmed players would exhibit the same behavior. (plus it made the next comment easier)
- Its bad form to name two timers the same thing when they have different purposes, it confused me for a while. Your NPC forget check timer was also somewhat unnescesary (as well as being in a bad spot, that code gets called very rapidly, and your slower timer should be burried inside other shorter timers so it dosent get checked so often.) Because of this, I just eliminated it, and moved the "look for people who got up" code into the AI scan area timer (where we look for people to aggro, which had the same duration).

unicorn97211 06-28-2006 04:28 PM

Great! I look forward to seeing how you implemented the above mentioned changes. The more I learn about the structure and where things should go and what the best objects to use in which situations, the more effective I can fix and or add features. For the immediate future I plan to focus on fixes to the necro class since it's a class I know thoroughly. I hope that more people with class specific knowledge can do the same to free the core devs up for the important things like getting AA's working in 7.0 :)

unicorn97211 06-30-2006 08:40 AM

I grabbed v.812 and did some testing. I found that I am not being remembered. I popped in a debug to tell me when I was being added to the feign memory list and that seems to be working fine. However when I stand up the mob does not remember me and add me to his hate list. It looks as though the memory check isn't being executed. It also looks to me as if the memory check won't occur if the mob is engaged. I'm thinking the mob should remember you even if it's fighting with someone else and you get up.

i.e. If I pull a mob to my group and feign. While the group is fighting the mob , I stand up. My groupies wipe. I should have been remembered when I stood up while the mob was engaged so that when my groupies wipe I am on the hate list even though I may be out of aggro range.

I'm not sure about this as I haven't had time to think through all the possible situations.

FNW: do you want me to try and debug whats going wrong with the memory check the way you implemented it or do you have time to debug it?

fathernitwit 06-30-2006 04:51 PM

what you describe is ultimately what should happen, as soon as the mob is no longer engaged (500ms later prolly), it will look for people to remember, but not until it is no longer engaged (no point in checking while engaged since we come back with only 1 hate).

feel free to debug it.

unicorn97211 07-01-2006 02:31 PM

Just got back into town, that makes sense. I'll toss in some debug messages and such and see if I can track down why they aren't remembering me when I get up even though I've been added to feign memory.

unicorn97211 07-01-2006 08:53 PM

Found the culprit...
 
This is causing fd memory to never be checked.

Code:

#ifdef REVERSE_AGGRO
        if(IsNPC() && !CastToNPC()->WillAggroNPCs())
                AIscanarea_timer->Disable();
#endif

FNW: Where do you recommend moving the feign memory check to?

fathernitwit 07-04-2006 03:23 AM

ah crap, forgot about reverse aggro.

I moved it to its own AI timer, give it a try next rev.

unicorn97211 07-06-2006 10:02 AM

Works like a charm in 0.7.0-815 :)

I need to play more to know for sure but it feels like they don't remember you often enough so perhaps we should make the chance to remember a user defined percentage.


All times are GMT -4. The time now is 08:05 AM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.