Ok, keep in mind a few things before looking at this coding mess. I have not done C++ coding in many years, and more or less forgot how

I know it can be done much better. Maybe someone here has better experience with it and can update it before its merged.
I had to make a new MakePet() function to handle the pet name. I am not sure how you guys wanna handle that part. Remeber, beastlords are gonna need %s' warder
I also guessed at what level each familiar is them selfs. I am sure someone could add the correct values by coning an even one and noteing there level.
There are a few dozen peaces missing to this, like zoning. I didn't get started on my search to find out where to re-summon them durring zoning. /pet get lost doesn't appear to work correctly, (it says you already have a pet if you try to summon another one) and they don't disappear when the buff fades or is dropped. (they also need to be protected from dispells, since you can't dispell them) Currently, the pets will attack as well. I didn't get a chance to track down how to tell the client to disable those from the pet window.
Also, another VERY important note. I wasn't sure which is the correct op code for familairs to be summoned. So, I took a wild guess. If its wrong, change it.
#define SE_Familiar 0x70
-- diff of spells.cpp --
1114,1125d1113
< case SE_Familiar:
< if (this->GetPetID() != 0) {
< Message(13, "You\'ve already got a pet.");
< break;
< }
<
< this->MakePet(spells[spell_id].teleport_zone);
< this->CastToNPC()->SetPetType(0);
< this->SetOwnerID(caster->GetID());
< caster->SetPetID(this->GetID());
< break;
<
1732,1761d1719
< else if (strncmp(pettype, "Familiar1",9) == 0) {
< char f_name[50];
< strcpy(f_name,this->GetName());
< strcat(f_name,"'s Familiar");
< MakePet(27,1,46,1,0,3,0,f_name);
< }
< else if (strncmp(pettype, "Familiar2",9) == 0) {
< char f_name[50];
< strcpy(f_name,this->GetName());
< strcat(f_name,"'s Familiar");
< MakePet(47,1,46,1,0,3,0,f_name);
< }
< else if (strncmp(pettype, "Familiar3",9) == 0) {
< char f_name[50];
< strcpy(f_name,this->GetName());
< strcat(f_name,"'s Familiar");
< MakePet(50,1,89,4,0,3,0,f_name);
< }
< else if (strncmp(pettype, "Familiar4",9) == 0) {
< char f_name[50];
< strcpy(f_name,this->GetName());
< strcat(f_name,"'s Familiar");
< MakePet(58,1,89,4,0,3,0,f_name);
< }
< else if (strncmp(pettype, "Familiar5",9) == 0) {
< char f_name[50];
< strcpy(f_name,this->GetName());
< strcat(f_name,"'s Familiar");
< MakePet(60,1,89,1,0,3,0,f_name);
< }
1775,1840c1733,1740
< if (! name)
< {
< if (this->IsClient())
< strcpy(npc_type->name, GetRandPetName());
< else {
< strcpy(npc_type->name, this->GetName());
< npc_type->name[29] = 0;
< npc_type->name[28] = 0;
< npc_type->name[19] = 0;
< strcat(npc_type->name, "'s_pet");
< }
< }
< else
< {
< strcpy(npc_type->name,name);
< }
< npc_type->level = in_level;
< npc_type->race = in_race;
< npc_type->class_ = in_class;
< npc_type->texture = in_texture;
< npc_type->helmtexture = in_texture;
< npc_type->size = in_size;
< npc_type->max_hp = CalcPetHp(npc_type->level, npc_type->class_);
< npc_type->cur_hp = npc_type->max_hp;
< npc_type->fixedZ = 1;
<
< switch(type)
< {
< case 15: // Mage Epic Pet
< {
< npc_type->max_hp = 3000;
< npc_type->cur_hp = 3000;
< npc_type->min_dmg = 0;
< npc_type->max_dmg = 25;
< sprintf(npc_type->npc_spells,"847 848 849");
< break;
< }
< case 2: // Enchanter Pet
< {
< npc_type->gender = 0;
< npc_type->equipment[7] = 34;
< npc_type->equipment[8] = 202;
< break;
< }
< case 11: // Druid Pet... Baron-Sprite: Info from
www.eqdruids.com said about 100 hp.
< {
< npc_type->max_hp = 100;
< npc_type->cur_hp = 100;
< npc_type->min_dmg = 17;
< npc_type->max_dmg = 25;
< break;
< }
< default:
< break;
< }
< NPC* npc = new NPC(npc_type, 0, this->GetX(), this->GetY(), this->GetZ(), this->GetHeading());
< delete npc_type;
< npc->SetPetType(in_pettype);
< npc->SetOwnerID(this->GetID());
< entity_list.AddNPC(npc);
< this->SetPetID(npc->GetID());
< }
<
< void Mob::MakePet(int8 in_level, int8 in_class, int16 in_race, int8 in_texture, int8 in_pettype, float in_size, int8 type, char* name) {
< if (this->GetPetID() != 0) {
< return;
---
> if (this->IsClient())
> strcpy(npc_type->name, GetRandPetName());
> else {
> strcpy(npc_type->name, this->GetName());
> npc_type->name[29] = 0;
> npc_type->name[28] = 0;
> npc_type->name[19] = 0;
> strcat(npc_type->name, "'s_pet");
1842,1847d1741
<
< NPCType* npc_type = new NPCType;
< memset(npc_type, 0, sizeof(NPCType));
< npc_type->gender = 2;
<
< strcpy(npc_type->name,name);
1894d1787
<
-- end diff --
I also thought of an intresting non-standard eqlive idea. GMs should be able to summon a different colored familiar. I figured a red drake would be kinda cool. I didn't add that in there, becuase I wasn't sure how people would react to it. Either way, I think its a cool idea.
Enjoy