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)

 
 
Thread Tools Display Modes
Prev Previous Post   Next Post Next
  #1  
Old 05-10-2009, 05:53 PM
Shendare
Dragon
 
Join Date: Apr 2009
Location: California
Posts: 814
Cool SoF Spawn_Struct Hacking

I'm new to the PEQ scene, and would like to find ways to contribute.

I thought I might get my feet wet looking into the server code by trying to figure out some of the unknown fields in Spawn_Struct like haircolor, beardcolor, etc.

I found the place in SoF.cpp where such tinkering should go, inside ENCODE(OP_ZoneSpawns) starting around line 757, and knew there needed to be a better way to test things than coding values into random unknown fields and re-compiling for each test.

I put together a little bit of hack code that allows you to push test values into any of the unknown fields of the Spawn_Struct struct at run-time using a test NPC's lastname.

Code:
		//Hack Test for finding more fields in the Struct:
		if (emu->lastName[0] == '*') // Test NPC!
		{
			char code = emu->lastName[1];
			char* sep = (char*)memchr(&emu->lastName[2], '=', 10);
			uint32 ofs;
			uint32 val;
			uint8 rnd = rand() & 0x0F;
			if (sep == NULL)
			{
				ofs = 0;
				if ((emu->lastName[2] < '0') || (emu->lastName[2] > '9'))
				{
					val = rnd;
				}
				else
				{
					val = atoi(&emu->lastName[2]);
				}
			}
			else
			{
				sep[0] = NULL;
				ofs = atoi(&emu->lastName[2]);
				sep[0] = '=';
				if ((sep[1] < '0') || (sep[1] > '9'))
				{
					val = rnd;
				}
				else
				{
					val = atoi(&sep[1]);
				}
			}

			char hex[] = "0123456789ABCDEF";
			size_t len = strlen(emu->lastName);
			
			eq->lastName[len + 0] = ' ';
			eq->lastName[len + 1] = code;
			eq->lastName[len + 2] = '0' + ((ofs / 1000) % 10);
			eq->lastName[len + 3] = '0' + ((ofs / 100) % 10);
			eq->lastName[len + 4] = '0' + ((ofs / 10) % 10);
			eq->lastName[len + 5] = '0' + (ofs % 10);
			eq->lastName[len + 6] = '=';
			eq->lastName[len + 7] = '0' + ((val / 100) % 10);
			eq->lastName[len + 8] = '0' + ((val / 10) % 10);
			eq->lastName[len + 9] = '0' + (val % 10);
			eq->lastName[len + 10] = 0x00;

			switch (code)
			{
				case 'a':
					eq->unknown0001[ofs % 4] = val; break;
				case 'b':
					eq->unknown0006 = val; break;
				case 'c':
					eq->unknown0008 = val; break;
				case 'd':
					eq->unknown0011[ofs % 6] = val; break;
				case 'e':
					eq->unknown0009 = val; break;
				case 'f':
					eq->unknown0010[ofs % 4] = val; break;
				case 'g':
					eq->unknown0048[ofs % 4] = val; break;
				case 'h':
					eq->unknown0059 = val; break;
				case 'i':
					eq->unknown0074[ofs % 24] = val; break;
				case 'j':
					eq->unknown0077[ofs % 7] = val; break;
				case 'k':
					eq->unknown00771[ofs % 184] = val; break;
				case 'l':
					eq->unknown00772[ofs % 10] = val; break;
				case 'm':
					eq->unknown0079[ofs % 123] = val; break;
				case 'n':
					eq->unknown0080[ofs % 10] = val; break;
				case 'o':
					eq->unknown0106[ofs % 4] = val; break;
				case 'p':
					eq->unknown0107[ofs % 5] = val; break;
				case 'q':
					eq->unknown01071[ofs % 5] = val; break;
				case 'r':
					eq->unknown0108[ofs % 6] = val; break;
				case 's':
					eq->unknown01082[ofs % 6] = val; break;
				case 't':
					eq->unknown0110[ofs % 20] = val; break;
				case 'u':
					eq->unknown01101[ofs % 21] = val; break;
				case 'v':
					eq->unknown0154[ofs % 4] = val; break;
				case 'w':
					eq->unknown0155[ofs % 4] = val; break;
				case 'x':
					eq->unknown0156[ofs % 4] = val; break;
				case 'y':
					eq->unknown0157[ofs % 4] = val; break;
				case 'z':
					eq->unknown0158[ofs % 4] = val; break;
				case 'A':
					eq->unknown0159[ofs % 4] = val; break;
				case 'B':
					eq->unknown0160[ofs % 4] = val; break;
				case 'C':
					eq->unknown0161[ofs % 4] = val; break;
				case 'D':
					eq->unknown0162[ofs % 4] = val; break;
				case 'E':
					eq->unknown0163[ofs % 4] = val; break;
				case 'F':
					eq->unknown0263[ofs % 2] = val; break;
				case 'G':
					eq->unknown0281 = val; break;
				case 'H':
					eq->unknown0308[ofs % 4] = val; break;
				case 'I':
					eq->unknown0309[ofs % 11] = val; break;
				case 'J':
					eq->unknown442[ofs % 8] = val; break;
				case 'K':
					eq->unknown0760 = val; break;
				case 'L':
					eq->unknown0761 = val; break;
				case 'M':
					eq->unknown0762 = val; break;
				case 'O':
					eq->unknown0763 = val; break;
				case 'P':
					eq->unknown0764 = val; break;
				case 'Q':
					eq->unknown0496[ofs % 2] = val; break;
				case 'X':
					((uint8*)eq)[ofs % 897] = val; break;
				case 'Z':
					eq->size = (float)val; break; // Test w/ size.
			}
To use the code, simply target any NPC in-game and change its last name to follow the special formula:

*(Code)[Optional-Offset=](Value)

I've been testing on Exterminator Valern just inside Felwithe, so I can target him and type "#npcedit lastname *Z2", then "#repop" (I've hotkeyed that one), and Valern will respawn with a size of 2, instead of his default 6!

You'll also get debug output tacked to the end of the lastname letting you know exactly what the hack-code interpreted from your formula. The debug output is in the format "(Code)(4-digit Offset)=(3-digit Value)". Because the Z code for size doesn't use an offset, the debug output for the previous example will be "Z0000=002".

If you want the code to pick a random value to put in the specified field, use any non-numeric character for the value. I generally use '?'. So, you could type "#npcedit lastname *Z?" and repop and the NPC will be a random size from 0-15 every time you repop.

For the code character, all alpha digits from a-z and A-Q map to specific sets of unknown fields in the Spawn_Struct. If you want to push the value 10 into unknown0110[3], for example, you would make the NPC's lastname "*t3=10" and repop, and there you go!

The real catch-all hack code is 'X'. If you specify X as the code character, you can push any value into any offset of Spawn_Struct. For example, looking in SoF_structs.h you see that gender is at offset 22 in the Spawn_Struct. If you specify "#npcedit lastname *X22=1", the NPC will repop as a female.

Anyway, I thought this might be useful for anyone else who feels like poking around in Spawn_Struct to try to figure out some of these many unknown fields as well!

- Shendare
Reply With Quote
 


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 01:50 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 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3