EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Archive::Development (https://www.eqemulator.org/forums/forumdisplay.php?f=621)
-   -   Feign Death Code - Revised (https://www.eqemulator.org/forums/showthread.php?t=3568)

Wiz 10-24-2002 06:41 PM

Feign Death Code - Revised
 
This is a complete code snippet for Feign Death, including aggro clearing, enemy memory, and such.

To initiate, open client_process.cpp, and insert this under the opcodes.

Code:

                                        case OP_FeignDeath:
                                        {
int16 feignskill = GetSkill(FEIGN_DEATH);
                                                int16 primfeign = feignskill;
                                                int16 secfeign = feignskill;
                                                if (primfeign > 100)
                                                {
                                                        primfeign = 100;
                                                        secfeign = secfeign - 100;
                                                        secfeign = secfeign / 2;
                                                }       
                                                else
                                                        secfeign = 0;
                                                int16 totalfeign = primfeign + secfeign;
                                                if (rand()%160 > totalfeign)
                                                {
                                                        SetFeigned(false);
                                                        entity_list.MessageClose(this,false,200,0,"%s has fallen to the ground.",this->GetName());
                                                }
                                                else
                                                {
                                                        SetFeigned(true);
                                                        entity_list.ClearFeignAggro(this);
                                                }
                                                if (rand()%300 > feignskill && rand()%4 == 1 && feignskill < 200 && feignskill < GetLevel()*5+5)
                                                {
                                                    SetSkill(25,++pp.skills[25]);
                                                        UpdateWho();
                                                }
                                                break;
                                        }

Now, go further up in client_process.cpp, find OP_SpawnAppearance. Under standing, sitting, looting and ducking, insert

Code:

SetFeigned(false);
Insert this into client.h:

Code:

        void        SetFeigned(bool in_feigned);
        bool    GetFeigned()        {return feigned;}
        bool    feigned;

Insert this into Client::Client in client.cpp

Code:

feigned=false;
And this at the bottom of client.cpp

Code:

void Client::SetFeigned(bool in_feigned) {
        if (in_feigned)
                SetPet(0); //Crashes unless this is put here
        feigned=in_feigned;
 }

Insert into npc.h

Code:

void        SetFeignMemory(const char* num) {feign_memory = num;}
const char*        feign_memory;
int8    forgetchance;
Timer* forget_timer;

Insert into npc.cpp, in NPC::NPC

Code:

feign_memory = "0";
forget_timer = new Timer(500);
forgetchance = 0;

Insert into npc.cpp, at the bottom of Process();

Code:

        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 = forgetchance + 5;
                        }
                }
                else
                {
                        SetFeignMemory("0");
                }
        }

Insert into entity.h:

Code:

        void        ClearFeignAggro(Mob* targ);
Insert into entity.cpp:

Code:

void EntityList::ClearFeignAggro(Mob* targ)
{
        LinkedListIterator<Entity*> iterator(list);
        iterator.Reset();
        while(iterator.MoreElements())
        {
                if (iterator.GetData()->IsNPC() && 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();
        }
}

In NpcAI.cpp, find this line:

Code:

                                                                sender->AddToHateList(currentmob,1);
A bit above it, in the if statement, add
Code:

&& !currentmob->CastToClient()->GetFeigned()
to prevent mobs from aggroing a feigned person.

Insert this into spells.cpp, under SpellEffect:

Code:

        if (spells[spell_id].goodEffect == 0 && this->IsClient() && this->CastToClient()->GetFeigned()) {
                this->CastToClient()->Message(MT_Shout,"You are no longer feigning death because a spell hit you!");
                this->CastToClient()->SetFeigned(false);
        }

Finally, insert into spells.cpp, under SE_FeignDeath:
Code:

                                this->CastToClient()->SetFeigned(true);
                                entity_list.ClearFeignAggro(this);

You're done! Yeah, it doesn't work exactly like VI's rather fucked up feign death code, but here's the advantages:

- Easier processing. Having a purely time based forget chance eliminates some of the more comical aspects to VI's FD, and can also be modified per NPC through a database, if some tweaking is done.

- You don't have to turn off autoattack for this feign to work (Never understood that anyways).

- No feign bug, at all. This feign always works when successfully processed.

Wiz 10-24-2002 06:45 PM

Oh, yeah. This needs to be added to hate_list.cpp:

Code:

bool HateList::IsOnList(Mob* targ)
{
        HateListElement *current = first;

        if (first == 0) {
                return false;
        }

        int r = ElementCount;
        for (int i=0; i < r; i++) {
                if (current && current->GetEnt() == targ) {
                        return true;
                }
                current = current->GetNext();
        }
        return false;
}

This to hate_list.h:

Code:

bool IsOnList(Mob* targ);
And this to npc.h:

Code:

bool        CheckAggro(Mob* other) {return hate_list.IsOnList(other);}
Sorry 'bout that. :P

Xarslik 10-24-2002 07:03 PM

Very nice wiz, can't wait to test it out on next release. =)

a_Guest03 10-25-2002 04:10 AM

Very clean and good, Wiz :) Thanks for the feature!

kathgar 10-25-2002 05:38 AM

You kinda missed the whole they only forget after they walk back to spawn point(we dont' do) and then they alwyas forget unless they are above level 35..

Wiz 10-25-2002 05:47 AM

Actually kath, level 35 is included. Check again.

Also, they CAN forget without walking back to spawn point, the chance is small - I just did it this way, because I personally like this system better. I don't believe in doing everything exactly as VI has.

I'll just quote the section:

Code:

                        if (iterator.GetData()->CastToMob()->GetLevel() >= 35)
                        {
                                iterator.GetData()->CastToNPC()->SetFeignMemory(targ->CastToMob()->GetName());
                        }


Wiz 10-25-2002 06:00 AM

Fixed a typo in the code.

But, if you REALLY want a VI clone, here you go:

Code:

        if (forget_timer->Check() && strcasecmp(GetFeignMemory(),"0") != 0) {
                Client* remember_client = entity_list.GetClientByName(GetFeignMemory());
                if (remember_client != 0)
                {
                        if (org_x == GetX() && org_y == GetY())
                                forgetchance = 80;
                        else
                                forgetchance = 15;
                        if (!remember_client->CastToClient()->GetFeigned() && rand()%100 <= forgetchance)
                        {
                                AddToHateList(remember_client,1);
                                SetFeignMemory("0");
                                forgetchance = 0;
                        }
                        else if (!remember_client->CastToClient()->GetFeigned())
                        {
                                SetFeignMemory("0");
                                forgetchance = 0;
                        }
                }
                else
                {
                        SetFeignMemory("0");
                }
        }

Exactly like the VI remember chance. Enjoy. :)

kathgar 10-25-2002 06:26 AM

Hmm, it sure does.. my bad =P


All times are GMT -4. The time now is 11:28 AM.

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