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
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
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.