Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #1  
Old 06-21-2009, 06:54 PM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Cool Armor Tint Deluxe

Okay, I wasn't satisfied with a single armor_tint value for an NPC's entire outfit. I wanted the ability to specify colors for individual armor pieces, so I could create colored armor uniforms for guards and such, potentially replacing old low-poly guards with Luclin models.

It wasn't too horribly difficult.



SQL change:
Code:
ALTER TABLE `npc_types` ADD COLUMN `armortint_id` INTEGER UNSIGNED NOT NULL DEFAULT 0 AFTER `drakkin_details`;
SQL table addition:
Code:
CREATE TABLE `npc_types_tint` (
  `id` int unsigned NOT NULL DEFAULT '0',
  `red1h` tinyint unsigned NOT NULL DEFAULT '0',
  `grn1h` tinyint unsigned NOT NULL DEFAULT '0',
  `blu1h` tinyint unsigned NOT NULL DEFAULT '0',
  `red2c` tinyint unsigned NOT NULL DEFAULT '0',
  `grn2c` tinyint unsigned NOT NULL DEFAULT '0',
  `blu2c` tinyint unsigned NOT NULL DEFAULT '0',
  `red3a` tinyint unsigned NOT NULL DEFAULT '0',
  `grn3a` tinyint unsigned NOT NULL DEFAULT '0',
  `blu3a` tinyint unsigned NOT NULL DEFAULT '0',
  `red4b` tinyint unsigned NOT NULL DEFAULT '0',
  `grn4b` tinyint unsigned NOT NULL DEFAULT '0',
  `blu4b` tinyint unsigned NOT NULL DEFAULT '0',
  `red5g` tinyint unsigned NOT NULL DEFAULT '0',
  `grn5g` tinyint unsigned NOT NULL DEFAULT '0',
  `blu5g` tinyint unsigned NOT NULL DEFAULT '0',
  `red6l` tinyint unsigned NOT NULL DEFAULT '0',
  `grn6l` tinyint unsigned NOT NULL DEFAULT '0',
  `blu6l` tinyint unsigned NOT NULL DEFAULT '0',
  `red7f` tinyint unsigned NOT NULL DEFAULT '0',
  `grn7f` tinyint unsigned NOT NULL DEFAULT '0',
  `blu7f` tinyint unsigned NOT NULL DEFAULT '0',
  `red8x` tinyint unsigned NOT NULL DEFAULT '0',
  `grn8x` tinyint unsigned NOT NULL DEFAULT '0',
  `blu8x` tinyint unsigned NOT NULL DEFAULT '0',
  `red9x` tinyint unsigned NOT NULL DEFAULT '0',
  `grn9x` tinyint unsigned NOT NULL DEFAULT '0',
  `blu9x` tinyint unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
Notes:

- I don't know if the table specs (engine, row_format, etc.) are the best ones to use. They were just the defaults used with my MySQL installation.

- Field numberings are Helm, Chest, Arms, Bracers, Gloves, Legs, then Face. The letters after the numbers can help if you're editing the table data directly. 8 and 9 are for Primary and Secondary weapon slots, and as far as I can tell are unused by the client at this time. They can be left at 0.

Server Code changes:

eq_packet_structs.h - Line 1868
Code:
...
  /*085*/  uint8  haircolor;    // Verified
- /*085*/  uint8  beard;      // Verified
+ /*086*/  uint8  beard;      // Verified
  /*087*/  uint8  beardcolor;    // Verified
  /*088*/  uint32  drakkin_heritage;  // Temp Placeholder until field is identified in SoF
  /*092*/  uint32  drakkin_tattoo;    // Temp Placeholder until field is identified in SoF
  /*096*/  uint32  drakkin_details;  // Temp Placeholder until field is identified in SoF
- /*100*/  uint32  armor_tint;    // Temp Placeholder until field is identified in SoF
- /*104*/  uint8  eyecolor1;    // Temp Placeholder until field is identified in SoF
- /*105*/  uint8  eyecolor2;    // Temp Placeholder until field is identified in SoF
- /*106*/  uint8  unknown106[150];  //was uint8  unknown021[168];
+ /*100*/  uint32  armor_tint[MAX_MATERIALS];    // Temp Placeholder until field is identified in SoF
+ /*136*/  uint8  eyecolor1;    // Temp Placeholder until field is identified in SoF
+ /*137*/  uint8  eyecolor2;    // Temp Placeholder until field is identified in SoF
+ /*138*/  uint8  unknown138[118];  //was uint8 unknown106[150]; //was uint8  unknown021[168];
  /*256*/
  };
...
mob.h - Line 374
Code:
...
  int32  in_drakkin_details,
- int32  in_armor_tint,
+ int32  in_armor_tint[MAX_MATERIALS],
  int8   in_aa_title,
...
mob.h - Line 535
Code:
...
  inline int8  GetDrakkinDetails()      const { return drakkin_details; }
- inline int32  GetArmorTint()      const { return armor_tint; }
+ inline int32  GetArmorTint(int8 i)      const { return armor_tint[(i < MAX_MATERIALS) ? i : 0]; }
  inline int8  GetClass()          const { return class_; }
...
mob.h - Line 726
Code:
...
  void  TryDotCritical(int16 spell_id, Mob *caster, int &damage);

- void  SendIllusionPacket(int16 in_race, int8 in_gender = 0xFF, int16 in_texture = 0xFFFF, int16 in_helmtexture = 0xFFFF, int8 in_haircolor = 0xFF, int8 in_beardcolor = 0xFF, int8 in_eyecolor1 = 0xFF, int8 in_eyecolor2 = 0xFF, int8 in_hairstyle = 0xFF, int8 in_luclinface = 0xFF, int8 in_beard = 0xFF, int8 in_aa_title = 0xFF, int32 in_drakkin_heritage = 0xFFFFFFFF, int32 in_drakkin_tattoo = 0xFFFFFFFF, int32 in_drakkin_details = 0xFFFFFFFF, int32 in_armor_tint = 0xFFFFFFFF);
+ void  SendIllusionPacket(int16 in_race, int8 in_gender = 0xFF, int16 in_texture = 0xFFFF, int16 in_helmtexture = 0xFFFF, int8 in_haircolor = 0xFF, int8 in_beardcolor = 0xFF, int8 in_eyecolor1 = 0xFF, int8 in_eyecolor2 = 0xFF, int8 in_hairstyle = 0xFF, int8 in_luclinface = 0xFF, int8 in_beard = 0xFF, int8 in_aa_title = 0xFF, int32 in_drakkin_heritage = 0xFFFFFFFF, int32 in_drakkin_tattoo = 0xFFFFFFFF, int32 in_drakkin_details = 0xFFFFFFFF, int32* in_armor_tint = 0);

  static  int32  GetAppearanceValue(EmuAppearance iAppearance);
...
mob.h - Line 1162
Code:
...
  int32  drakkin_details;
- int32  armor_tint;
+ int32  armor_tint[MAX_MATERIALS];

  int8  aa_title;
...
mob.cpp - Line 89
Code:
...
  int32  in_drakkin_details,
- int32  in_armor_tint,
+ int32  in_armor_tint[MAX_MATERIALS],

  int8   in_aa_title,
...
mob.cpp - Line 187
Code:
...
  drakkin_details    = in_drakkin_details;
- armor_tint = in_armor_tint;
  attack_speed = 0;
...
mob.cpp - Line 249
Code:
...
  }

+ for (i = 0; i < MAX_MATERIALS; i++)
+ {
+   if (in_armor_tint)
+   {
+     armor_tint[i] = in_armor_tint[i];
+   }
+   else
+   {
+     armor_tint[i] = 0;
+   }
+ }

  delta_heading = 0;
...
mob.cpp - Line 792
Code:
...
    ns->spawn.equipment[i] = GetEquipmentMaterial(i);
-   if (armor_tint)
-   {
-      ns->spawn.colors[i].color = armor_tint;
-   }
+   if (armor_tint[i])
+   {
+      ns->spawn.colors[i].color = armor_tint[i];
+   }
    else
    {
      ns->spawn.colors[i].color = GetEquipmentColor(i);
    }
  }
...
mob.cpp - Line 1164
Code:
...
- void Mob::SendIllusionPacket(int16 in_race, int8 in_gender, int16 in_texture, int16 in_helmtexture, int8 in_haircolor, int8 in_beardcolor, int8 in_eyecolor1, int8 in_eyecolor2, int8 in_hairstyle, int8 in_luclinface, int8 in_beard, int8 in_aa_title, int32 in_drakkin_heritage, int32 in_drakkin_tattoo, int32 in_drakkin_details, int32 in_armor_tint) {
+ void Mob::SendIllusionPacket(int16 in_race, int8 in_gender, int16 in_texture, int16 in_helmtexture, int8 in_haircolor, int8 in_beardcolor, int8 in_eyecolor1, int8 in_eyecolor2, int8 in_hairstyle, int8 in_luclinface, int8 in_beard, int8 in_aa_title, int32 in_drakkin_heritage, int32 in_drakkin_tattoo, int32 in_drakkin_details, int32* in_armor_tint) {
...
mob.cpp - Line 1209
Code:
...
  this->helmtexture = in_helmtexture;

+ int i;

  if (in_race > 12 && in_race != 128 && in_race != 130 && in_race != 330 && in_race != 522) {
...
mob.cpp - Line 1223
Code:
...
    this->drakkin_details = 0xFFFFFFFF;
-   this->armor_tint = 0xFFFFFFFF;
+   for (i = 0; i < MAX_MATERIALS; i++)
+   {
+     this->armor_tint[i] = 0xFFFFFFFF;
+   }

  }
...
mob.cpp - Line 1282
Code:
...
    this->drakkin_details = in_drakkin_details;

-   if (in_armor_tint == 0xFFFFFFFF)
-     this->armor_tint = GetArmorTint();
-   else
-     this->armor_tint = in_armor_tint;    

+   for (i = 0; i < MAX_MATERIALS; i++)
+   {
+     if ((in_armor_tint) && (in_armor_tint[i]))
+       this->armor_tint[i] = in_armor_tint[i];
+     else
+       this->armor_tint[i] = GetArmorTint(i);
+   }
    
  }
...
mob.cpp - Line 1308
Code:
...
    this->drakkin_details = CastToClient()->GetBaseDetails();
-   this->armor_tint = 0xFFFFFFFF;
+   for (i = 0; i < MAX_MATERIALS; i++)
+   {
+     this->armor_tint[i] = 0xFFFFFFFF;
+   }
  }
...
mob.cpp - Line 1334
Code:
...
    is->drakkin_details = this->drakkin_details;
-   is->armor_tint = this->armor_tint;
+   for (i = 0; i < MAX_MATERIALS; i++)
+   {
+     is->armor_tint[i] = this->armor_tint[i];
+   }
  
    DumpPacket(outapp);
...
npc.cpp - Line 97
Code:
...
    d->drakkin_details,
-   d->armor_tint,
+   (int32*)d->armor_tint,
    0,
...
zonedump.h - Line 89
Code:
...
    int32  drakkin_details;
-   int32  armor_tint;
+   int32  armor_tint[MAX_MATERIALS];
//  int8  aa_title;  ////not loaded from DB
...
zonedb.cpp - Line 1053
Code:
...
      "npc_types.drakkin_details,"
+     "npc_types.armortint_id,"
      "npc_types.armortint_red,"
...
zonedb.cpp - Line 1144
Code:
...
        tmpNPCType->drakkin_details = atoi(row[r++]);

-       tmpNPCType->armor_tint = (atoi(row[r++]) & 0xFF) << 16;
-       tmpNPCType->armor_tint |= (atoi(row[r++]) & 0xFF) << 8;
-       tmpNPCType->armor_tint |= (atoi(row[r++]) & 0xFF);
-       tmpNPCType->armor_tint |= (tmpNPCType->armor_tint) ? (0xFF << 24) : 0;

+       uint32 armor_tint_id = atoi(row[r++]);
+       tmpNPCType->armor_tint[0] = (atoi(row[r++]) & 0xFF) << 16;
+       tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF) << 8;
+       tmpNPCType->armor_tint[0] |= (atoi(row[r++]) & 0xFF);
+       tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0;
+
+       int i;
+       if (armor_tint_id > 0)
+       {
+         if (tmpNPCType->armor_tint[0] == 0)
+         {
+           char at_errbuf[MYSQL_ERRMSG_SIZE];
+           char *at_query = NULL;
+           MYSQL_RES *at_result = NULL;
+            MYSQL_ROW at_row;
+            
+            MakeAnyLenString(&at_query,
+             "SELECT "
+             "red1h,grn1h,blu1h,"
+             "red2c,grn2c,blu2c,"
+             "red3a,grn3a,blu3a,"
+             "red4b,grn4b,blu4b,"
+             "red5g,grn5g,blu5g,"
+             "red6l,grn6l,blu6l,"
+             "red7f,grn7f,blu7f,"
+             "red8x,grn8x,blu8x,"
+             "red9x,grn9x,blu9x "
+             "FROM npc_types_tint WHERE id=%d", armor_tint_id);
+
+           if (RunQuery(at_query, strlen(at_query), at_errbuf, &at_result))
+           {
+             if ((at_row = mysql_fetch_row(at_result)))
+             {
+               for (i = 0; i < MAX_MATERIALS; i++)
+               {
+                 tmpNPCType->armor_tint[i] = atoi(at_row[i * 3]) << 16;
+                 tmpNPCType->armor_tint[i] |= atoi(at_row[i * 3 + 1]) << 8;
+                 tmpNPCType->armor_tint[i] |= atoi(at_row[i * 3 + 2]);
+                  tmpNPCType->armor_tint[i] |= (tmpNPCType->armor_tint[i]) ? (0xFF << 24) : 0;
+               }
+             }
+             else
+             {
+               armor_tint_id = 0;
+             }
+           }
+           else
+           {
+             armor_tint_id = 0;
+           }
+
+           if (at_result)
+           {
+              mysql_free_result(at_result);
+            }
+            
+           safe_delete_array(at_query);
+         }
+         else
+         {
+           armor_tint_id = 0;
+         }
+       }
+
+       if (armor_tint_id == 0)
+       {
+         for (i = 1; i < MAX_MATERIALS; i++)
+         {
+           tmpNPCType->armor_tint[i] = tmpNPCType->armor_tint[0];
+         }
+       }

        tmpNPCType->see_invis = atoi(row[r++])==0?false:true;      // Set see_invis flag
...
I think that got everything.

Last edited by trevius; 06-22-2009 at 01:11 PM.. Reason: Changed zonedb.h to zonedump.h
Reply With Quote
  #2  
Old 06-21-2009, 07:30 PM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Forgot to clarify. This is the order of priority for armor tints:

1. armortint_red, _green, and _blue in npc_types. If any of these values is non-zero, the tint is applied to all armor pieces, ignoring armortint_id and individual armor piece coloring.

2. armortint_id. If the RGB values in #1 are all 0 but armortint_id is specified, the values from the npc_types_tint table with the corresponding id are used.

3. armor piece tint. If the RGB values in 1 are zero and armortint_id is 0 (or a corresponding record in npc_types_tint cannot be found), or if the red/grn/blu values for a particular armor piece in npc_types_tint are all 0, the tint on the actual armor piece item is displayed.

Hope that clears up any potential confusion.
Reply With Quote
  #3  
Old 06-21-2009, 08:16 PM
ChaosSlayerZ's Avatar
ChaosSlayerZ
Demi-God
 
Join Date: Mar 2009
Location: Umm
Posts: 1,492
Default

AWSOME...

stupid question but to say to truly replicate the old felguard - he actual needs to wear CHAIN arms - how would you achieve that?

ALSO:

"Helm, Chest, Arms, Bracers, Gloves, Legs, then Face."

Face? but no Boots?
Reply With Quote
  #4  
Old 06-21-2009, 09:09 PM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Err... I actually typed that? LOL.

Feet. The 'F' is for feet.

And really, mixing armor types doesn't work out well. The armor meshes were designed to match up together, and they look out of place when mixed and matched. Better to stick with all chain, all plate, all leather, or all cloth.
Reply With Quote
  #5  
Old 06-21-2009, 09:32 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

That is really awesome, Shendare! ChaosSlayer, I think Shendare meant to say "foot", not "face", since helm was already listed and that would be the same as face.

I will try to get this added ASAP. One thing I wanted to mention is that I don't think armor tint can be sent with an illusion packet, but it should be able to be sent with a wearchange packet. So, I need to go through and write a command or 2 that will use the wearchange packets for changing armor tints or weapons without having to repop the zone/NPC. I don't think it will be too hard to get that coded and I will probably start soon after I get AAs for SoF all figured out and finalized. I will probably try to add in a quest command or 2 for handling armor changes Then we would be able to change out armor on playable races, or we could even swap out weapons on other races mid-fight. Might be cool to have guards that normally have no weapons showing and then they whip them out when they aggro on something, or anything along those lines.

I really like how you made a separate table for handling the new armor settings. I am surprised Live doesn't have anything like this, but maybe they will steal the idea when they see it :P

I do think we could also include a material field for each slot in that table. Then, we could have it send the material for each slot so you could have NPCs with mismatched set pieces like ChaosSlayer suggested.

This is some nice stuff, Shendare I don't know why, but I have been really happy with the illusion and spawn struct stuff we have figure out so far. I guess they are just things that have always bothered me just enough to stay on my radar. It is really nice to finally be working all of this stuff out so it never has to be messed with again other than maybe adding in more commands to use them.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #6  
Old 06-21-2009, 09:42 PM
ChaosSlayerZ's Avatar
ChaosSlayerZ
Demi-God
 
Join Date: Mar 2009
Location: Umm
Posts: 1,492
Default

yeah I kind of figured it was a mistype, since helm was allreday listed, and for a moment I was wondering - "what? he managed to tint the FACE too?"

As far as diffirent materials go - didn't just recently someone wrote a perl script which can ultra randomize npc when it spawns? Like face, hair, and specificly armor by slot? Or it was just something someone wanted to do?

Quote:
I am surprised Live doesn't have anything like this, but maybe they will steal the idea when they see it :P
LIVE sucks =) Honestly when I look back at early EQ days it kills me how UNCREATIVE the original team was. Some basic natural things which are directly obvious took them years to put in, and not untill SOE took over..
Reply With Quote
  #7  
Old 06-21-2009, 09:45 PM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Yeah, it's cool, Trev!

I'm not sure exactly what you're unsure of regarding the illusion packets, but the code there in mob.cpp from lines 1164-1350 or so is in SendIllusionPacket().

I can change an NPC's race and gender in-game and the armor tints carry over to the new model, and it was my understanding that you use SendIllusionPacket when changing these in-game.
Reply With Quote
  #8  
Old 06-21-2009, 10:40 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Shendare, I added the armor tint stuff to that command because there is a large part of the illusion packet that we don't have identified yet and I assume that part of it may for armor and tint. I tried to identify those parts and was able to find some helms (some of which showed up as sideway), but I could never exactly figure out what was going on. It is probably because the test I was using is your test code, but it is in int8 and I assume armor would need int32 instead. I just never tried it to see if that was the case.

On a side note, I also noticed that most races cannot change their hair style when using illusion packets. I have no idea why this is, but I can only get Drakkin, Humans, and Female Ogres to change their hairstyle using Illusion packets. The other races all just set their hair to 0 or something. This one has stumped me and may just be an issue with the client (I really only use SoF), so I just gave up on the hair thing.

I will just have to mess with the wearchange packets and get something similar setup for them. I was able to get it to keep the current texture they had on by just not sending anything for the texture/helm fields of the illusion struct. To be able to change armor without repops, it would probably take wearchanges to do it.

ChaosSlayer, it was me that recently added the #randomfeatures command. But, that command only randomizes facial features like hair, beard, haircolor, tattoo and so on. It doesn't randomize armor, but that is a command I would like to add at some point. I wouldn't want it to make completely random armor for entire sets, but maybe using some sort of logic that has chances to make certain random changes that might look good together. The basic idea would be for it to be able to make armor sets similar to the guard one that Shendare posted in the first post. It would definitely take some playing around to make it output halfway decent sets most of the time.

I also really need to create a way to update an NPCs features and armor set/tint. Maybe the #npcspawn command can be expanded with a new option that would let you save the current race, gender, texture, features, armor and armor tint and so on of the current NPC you have targeted. So, you could use the randomizing commands until you found one that looked right and then just save it as it is.

I really have to at least knock out the SoF AA stuff first and maybe the newly added SoF item stats as well. So, I am not sure when I will be able to get to that. I will definitely try to get this tested and added to the code soon if someone doesn't beat me to it.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 06-22-2009 at 06:43 AM..
Reply With Quote
  #9  
Old 06-21-2009, 11:42 PM
ChaosSlayerZ's Avatar
ChaosSlayerZ
Demi-God
 
Join Date: Mar 2009
Location: Umm
Posts: 1,492
Default

Quote:
Originally Posted by trevius View Post
ChaosSlayer, it was me that recently added the #randomfeatures command. But, that command only randomizes facial features like hair, beard, haircolor, tattoo and so on. It doesn't randomize armor, but that is a command I would like to add at some point. I wouldn't want it to make completely random armor for entire sets, but maybe using some sort of logic that has chances to make certain random changes that might look good together. The basic idea would be for it to be able to make armor sets similar to the guard one that Shendare posted in the first post. It would definitely take some playing around to make it output halfway decent sets most of the time.

Trev if this case, what we realy need is something like:

quest::npcarmor(slot, material);

so its not random, but rather specific by user wish.
If you do want it random you just do RND on material for specific/all slots

then we don't need to have to put it into DB
Reply With Quote
  #10  
Old 06-22-2009, 05:16 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

ChaosSlayer, before I add another random command, I would definitely add the direct command for changing stuff like that. The random command would just be another bonus command to go along with it. First would be one for changing tint, then maybe one for changing the material of each slot, and yet another for changing weapons out. Last and most importantly is to create a command that let's a dev save the current looks from in game. Actual # commands would be added first and then those could be copied to create quest:: commands as well whenever.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 06-22-2009 at 01:41 PM..
Reply With Quote
  #11  
Old 06-22-2009, 05:58 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

This has now been added to Revision 702 on the SVN.

This feature is awesome BTW! Playing with it shows that it has a ton of potential. The only thing I might add in soon is a simple notes field for the table so you can name each armor set. This way, you can easily have different colored sets and just name them to use them anywhere. It would make managing a large amount of sets quite a bit easier.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 06-22-2009 at 04:13 PM..
Reply With Quote
  #12  
Old 06-22-2009, 10:39 AM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Agreed, a name field is a very good idea! Don't know how I missed it.
Reply With Quote
  #13  
Old 06-22-2009, 10:52 AM
So_1337
Dragon
 
Join Date: May 2006
Location: Cincinnati, OH
Posts: 689
Default

I just wanted to take a minute and chime in to say how amazing your work has been. Thanks for this splendid ability to add some real customization =)
Reply With Quote
  #14  
Old 06-22-2009, 11:32 AM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Thanks, it's good to feel appreciated.
Reply With Quote
  #15  
Old 06-22-2009, 01:43 PM
steve
Discordant
 
Join Date: Jan 2002
Posts: 305
Default

Quote:
Originally Posted by Shendare View Post
Thanks, it's good to feel appreciated.
I have to second his remarks. Your additions to the project have been invaluable. If anyone's earned the rank of Developer, it's you!
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 09:20 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3