Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Development

Development::Development Forum for development topics and for those interested in EQEMu development. (Not a support forum)

Reply
 
Thread Tools Display Modes
  #16  
Old 05-16-2009, 02:13 PM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Okay. Originally I'd taken the original function and simplified it to make it very fast and efficient, and it even let you use shortcuts to shrink the command down to one or two digits (nh for nexthelm, pt for prevtexture, etc.).

Then I saw what you were doing with your actual post, giving the option to change more fields with the #fixmob command than the existing ones, and the shortcuts and such wouldn't work out.

So, back to the original question, the main issue with with your code is that C++ does not support using the switch statement with strings (like Javascript, C#, etc, do). It only works with numbers and single chars.

Here's a reworked version of your code that runs efficiently and has plenty of room for expansion with new commands:

Code:
void command_fixmob(Client *c, const Seperator *sep)
{
  Mob *target=c->GetTarget();
  char* Usage = "Usage: #fixmob [gender]|[(next/prev)race|texture|helm|hairstyle|haircolor]";

  if (!sep->arg[1])
    c->Message(0,Usage);
  else if (!target)
    c->Message(0,"Error: this command requires an NPC target");
  else
  {
    int16 Race = target->GetRace();
    int8 Gender = target->GetGender();
    int8 Texture = target->GetTexture();
    int8 HelmTexture = target->GetHelmTexture();
    int8 HairColor = target->GetHairColor();
    int8 BeardColor = target->GetBeardColor();
    int8 EyeColor1 = target->GetEyeColor1();
    int8 EyeColor2 = target->GetEyeColor2();
    int8 HairStyle = target->GetHairStyle();
    int8 LuclinFace = target->GetLuclinFace();
    int8 Beard = target->GetBeard();
    int32 DrakkinHeritage = target->GetDrakkinHeritage();
    int32 DrakkinTattoo = target->GetDrakkinTattoo();
    int32 DrakkinDetails = target->GetDrakkinDetails();
    
    char* ChangeType = NULL; // If it's still NULL after processing, they didn't send a valid command
    int32 ChangeSetting;
    char* command = sep->arg[1];
    char codeMove;
    char codeType;

    codeMove = (command[0] | 0x20); // First character, lower-cased
    if (strlen(command) > 4)
    {
      codeType = command[4] | 0x20; // Fifth character, lower-cased
    }
    else
    {
      codeType = NULL;
    }

    if (codeMove == 'g')
    {
      // Gender doesn't start with next/prev, so the first char is actually the type
      codeType = codeMove;
    }

    switch (codeType)
    {
      case 'g': // Gender
        if (strcasecmp(command, "gender") == 0)
        {
          Gender = (Gender == 2) ? 0 : Gender + 1; // 0 - 2
          ChangeType = "Gender";
          ChangeSetting = Gender;
        }
        break;
      case 'r': // Race
        switch (codeMove)
        {
          case 'n': // Next
            if (strcasecmp(command, "nextrace") == 0)
            {
              Race = (Race == 586) ? 0 : Race + 1; // 0 - 586
              ChangeType = "Race";
              ChangeSetting = Race;
            }
            break;
          case 'p': // Prev
            if (strcasecmp(command, "prevrace") == 0)
            {
              Race = (Race == 0) ? 586 : Race - 1; // 0 - 586
              ChangeType = "Race";
              ChangeSetting = Race;
            }
            break;
        }
        break;
      case 't': // Texture
        switch (codeMove)
        {
          case 'n': // Next
            if (strcasecmp(command, "nexttexture") == 0)
            {
              Texture = (Texture == 25) ? 0 : Texture + 1; // 0 - 25
              ChangeType = "Texture";
              ChangeSetting = Texture;
            }
            break;
          case 'p': // Prev
            if (strcasecmp(command, "prevtexture") == 0)
            {
              Texture = (Texture == 0) ? 25 : Texture - 1; // 0 - 25
              ChangeType = "Texture";
              ChangeSetting = Texture;
            }
            break;
        }
        break;
      case 'h': // HelmTexture, HairStyle, HairColor
        switch (codeMove)
        {
          case 'n': // Next
            if (strcasecmp(command, "nexthelm") == 0)
            {
              HelmTexture = (HelmTexture == 25) ? 0 : HelmTexture + 1; // 0 - 25
              ChangeType = "HelmTexture";
              ChangeSetting = HelmTexture;
            }
            else if (strcasecmp(command, "nexthaircolor") == 0)
            {
              HairColor = (HairColor == 15) ? 0 : HairColor + 1; // 0 - 15
              ChangeType = "HairColor";
              ChangeSetting = HairColor;
            }
            else if (strcasecmp(command, "nexthairstyle") == 0)
            {
              HairStyle = (HairStyle == 7) ? 0 : HairStyle + 1; // 0 - 7
              ChangeType = "HairStyle";
              ChangeSetting = HairStyle;
            }
            break;
          case 'p': // Prev
            if (strcasecmp(command, "prevhelm") == 0)
            {
              HelmTexture = (HelmTexture == 0) ? 25 : HelmTexture - 1; // 0 - 25
              ChangeType = "HelmTexture";
              ChangeSetting = HelmTexture;
            }
            else if (strcasecmp(command, "prevhaircolor") == 0)
            {
              HairColor = (HairColor == 0) ? 15 : HairColor - 1; // 0 - 15
              ChangeType = "HairColor";
              ChangeSetting = HairColor;
            }
            else if (strcasecmp(command, "prevhairstyle") == 0)
            {
              HairStyle = (HairStyle == 0) ? 7 : HairStyle - 1; // 0 - 7
              ChangeType = "HairStyle";
              ChangeSetting = HairStyle;
            }
            break;
        }
        break;
      default:
        break;
    }

    if (ChangeType == NULL)
    {
      c->Message(0,Usage);
    }
    else
    {
      target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor,
          EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF,
          DrakkinHeritage, DrakkinTattoo, DrakkinDetails);
        
      c->Message(0, "%s=%i", ChangeType, ChangeSetting);
    }
  }
}
I tested adding haircolor and hairstyle options.

Of course, options won't work if the illusion struct fields haven't been figured out.

I'll leave messing around with that one to you. Don't want to double up on your work. :P

- Shendare
Reply With Quote
  #17  
Old 05-16-2009, 11:17 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

By updating the struct inside the corpse's data field all old corpses are now prevented from spawning. In the future I'd probably avoid doing this if at all possible and if there's no other choice you need to provide a way for people to upgrade the corpses in a database (I'm writing this atm so don't worry about it).
Reply With Quote
  #18  
Old 05-17-2009, 12:19 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Yeah, as I have said elsewhere, this is my fault and I honestly didn't know it was going to happen. I didn't notice that there was a blob in the corpse tables. I thought it was just pulling the info from the PP. I had never attempted to do any changes like that before, so I really didn't know what I was doing. Honestly, I was hoping that someone more skilled would pick it up and add that stuff in at some point, but I know there are many other more important things to do. I figured I would try it and see if I could get them working and then just test it as best as I could to make sure there weren't issues with the changes. Unfortunately, I only tested newly created corpses, I didn't look for any old ones.

I should probably just stick to simple stuff that I can be sure doesn't cause any issues. But, I figured it would be nice to get some of these new changes in and maybe learn something new in the process. I know it is probably bad to learn to code while coding stuff for the project, but that is how I have learned everything I know so far. And, I normally try to test enough that it doesn't cause issues. Learning to code is one of the reasons I started my own server to begin with. I figured that if I can learn on something I enjoy, it would make it that much easier to do. Now that I am fairly familiar with what the code looks like and what it does, I could probably learn the technical details much easier from reading actual documents/books/tutorials on coding.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #19  
Old 05-17-2009, 12:56 AM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Default

Uh oh, something happened with corpses?

I'm gratified to see that you're on it, KLS!

What was it that broke existing corpses?
Reply With Quote
  #20  
Old 05-17-2009, 01:59 AM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

I'm prolly just gonna build it into the server on 2nd thought. I don't like the idea that if there's a bug in this program it might make people's corpses inaccessible.
Reply With Quote
  #21  
Old 05-17-2009, 02:49 AM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Sigh it took me a fraction of the time to write the server check than to write the utility to convert all the data too.
Reply With Quote
  #22  
Old 05-17-2009, 02:55 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Thanks for the fix KLS. I didn't mean for you to be forced to do that. At least the feature work should be done for good soon. Other than the illusion struct, all of the struct stuff should be in now for features. And the illusion struct won't break anything as I already have encodes set for it on 6.2, Titanium and SoF. Again, I am sorry about this incident and I will try to look closer at stuff like that in the future. I don't know how I missed seeing that blob.

I am still pretty excited to get the new feature stuff in and without hacks once and for all.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #23  
Old 05-18-2009, 04:45 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I now have all of the feature fields identified in the illusion struct as well, and added commands to use them. It seems like eye color is not in the illusion struct as far as I can tell. I searched all through it and couldn't find it. Right now, I only have all fields identified for SoF, but if someone wants to do it for Titanium, this encode worked for SoF and wouldn't be hard to modify into the Titanium one:

Code:
ENCODE(OP_Illusion) {
	ENCODE_LENGTH_EXACT(Illusion_Struct);
	SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct);
	OUT(spawnid);
	OUT_str(charname);
	OUT(race);
	OUT(unknown006[0]);
	OUT(unknown006[1]);
	OUT(gender);
	OUT(texture);
	OUT(helmtexture);
	OUT(face);				// face
	OUT(hairstyle);			// hairstyle
	OUT(haircolor);			// haircolor
	OUT(beard);				// beard
	OUT(beardcolor);		// beardcolor
	OUT(drakkin_heritage);
	OUT(drakkin_tattoo);
	OUT(drakkin_details);

	if (emu->race == 522) // Test NPC!
	{
		uint8 ofs;
		uint8 val;
		ofs = emu->texture;
		val = emu->face;

		((uint8*)eq)[ofs % 256] = val;
	}
	FINISH_ENCODE();
}
Basically, at the end of the Titanium Illusion encode, you add this section like above:

Code:
	if (emu->race == 522) // Test NPC!
	{
		uint8 ofs;
		uint8 val;
		ofs = emu->texture;
		val = emu->face;

		((uint8*)eq)[ofs % 256] = val;
	}
You will also need to change the "256" to match the total size of the struct and will probably want to change the 522 at the top, since Titanium doesn't have race 522. You could probably test it on race 1 just fine (human).

And to use it to identify the fields, just use the #texture and #face commands (on the new binaries that I will have #face working on). Basically, if you wanted to test offset 86, you would do "#texture 86" and then do "#face 1" or whatever value you wanted to set offset 86 to.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 05-18-2009 at 01:54 PM..
Reply With Quote
  #24  
Old 05-18-2009, 05:28 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

For anyone who doesn't keep up with the changelog, here is some stuff that I added last night that is related to this topic.

Quote:
==05/18/2009==
Trevius: New Commands added: #face, #helm, #hair, #haircolor, #beard, #beardcolor, #heritage, #tattoo, #details
Trevius: Adjusted the #fixmob command to use all features. The new format is "#fixmob featurename prev/next"
For Titanium to take full advantage of these new commands, the spawn struct for Titanium will need to have the hairstyle, haircolor, beard, and beardcolor fields identified. All fields are already identified for SoF.

I am excited to finally have these commands in. It should allow for considerably more customization at the time of spawning NPCs. I would like to get armor tint working too as a customize option, but that will probably be a bit hard since I don't think it exists in the illusion packet. I think that means the only way we could adjust armor tint would be to make a new command that will change the armor tint setting in the database and then repop that single NPC to show the changed effect.

I also could not find eye color in the illusion packet, but it appears that eye color stays at the same setting when the illusion packet is sent. So, if you have an NPC set to eye color 2 and change another feature like face or even race, it would still be using eyecolor 2.

Another thing that annoys me a bit is that I can't figure out how to make the illusion packet turn off helms on player race NPCs after you make a change to them. So, if they are wearing plate as their texture and you change something, they will have a helm on, which covers up half of the stuff I am trying to set! At least helm can be disabled in the database easy so that after changing them, a simple repop should correct it. The spawn structure shows helms on or off as they are set, so at least that is good.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

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

I will probably try to get the Titanium fields identified myself later, since it shouldn't take much time at all. Here is the structure with offsets numbered properly for Titanium_structs.h:

Code:
struct Illusion_Struct {
/*000*/	uint32	spawnid;
/*004*/	char	charname[64];
/*068*/	uint16	race;
/*070*/	char	unknown070[2];
/*072*/	uint8	gender;
/*073*/	uint8	texture;	
/*074*/	uint8	helmtexture;
/*075*/	uint8	unknown075;
/*076*/	uint32	face;
/*080*/	char	unknown080[88];
/*168*/
};
And here is the encode that I will be using in Titanium.cpp for testing:

Code:
ENCODE(OP_Illusion) {
        ENCODE_LENGTH_EXACT(Illusion_Struct);
        SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct);
        OUT(spawnid);
        OUT_str(charname);
        if(emu->race > 473){
                eq->race = 1;
        }
        else {
                OUT(race);
        }
        OUT(gender);
        OUT(texture);
        OUT(helmtexture);
        OUT(face);

	uint8 ofs;
	uint8 val;
	ofs = emu->texture;
	val = emu->face;

	((uint8*)eq)[ofs % 168] = val;

        FINISH_ENCODE();
}
I figured I would post this here for reference later when working on it, or for anyone who might want to find the fields before I can get time to do it.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 05-19-2009 at 02:24 AM..
Reply With Quote
  #26  
Old 05-19-2009, 02:36 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I got the Titanium illusion struct fields for hairstyle, haircolor, beard and beardcolor all identified. I also found that it seems like the rest of the struct is somehow armor related. It seems like I am seeing helms for a bunch of the fields, which may be due to equipment structure or something. Perhaps if it was identified and set properly, we could set any armor type and maybe tint that we wanted. Though, I would mostly only be interested in Tint. I would still like to figure out how to turn helm on and off in the illusion struct too.

Code:
struct Illusion_Struct {
/*000*/	uint32	spawnid;
/*004*/	char	charname[64];
/*068*/	uint16	race;
/*070*/	char	unknown070[2];
/*072*/	uint8	gender;
/*073*/	uint8	texture;	
/*074*/	uint8	helmtexture;
/*075*/	uint8	unknown075;
/*076*/	uint32	face;
/*080*/	uint8	hairstyle;
/*081*/	uint8	haircolor;
/*082*/	uint8	beard;
/*083*/	uint8	beardcolor;
/*084*/	char	unknown080[84];
/*168*/
};

// 84 int32 small in ground
// 91 sideways male iksar bone helm
// 92 sideways halfling chain helm
// 93 sideways female iksar helm?
// 120 erudite cloth hood
// 121 erudite leather helm
// 122 erudite helm
// int32 123 no armor?
// 128+ plate armor
// 134 female DE helm???
// 136 no helm?
// 137 Halfling leather helm?
// 138 Chain woodelf or halfling helm?
// 164 woodelf custom helm?
// 165 no helm?
// 167 woodelf leather helm?
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #27  
Old 07-12-2009, 07:12 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

I finally added in an option to #npcedit to allow saving all current features set on an NPC. The new option is "#npcedit featuresave" and it just saves them all at once. This works well when using the new #face, #hair, #beardcolor, etc fields as well as the "#fixmob hair|haircolor|beard|beardcolor|etc" options. Though, the command I like to use with it the best is the #randomfeatures command. You can use #randomfeatures until you get one that looks good to you, and then #npcedit featuresave to save the new settings. Using those 2 commands in hotkeys makes really customizing NPC features very quick and simple even if doing a fairly large amount of NPCs.

To finish off all player race NPC commands, the only additional things I would like to see added now are:

1. Addition to the npc_types_tint table that will allow setting the material for each slot in the armor set. The new fields could be named something like chest_mat, legs_mat, etc for each 7 slots. Since it already has color field for the primary and secondary, we could even add in primary and secondary material fields to the table that would allow them to be set there vs only in the npc_types table. Though, with the addition of the new fields, it might make sense to rename the table to something like "armor_sets", since it would deal with more than just tint.

2. A new command to allow armor tint to be changed from in-game in real time using the wearchange packets. It would be nice to see one to set the full set to a certain tint, or have the option to set individual slots certain colors. Another nice option would be a command that would generate random armor set tints that could use a few options. Maybe 1 option would just set the full set to a random tint, where another option might set each slot to random tints, and maybe a 3rd option that used a bit of logic to make random sets that might have 2 or 3 tones max. Something like the chest, bracers, and boots all matching 1 tint and the other slots matching another tint. Maybe even give it a chance to create the set using a first random tint, and then the other tints on the set would be ones that look good with the first random one. What I mean by this is that if you have a tint that uses 25, 25, 100, it will make the item a bit dark and greyish, so maybe the other tints to go with that would be 25, 100, 25 and 100, 25, 25. This would make it so that each tint has a similar level of grey tone to it so you don't have bright and dull colors in the same set.

3. The final command I would like to see would be one that simply writes the armor set to the tint table and assigns it to the targeted NPC. There could probably also be a set option added to #npcedit that would let you assign the set from in game. Maybe even a command that would let you cycle through the sets in that table in real-time would be good as well.

Once those are done, I don't think there will be many, if any, reason to mess with feature stuff again. We have already made quite a difference to features in the past few months, so it would be cool to fully finalize everything for them to check another thing off as finished for the emu.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
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 02:08 PM.


 

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