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

05-11-2009, 12:24 PM
|
Dragon
|
|
Join Date: Apr 2009
Location: California
Posts: 814
|
|
Quote:
Originally Posted by trevius
...
740 puts an exclamation point in front of the name of the NPC.
...
|
Oh my god, I think you found Doug! I remember from years and years ago after a patch, people were finding unresponsive naked human male models in random places in the game with only an exclamation point as their name. The EQ team responded to the community's questions with the response that these were test characters that aren't normally visible, and they'd figure out what broke in the patch that allowed people to see them. The team revealed the little tidbit that they had taken to calling these default human models "Doug", so whenever someone in the game found an unresponsive naked human male NPC that probably shouldn't be there (or should look different), they reported a "Doug".
I wonder if offset 740 marks the character as an EQ dev test character, and the original Doug didn't actually have "!" as its name, but had a blank name with the equivalent of Flag 740 set. That just blows my mind, and totally brings back some old EQ nostalgia. LOL.
- Shendare
|
 |
|
 |
 |
|
 |

05-11-2009, 06:00 PM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
Yeah, woads being set by factor of 10 on the face setting is known and in the wiki I believe. Shouldn't be too hard to find beard color and such once test is done with an NPC that has a beard set on them since beard is already identified.
I was thinking about the storm cloud that spawns from i5 and I actually recall something in either BoT or PoStorms about storm clouds spawning over your head and you have to move or something or something bad happens. Not too clear on the details, but it occurred to me that this is probably a case of when those effects are used.
I bet we could apply your same code to figure out more structure related stuff. Like, we could modify it for the player profile by using something that is easily changeable like currency. Just have it so that if the character has 1337 copper on their character, it will go into test mode. Then, use the plat and gold on that character to set the offset (number of plat) and what to set that offset to (number of gold). It would require zoning each time to test the changes, but it is at least a possible option to consider if we need it. Most of the player profile should be pretty good already, but if we still need to find anything in it, this would probably work.
One thing we need to get working better cosmetically is the character select screen. Unfortunately I think the client limits names during creation to only include letters. So either we would need to use letters and convert them or maybe use stats, but stats would probably be even trickier. Maybe for testing, the first 3 letters could be Z (Zzz) to designate that it is a test, and the 4th letter could be the field in the struct and the 5th would be the value to set it at. This might get a bit confusing, but the char select struct isn't overly large so it shouldn't be too much work to get it all figured out. Can't really set offsets since it is a variable length structure. I think the struct is already pretty close, so maybe finding what is throwing it off would make an easy fix to align everything back up again. There are only a few unknown fields in that struct, so I am sure those are Drakkin related, or at least most of them probably are.
Maybe for char select, we could use 1337 speak lettering in place of numbers to make it easier to set.
0 = o (O)
1 = i (I)
2 = z (Z)
3 = e (E)
4 = a (A)
5 = s (S)
6 = g (G)
7 = t (T)
8 = b (B)
9 = q (Q)
So, if you wanted to set field "a" (level) to 25, you would name the character "Zzzazs". Or if you wanted to set field "b" (haircolor) to 10, you would name the character Zzzbio.
This isn't quite as critical as the spawn struct, but everything that gets fixed makes SoF that much closer to being fully completed 
|
 |
|
 |

05-11-2009, 06:56 PM
|
Dragon
|
|
Join Date: Apr 2009
Location: California
Posts: 814
|
|
Sounds interesting! I'm all for getting SoF working better.
I did notice I left a quickie hack in the code that should be cleaned up.
This line...
Code:
size_t len = strlen(emu->lastName);
...should be moved up to this block, which should be changed to refer to it...
Code:
char code = emu->lastName[1];
+ size_t len = strlen(emu->lastName);
- char* sep = (char*)memchr(&emu->lastName[2], '=', 10);
+ char* sep = (char*)memchr(&emu->lastName[2], '=', len - 2);
uint32 ofs;
This prevents reading beyond the end of lastName in case it's fewer than 10 characters including the null.
Last edited by Shendare; 05-12-2009 at 02:57 AM..
Reason: Typo
|
 |
|
 |

05-12-2009, 07:45 AM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
I finally identified beard color as offset 373. Got all of the new fields in and adjusted the struct to have the proper offset labels as well as correctly renamed all of the unknowns. Seems to work perfectly for NPCs now. I also added in your change to mob.cpp for facial features, but that might require further testing to verify if it is a good change or not (though it makes sense to me). And, I added in your testing code in place of the sloppy hack I had commented out before lol. It is commented out, but I figure it might be useful to others doing struct work, so it may be a good idea to keep it in there as commented out. I put this up on the SVN on R501 and gave you (shendare) credit for it since you did most of it.
I think that pretty much finalizes the spawn struct, or at least very close now. Still need to figure out a few things for players, but that shouldn't be too hard I think. I put temp hacks in for the drakkin extra features so they get set in the encode to whatever face is set to. At least this will let some variety into drakkin NPCs (and PCs for now as well).
|
 |
|
 |

05-12-2009, 09:25 AM
|
Dragon
|
|
Join Date: Apr 2009
Location: California
Posts: 814
|
|
I'm glad to see that BeardColor gets applied to the face-based facial hair as well as the beard field mesh facial hair.
I dinked around a little with player appearance as well, but found that I had to modify some things. SoF's FaceChange_Struct is 24 bytes now instead of 7, assumedly to account for Tattoo, DrakkinFaceSpikes, and possibly DrakkinHeritage (though that's read-only in face changes). The rest must be reserved space.
I also noticed a block in Client::Handle_OP_FaceChange (or whatever it was called) that did something similar to the 0xFF problem above, except this time it's changing zero values to 99. That'll have to be taken out to properly handle face changes as well.
Then it's just a matter of making sure things are applied in PlayerProfile properly.
|
 |
|
 |

05-12-2009, 04:57 PM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
Yeah, I am not quite sure why they have it changing the values at all, but it seems to change them to 99 or 255 in some cases. As far as I can tell, we shouldn't be changing anything and just save the actual value and call the actual value. The conversions it is doing is almost certainly the cause of baldness and why faces have had so many issues in the past.
I know KLS did quite a bit of work on facial features in the past and I am wondering if she has any input on why those values are changed like that before I start making changes so that it uses the actual value instead of all of this converting.
Oh yeah, Drakkin NPCs look much cooler now that they aren't all exactly the same.
Another thing I wanted to mention is that a while back, I got the illusion struct all identified other than the Drakkin specific stuff. It would be nice if we could get facechange and other facial features added into the illusion function since they currently are not. I think the problem is that Titanium doesn't have the illusion struct filled out fully, so no one bothered to finish the function for illusion to add in the other features. It would also be very cool to have armor stuff (texture and tint) in the illusion function. Then, when someone clicks off an illusion, they would actually look exactly like they did before the illusion was cast instead of just returning to the same race and armor texture. I am pretty sure everything is in the illusion struct and we just need to find the armor and Drakkin stuff to completely finalize it. It wouldn't be hard to finalize the struct, but the code to handle all of it might take a bit of work to do. It would be awesome to expand the #fixmob functionality to work with faces, hairstyle, haircolor, eyecolor, beard, beardcolor, armor tint, and the new Drakkin features. Then, you could really fine tune an NPC in realtime before creating it in the database. Otherwise, it means a database change and a repop to see how it looks. Much quicker and easier to just have hotkeys and spam through the different looks until you find one you like.
Last edited by trevius; 05-13-2009 at 01:15 AM..
|
 |
|
 |
 |
|
 |

05-12-2009, 08:01 PM
|
 |
Developer
|
|
Join Date: Aug 2006
Location: USA
Posts: 5,946
|
|
Here are at least a couple places where we can try removing the 99 change for features set to 0 and see if that corrects the issues with bald players and features not showing up correctly once and for all:
zone/client_packet.cpp
Code:
void Client::Handle_OP_FaceChange(const EQApplicationPacket *app)
{
if (app->size != sizeof(FaceChange_Struct)) {
LogFile->write(EQEMuLog::Error, "Invalid size for OP_FaceChange: Expected: %i, Got: %i",
sizeof(FaceChange_Struct), app->size);
return;
}
// Notify other clients in zone
entity_list.QueueClients(this, app, false);
FaceChange_Struct* fc = (FaceChange_Struct*)app->pBuffer;
m_pp.haircolor = fc->haircolor;
m_pp.beardcolor = fc->beardcolor;
m_pp.eyecolor1 = fc->eyecolor1;
m_pp.eyecolor2 = fc->eyecolor2;
m_pp.hairstyle = fc->hairstyle;
m_pp.face = fc->face;
// vesuvias - appearence fix
m_pp.beard = fc->beard;
if (fc->face == 0) {m_pp.face = 99;}
if (fc->eyecolor1 == 0) {m_pp.eyecolor1 = 99;}
if (fc->eyecolor2 == 0) {m_pp.eyecolor2 = 99;}
if (fc->hairstyle == 0) {m_pp.hairstyle = 99;}
if (fc->haircolor == 0) {m_pp.haircolor = 99;}
if (fc->beard == 0) {m_pp.beard = 99;}
if (fc->beardcolor == 0) {m_pp.beardcolor = 99;}
Save();
Message_StringID(13,FACE_ACCEPTED);
//Message(13, "Facial features updated.");
return;
}
world/client.cpp
Code:
bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
{
PlayerProfile_Struct pp;
ExtendedProfile_Struct ext;
Inventory inv;
time_t bday = time(NULL);
char startzone[50]={0};
uint32 i;
struct in_addr in;
int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX +
cc->WIS + cc->INT + cc->CHA;
in.s_addr = GetIP();
clog(WORLD__CLIENT,"Character creation request from %s LS#%d (%s:%d) : ", GetCLE()->LSName(), GetCLE()->LSID(), inet_ntoa(in), GetPort());
clog(WORLD__CLIENT,"Name: %s", name);
clog(WORLD__CLIENT,"Race: %d Class: %d Gender: %d Deity: %d Start zone: %d",
cc->race, cc->class_, cc->gender, cc->deity, cc->start_zone);
clog(WORLD__CLIENT,"STR STA AGI DEX WIS INT CHA Total");
clog(WORLD__CLIENT,"%3d %3d %3d %3d %3d %3d %3d %3d",
cc->STR, cc->STA, cc->AGI, cc->DEX, cc->WIS, cc->INT, cc->CHA,
stats_sum);
clog(WORLD__CLIENT,"Face: %d Eye colors: %d %d", cc->face, cc->eyecolor1, cc->eyecolor2);
clog(WORLD__CLIENT,"Hairstyle: %d Haircolor: %d", cc->hairstyle, cc->haircolor);
clog(WORLD__CLIENT,"Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor);
// validate the char creation struct
if(!CheckCharCreateInfo(cc))
{
clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)");
return false;
}
// Convert incoming cc_s to the new PlayerProfile_Struct
memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile
InitExtendedProfile(&ext);
strncpy(pp.name, name, 63);
// clean the capitalization of the name
#if 0 // on second thought, don't - this will just make the creation fail
// because the name won't match what was already reserved earlier
for (i = 0; pp.name[i] && i < 63; i++)
{
if(!isalpha(pp.name[i]))
return false;
pp.name[i] = tolower(pp.name[i]);
}
pp.name[0] = toupper(pp.name[0]);
#endif
pp.race = cc->race;
pp.class_ = cc->class_;
pp.gender = cc->gender;
pp.deity = cc->deity;
pp.STR = cc->STR;
pp.STA = cc->STA;
pp.AGI = cc->AGI;
pp.DEX = cc->DEX;
pp.WIS = cc->WIS;
pp.INT = cc->INT;
pp.CHA = cc->CHA;
pp.face = cc->face;
pp.eyecolor1 = cc->eyecolor1;
pp.eyecolor2 = cc->eyecolor2;
pp.hairstyle = cc->hairstyle;
pp.haircolor = cc->haircolor;
pp.beard = cc->beard;
pp.beardcolor = cc->beardcolor;
if (cc->face == 0) {pp.face = 99;}
if (cc->eyecolor1 == 0) {pp.eyecolor1 = 99;}
if (cc->eyecolor2 == 0) {pp.eyecolor2 = 99;}
if (cc->hairstyle == 0) {pp.hairstyle = 99;}
if (cc->haircolor == 0) {pp.haircolor = 99;}
if (cc->beard == 0) {pp.beard = 99;}
if (cc->beardcolor == 0) {pp.beardcolor = 99;}
pp.birthday = bday;
pp.lastlogin = bday;
pp.level = 1;
pp.points = 5;
pp.cur_hp = 1000; // 1k hp during dev only
//what was the point of this? zone dosent handle this:
//pp.expAA = 0xFFFFFFFF;
pp.hunger_level = 6000;
pp.thirst_level = 6000;
// FIXME: FV roleplay, database goodness...
// Racial Languages
SetRacialLanguages( &pp ); // bUsh
SetRaceStartingSkills( &pp ); // bUsh
SetClassStartingSkills( &pp ); // bUsh
pp.skills[SENSE_HEADING] = 200;
// Some one fucking fix this to use a field name. -Doodman
//pp.unknown3596[28] = 15; // @bp: This is to enable disc usage
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
for(i = 0; i < MAX_PP_SPELLBOOK; i++)
pp.spell_book[i] = 0xFFFFFFFF;
for(i = 0; i < MAX_PP_MEMSPELL; i++)
pp.mem_spells[i] = 0xFFFFFFFF;
for(i = 0; i < BUFF_COUNT; i++)
pp.buffs[i].spellid = 0xFFFF;
//was memset(pp.unknown3704, 0xffffffff, 8);
//but I dont think thats what you really wanted to do...
//memset is byte based
//If server is PVP by default, make all character set to it.
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
// if there's a startzone variable put them in there
if(database.GetVariable("startzone", startzone, 50))
{
clog(WORLD__CLIENT,"Found 'startzone' variable setting: %s", startzone);
pp.zone_id = database.GetZoneID(startzone);
if(pp.zone_id)
database.GetSafePoints(pp.zone_id, &pp.x, &pp.y, &pp.z);
else
clog(WORLD__CLIENT_ERR,"Error getting zone id for '%s'", startzone);
}
else // otherwise use normal starting zone logic
{
if(!SoFClient)
database.GetStartZone(&pp, cc);
else
database.GetStartZoneSoF(&pp, cc);
}
if(!pp.zone_id)
{
pp.zone_id = 1; // qeynos
pp.x = pp.y = pp.z = -1;
}
if(!pp.binds[0].zoneId)
{
pp.binds[0].zoneId = pp.zone_id;
pp.binds[0].x = pp.x;
pp.binds[0].y = pp.y;
pp.binds[0].z = pp.z;
pp.binds[0].heading = pp.heading;
}
clog(WORLD__CLIENT,"Current location: %s %0.2f, %0.2f, %0.2f",
database.GetZoneName(pp.zone_id), pp.x, pp.y, pp.z);
clog(WORLD__CLIENT,"Bind location: %s %0.2f, %0.2f, %0.2f",
database.GetZoneName(pp.binds[0].zoneId), pp.binds[0].x, pp.binds[0].y, pp.binds[0].z);
// Starting Items inventory
database.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin());
// now we give the pp and the inv we made to StoreCharacter
// to see if we can store it
if (!database.StoreCharacter(GetAccountID(), &pp, &inv, &ext))
{
clog(WORLD__CLIENT_ERR,"Character creation failed: %s", pp.name);
return false;
}
else
{
clog(WORLD__CLIENT,"Character creation successful: %s", pp.name);
return true;
}
}
worlddb.cpp
Code:
void WorldDatabase::GetCharSelectInfo(int32 account_id, CharacterSelect_Struct* cs) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
Inventory *inv;
for (int i=0; i<10; i++) {
strcpy(cs->name[i], "<none>");
cs->zone[i] = 0;
cs->level[i] = 0;
cs->tutorial[i] = 0;
cs->gohome[i] = 0;
}
int char_num = 0;
unsigned long* lengths;
// Populate character info
if (RunQuery(query, MakeAnyLenString(&query, "SELECT name,profile,zonename,class,level FROM character_ WHERE account_id=%i order by name limit 10", account_id), errbuf, &result)) {
safe_delete_array(query);
while ((row = mysql_fetch_row(result))) {
lengths = mysql_fetch_lengths(result);
////////////
//////////// This is the current one, the other are for converting
////////////
if ((lengths[1] == sizeof(PlayerProfile_Struct))) {
strcpy(cs->name[char_num], row[0]);
PlayerProfile_Struct* pp = (PlayerProfile_Struct*)row[1];
uint8 clas = atoi(row[3]);
uint8 lvl = atoi(row[4]);
// Character information
if(lvl == 0)
cs->level[char_num] = pp->level; //no level in DB, trust PP
else
cs->level[char_num] = lvl;
if(clas == 0)
cs->class_[char_num] = pp->class_; //no class in DB, trust PP
else
cs->class_[char_num] = clas;
cs->race[char_num] = pp->race;
cs->gender[char_num] = pp->gender;
cs->deity[char_num] = pp->deity;
cs->zone[char_num] = GetZoneID(row[2]);
cs->face[char_num] = pp->face;
cs->haircolor[char_num] = pp->haircolor;
cs->beardcolor[char_num] = pp->beardcolor;
cs->eyecolor2[char_num] = pp->eyecolor2;
cs->eyecolor1[char_num] = pp->eyecolor1;
cs->hair[char_num] = pp->hairstyle;
cs->beard[char_num] = pp->beard;
if (pp->face == 99) {cs->face[char_num] = 0;}
if (pp->eyecolor1 == 99) {cs->eyecolor1[char_num] = 0;}
if (pp->eyecolor2 == 99) {cs->eyecolor2[char_num] = 0;}
if (pp->hairstyle == 99) {cs->hair[char_num] = 0;}
if (pp->haircolor == 99) {cs->haircolor[char_num] = 0;}
if (pp->beard == 99) {cs->beard[char_num] = 0;}
if (pp->beardcolor == 99) {cs->beardcolor[char_num] = 0;}
if(RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
cs->tutorial[char_num] = 1;
if(RuleB(World, EnableReturnHomeButton)) {
int now = time(NULL);
if((now - pp->lastlogin) >= RuleI(World, MinOfflineTimeToReturnHome))
cs->gohome[char_num] = 1;
}
// Character's equipped items
// @merth: Haven't done bracer01/bracer02 yet.
// Also: this needs a second look after items are a little more solid
// NOTE: items don't have a color, players MAY have a tint, if the
// use_tint part is set. otherwise use the regular color
inv = new Inventory;
if(GetInventory(account_id, cs->name[char_num], inv))
{
for (uint8 material = 0; material <= 8; material++)
{
uint32 color;
ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material));
if(item == 0)
continue;
cs->equip[char_num][material] = item->GetItem()->Material;
if(pp->item_tint[material].rgb.use_tint) // they have a tint (LoY dye)
color = pp->item_tint[material].color;
else // no tint, use regular item color
color = item->GetItem()->Color;
cs->cs_colors[char_num][material].color = color;
// the weapons are kept elsewhere
if ((material==MATERIAL_PRIMARY) || (material==MATERIAL_SECONDARY))
{
if(strlen(item->GetItem()->IDFile) > 2) {
int32 idfile=atoi(&item->GetItem()->IDFile[2]);
if (material==MATERIAL_PRIMARY)
cs->primary[char_num]=idfile;
else
cs->secondary[char_num]=idfile;
}
}
}
}
else
{
printf("Error loading inventory for %s\n", cs->name[char_num]);
}
safe_delete(inv);
if (++char_num > 10)
break;
}
else
{
cout << "Got a bogus character (" << row[0] << ") Ignoring!!!" << endl;
cout << "PP length ="<<lengths[1]<<" but PP should be "<<sizeof(PlayerProfile_Struct)<<endl;
//DeleteCharacter(row[0]);
}
}
mysql_free_result(result);
}
else
{
cerr << "Error in GetCharSelectInfo query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return;
}
return;
}
mob.cpp
Code:
void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
{
int i;
strcpy(ns->spawn.name, name);
if(IsClient())
strncpy(ns->spawn.lastName,lastname,sizeof(lastname));
ns->spawn.heading = FloatToEQ19(heading);
ns->spawn.x = FloatToEQ19(x_pos);//((sint32)x_pos)<<3;
ns->spawn.y = FloatToEQ19(y_pos);//((sint32)y_pos)<<3;
ns->spawn.z = FloatToEQ19(z_pos);//((sint32)z_pos)<<3;
ns->spawn.spawnId = GetID();
ns->spawn.curHp = (sint16)GetHPRatio();
ns->spawn.max_hp = 100; //this field needs a better name
ns->spawn.race = race;
ns->spawn.runspeed = runspeed;
ns->spawn.walkspeed = runspeed * 0.5f;
ns->spawn.class_ = class_;
ns->spawn.gender = gender;
ns->spawn.level = level;
ns->spawn.deity = deity;
ns->spawn.animation = 0;
ns->spawn.findable = findable?1:0;
// vesuvias - appearence fix
ns->spawn.light = light;
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
ns->spawn.NPC = IsClient() ? 0 : 1;
ns->spawn.petOwnerId = ownerid;
ns->spawn.haircolor = haircolor ? haircolor : 0xFF;
ns->spawn.beardcolor = beardcolor ? beardcolor : 0xFF;
ns->spawn.eyecolor1 = eyecolor1 ? eyecolor1 : 0xFF;
ns->spawn.eyecolor2 = eyecolor2 ? eyecolor2 : 0xFF;
ns->spawn.hairstyle = hairstyle ? hairstyle : 0xFF;
ns->spawn.face = luclinface;
ns->spawn.beard = beard ? beard : 0xFF;
ns->spawn.equip_chest2 = texture;
// ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn
//mob invis
if(helmtexture && helmtexture != 0xFF)
{
//ns->spawn.equipment[MATERIAL_HEAD] = helmtexture;
ns->spawn.helm=helmtexture;
} else {
//ns->spawn.equipment[MATERIAL_HEAD] = 0;
ns->spawn.helm = 0;
}
ns->spawn.guildrank = 0xFF;
ns->spawn.size = size;
ns->spawn.bodytype = bodytype;
// The 'flymode' settings have the following effect:
// 0 - Mobs in water sink like a stone to the bottom
// 1 - Same as #flymode 1
// 2 - Same as #flymode 2
// 3 - Mobs in water do not sink. A value of 3 in this field appears to be the default setting for all mobs
// (in water or not) according to 6.2 era packet collects.
if(IsClient())
ns->spawn.flymode = 0;
else
ns->spawn.flymode = 3;
ns->spawn.lastName[0] = '\0';
strncpy(ns->spawn.lastName, lastname, sizeof(lastname));
for(i = 0; i < MAX_MATERIALS; i++)
{
ns->spawn.equipment[i] = GetEquipmentMaterial(i);
ns->spawn.colors[i].color = GetEquipmentColor(i);
}
memset(ns->spawn.set_to_0xFF, 0xFF, sizeof(ns->spawn.set_to_0xFF));
}
It makes sense that NPCs load perfectly as they are set because they don't do these weird conversions. So, I think it is logical to conclude that the 99 and the 0xFF settings that are getting done are to blame for PCs not showing up properly. Seems to me like things were being overcomplicated when they should just save the number that is set and use that same number when loading the settings. The bald characters and the white hair issues should both be caused by the 99 and 0xFF settings, so removing that should correct them.
Last edited by trevius; 05-13-2009 at 06:54 AM..
|
 |
|
 |
Thread Tools |
|
Display Modes |
Hybrid Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -4. The time now is 08:53 PM.
|
|
 |
|
 |
|
|
|
 |
|
 |
|
 |