More stuff

This commit is contained in:
Akkadius 2014-08-31 21:31:44 -05:00
parent ca430e2494
commit 6497bdf45a
7 changed files with 243 additions and 178 deletions

View File

@ -1086,6 +1086,28 @@ bool Database::CheckDatabaseConversions() {
QueryDatabase(rquery);
printf(" done...\n");
}
/* Check for table `character_material` */
rquery = StringFormat("SHOW TABLES LIKE 'character_material'");
results = QueryDatabase(rquery);
// blue, green, red, use_tint,
if (results.RowCount() == 0){
printf("Table: `character_material` doesn't exist... creating...");
rquery = StringFormat(
"CREATE TABLE `character_material` ( "
"`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
"`slot` tinyint(11) UNSIGNED NOT NULL DEFAULT '0',"
"`blue` tinyint(11) UNSIGNED NOT NULL DEFAULT '0',"
"`green` tinyint(11) UNSIGNED NOT NULL DEFAULT '0',"
"`red` tinyint(11) UNSIGNED NOT NULL DEFAULT '0',"
"`use_tint` tinyint(11) UNSIGNED NOT NULL DEFAULT '0',"
"`color` int(11) UNSIGNED NOT NULL DEFAULT '0',"
"PRIMARY KEY(`id`, `slot`),"
"KEY `id` (`id`)"
") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;"
);
QueryDatabase(rquery);
printf(" done...\n");
}
/* Done */
printf("Starting conversion...\n\n");
@ -1093,7 +1115,7 @@ bool Database::CheckDatabaseConversions() {
// querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238");
int char_iter_count = 0;
querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 100");
querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 10");
if (RunQuery(query, querylen, errbuf, &result)) {
safe_delete_array(query);
while (row = mysql_fetch_row(result)) {
@ -1105,14 +1127,15 @@ bool Database::CheckDatabaseConversions() {
pp = (PlayerProfile_Struct*)row2[1];
character_id = atoi(row[0]);
account_id = atoi(row2[4]);
/* Verify PP Integrity */
lengths = mysql_fetch_lengths(result2);
if (lengths[1] == sizeof(PlayerProfile_Struct)) {
if (lengths[1] > 0) {
memcpy(pp, row2[1], sizeof(PlayerProfile_Struct));
// printf("FINE: Player profile '%s' %i length mismatch Expected: %i, Got: %i \n", row2[2], atoi(row2[3]), sizeof(PlayerProfile_Struct), lengths[1]);
// printf("FINE: Player profile '%s' %i length Expected: %i, Got: %i \n", row2[2], atoi(row2[3]), sizeof(PlayerProfile_Struct), lengths[1]);
}
/* Continue of PP Size does not match (Usually a created character never logged in) */
else {
else {
// printf("NO PP: Player profile '%s' %i length mismatch Expected: %i, Got: %i \n", row2[2], atoi(row2[3]), sizeof(PlayerProfile_Struct), lengths[1]);
continue;
}
@ -1483,6 +1506,14 @@ bool Database::CheckDatabaseConversions() {
QueryDatabase(rquery);
}
}
/* Run Material Color Convert */
for (i = 0; i < _MaterialCount; i++){
if (pp->item_tint[i].color > 0){
if (pp->item_tint[i].rgb.use_tint > 0){ pp->item_tint[i].rgb.use_tint = 1; }
rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color);
QueryDatabase(rquery);
}
}
}
/* Print out the entire Player Profile for testing */

View File

@ -35,12 +35,10 @@ extern std::vector<RaceClassCombos> character_create_race_class_combos;
// solar: the current stuff is at the bottom of this function
void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs) {
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
Inventory *inv;
/* Initialize Player Profile for the small time it is being used for item material */
PlayerProfile_Struct pp;
memset(&pp, 0, sizeof(PlayerProfile_Struct));
/* Initialize Variables */
for (int i=0; i<10; i++) {
strcpy(cs->name[i], "<none>");
@ -50,188 +48,194 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
cs->gohome[i] = 0;
}
int char_num = 0;
unsigned long* lengths;
/* Get Character Info */
std::string cquery = StringFormat(
"SELECT "
"`id`, " // 0
"name, " // 1
"gender, " // 2
"race, " // 3
"class, " // 4
"`level`, " // 5
"deity, " // 6
"last_login, " // 7
"time_played, " // 8
"hair_color, " // 9
"beard_color, " // 10
"eye_color_1, " // 11
"eye_color_2, " // 12
"hair_style, " // 13
"beard, " // 14
"face, " // 15
"drakkin_heritage, " // 16
"drakkin_tattoo, " // 17
"drakkin_details, " // 18
"zone_id " // 19
"FROM "
"character_data "
"WHERE `account_id` = %i LIMIT 10 ", account_id);
auto results = database.QueryDatabase(cquery); uint16 char_num = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
printf("id is %i \n", atoi(row[0]));
uint32 character_id = atoi(row[0]);
strcpy(cs->name[char_num], row[1]);
uint8 lvl = atoi(row[5]);
cs->level[char_num] = lvl;
cs->class_[char_num] = atoi(row[4]);
cs->race[char_num] = atoi(row[3]);
cs->gender[char_num] = atoi(row[2]);
cs->deity[char_num] = atoi(row[6]);
cs->zone[char_num] = atoi(row[19]);
cs->face[char_num] = atoi(row[15]);
cs->haircolor[char_num] = atoi(row[9]);
cs->beardcolor[char_num] = atoi(row[10]);
cs->eyecolor2[char_num] = atoi(row[12]);
cs->eyecolor1[char_num] = atoi(row[11]);
cs->hairstyle[char_num] = atoi(row[13]);
cs->beard[char_num] = atoi(row[14]);
cs->drakkin_heritage[char_num] = atoi(row[16]);
cs->drakkin_tattoo[char_num] = atoi(row[17]);
cs->drakkin_details[char_num] = atoi(row[18]);
// 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]);
if (RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
cs->tutorial[char_num] = 1;
// 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->hairstyle[char_num] = pp->hairstyle;
cs->beard[char_num] = pp->beard;
cs->drakkin_heritage[char_num] = pp->drakkin_heritage;
cs->drakkin_tattoo[char_num] = pp->drakkin_tattoo;
cs->drakkin_details[char_num] = pp->drakkin_details;
if (RuleB(World, EnableReturnHomeButton)) {
int now = time(nullptr);
if ((now - atoi(row[8])) >= RuleI(World, MinOfflineTimeToReturnHome))
cs->gohome[char_num] = 1;
}
if(RuleB(World, EnableTutorialButton) && (lvl <= RuleI(World, MaxLevelForTutorial)))
cs->tutorial[char_num] = 1;
/*
This part creates home city entries for characters created before the home bind point was tracked.
Do it here because the player profile is already loaded and it's as good a spot as any. This whole block should
probably be removed at some point, when most accounts are safely converted.
*/
if(RuleB(World, EnableReturnHomeButton)) {
int now = time(nullptr);
if((now - pp->lastlogin) >= RuleI(World, MinOfflineTimeToReturnHome))
cs->gohome[char_num] = 1;
}
/* Load Character Bind Data */
cquery = StringFormat("SELECT zone_id, instance_id, x, y, z, heading FROM character_bind_home WHERE `id` = %i LIMIT 1", character_id);
auto results_bind = database.QueryDatabase(cquery); int r = 0;
for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
uint8 bind_zone_id = atoi(row_b[r]); r++;
uint8 bind_instance_id = atoi(row_b[r]); r++;
uint8 bind_x_id = atoi(row_b[r]); r++;
uint8 bind_y_id = atoi(row_b[r]); r++;
uint8 bind_z_id = atoi(row_b[r]); r++;
uint8 bind_heading_id = atoi(row_b[r]); r++;
}
// if (pp->binds[4].zoneId == 0) {
// bool altered = false;
// MYSQL_RES *result2;
// MYSQL_ROW row2;
// char startzone[50] = { 0 };
//
// // check for start zone variable (I didn't even know any variables were still being used...)
// if (database.GetVariable("startzone", startzone, 50)) {
// uint32 zoneid = database.GetZoneID(startzone);
// if (zoneid) {
// pp->binds[4].zoneId = zoneid;
// GetSafePoints(zoneid, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
// altered = true;
// }
// }
// else {
// RunQuery(query,
// MakeAnyLenString(&query,
// "SELECT zone_id,bind_id,x,y,z FROM start_zones "
// "WHERE player_class=%i AND player_deity=%i AND player_race=%i",
// pp->class_,
// pp->deity,
// pp->race
// ),
// errbuf,
// &result2
// );
// safe_delete_array(query);
//
// // if there is only one possible start city, set it
// if (mysql_num_rows(result2) == 1) {
// row2 = mysql_fetch_row(result2);
// if (atoi(row2[1]) != 0) { // if a bind_id is specified, make them start there
// pp->binds[4].zoneId = (uint32)atoi(row2[1]);
// GetSafePoints(pp->binds[4].zoneId, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
// }
// else { // otherwise, use the zone and coordinates given
// pp->binds[4].zoneId = (uint32)atoi(row2[0]);
// float x = atof(row2[2]);
// float y = atof(row2[3]);
// float z = atof(row2[4]);
// if (x == 0 && y == 0 && z == 0)
// GetSafePoints(pp->binds[4].zoneId, 0, &x, &y, &z);
//
// pp->binds[4].x = x;
// pp->binds[4].y = y;
// pp->binds[4].z = z;
// }
// altered = true;
// }
//
// mysql_free_result(result2);
// }
// }
// This part creates home city entries for characters created before the home bind point was tracked.
// Do it here because the player profile is already loaded and it's as good a spot as any. This whole block should
// probably be removed at some point, when most accounts are safely converted.
if(pp->binds[4].zoneId == 0) {
bool altered = false;
MYSQL_RES *result2;
MYSQL_ROW row2;
char startzone[50] = {0};
/*
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
*/
// check for start zone variable (I didn't even know any variables were still being used...)
if(database.GetVariable("startzone", startzone, 50)) {
uint32 zoneid = database.GetZoneID(startzone);
if(zoneid) {
pp->binds[4].zoneId = zoneid;
GetSafePoints(zoneid, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
altered = true;
}
}
else {
RunQuery(query,
MakeAnyLenString(&query,
"SELECT zone_id,bind_id,x,y,z FROM start_zones "
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
pp->class_,
pp->deity,
pp->race
),
errbuf,
&result2
);
safe_delete_array(query);
/* Load Character Material Data for Char Select */
cquery = StringFormat("SELECT slot, use_tint, color FROM `character_material` WHERE `id` = %u", character_id);
auto results_b = database.QueryDatabase(cquery); uint8 slot = 0;
for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
slot = atoi(row_b[0]);
if (atoi(row_b[1]) == 1){ pp.item_tint[slot].rgb.use_tint = 0xFF; }
pp.item_tint[slot].color = atoul(row_b[2]);
printf("charid: %u \n", character_id);
printf("slot: %u \n", slot);
printf("use_tint: %u item_tint: %u \n", pp.item_tint[slot].rgb.use_tint, atoul(row_b[2]));
cs->cs_colors[char_num][slot].color = atoul(row_b[2]);
}
// if there is only one possible start city, set it
if(mysql_num_rows(result2) == 1) {
row2 = mysql_fetch_row(result2);
if(atoi(row2[1]) != 0) { // if a bind_id is specified, make them start there
pp->binds[4].zoneId = (uint32)atoi(row2[1]);
GetSafePoints(pp->binds[4].zoneId, 0, &pp->binds[4].x, &pp->binds[4].y, &pp->binds[4].z);
}
else { // otherwise, use the zone and coordinates given
pp->binds[4].zoneId = (uint32)atoi(row2[0]);
float x = atof(row2[2]);
float y = atof(row2[3]);
float z = atof(row2[4]);
if(x == 0 && y == 0 && z == 0)
GetSafePoints(pp->binds[4].zoneId, 0, &x, &y, &z);
/* Load Inventory */
Inventory *inv;
inv = new Inventory;
if (GetInventory(account_id, cs->name[char_num], inv)) {
for (uint8 material = 0; material <= 8; material++) {
uint32 color = 0;
ItemInst *item = inv->GetItem(Inventory::CalcSlotFromMaterial(material));
if (item == 0)
continue;
pp->binds[4].x = x;
pp->binds[4].y = y;
pp->binds[4].z = z;
}
altered = true;
}
cs->equip[char_num][material] = item->GetItem()->Material;
mysql_free_result(result2);
}
color = pp.item_tint[material].color;
// if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; }
// else{ color = item->GetItem()->Color; }
// update the player profile
if(altered) {
uint32 char_id = GetCharacterID(cs->name[char_num]);
RunQuery(query,MakeAnyLenString(&query,"SELECT extprofile FROM character_ WHERE id=%i",char_id), errbuf, &result2);
safe_delete_array(query);
if(result2) {
row2 = mysql_fetch_row(result2);
ExtendedProfile_Struct* ext = (ExtendedProfile_Struct*)row2[0];
// SetPlayerProfile(account_id,char_id,pp,inv,ext, 0, 0, 5);
}
mysql_free_result(result2);
}
} // end of "set start zone" block
cs->cs_colors[char_num][material].color = color;
// 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==MaterialPrimary) || (material==MaterialSecondary))
{
if(strlen(item->GetItem()->IDFile) > 2) {
uint32 idfile=atoi(&item->GetItem()->IDFile[2]);
if (material==MaterialPrimary)
cs->primary[char_num]=idfile;
else
cs->secondary[char_num]=idfile;
}
}
// the weapons are kept elsewhere
if ((material == MaterialPrimary) || (material == MaterialSecondary)) {
if (strlen(item->GetItem()->IDFile) > 2) {
uint32 idfile = atoi(&item->GetItem()->IDFile[2]);
if (material == MaterialPrimary)
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
{
std::cout << "Got a bogus character (" << row[0] << ") Ignoring!!!" << std::endl;
std::cout << "PP length ="<<lengths[1]<<" but PP should be "<<sizeof(PlayerProfile_Struct) << std::endl;
//DeleteCharacter(row[0]);
}
}
mysql_free_result(result);
}
else
{
std::cerr << "Error in GetCharSelectInfo query '" << query << "' " << errbuf << std::endl;
safe_delete_array(query);
return;
else {
printf("Error loading inventory for %s\n", cs->name[char_num]);
}
safe_delete(inv);
if (++char_num > 10)
break;
}
return;

View File

@ -3120,6 +3120,7 @@ void Client::SetTint(int16 in_slot, uint32 color) {
Color_Struct new_color;
new_color.color = color;
SetTint(in_slot, new_color);
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color);
}
// Still need to reconcile bracer01 versus bracer02
@ -3147,6 +3148,8 @@ void Client::SetTint(int16 in_slot, Color_Struct& color) {
m_pp.item_tint[MaterialLegs].color=color.color;
else if (in_slot==MainFeet)
m_pp.item_tint[MaterialFeet].color=color.color;
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
}
void Client::SetHideMe(bool flag)

View File

@ -597,6 +597,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
database.LoadCharacterMaterial(cid, &m_pp); /* Load Character Material */
database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency into PP */
database.LoadCharacterData(cid, &m_pp); /* Load Character Data from DB into PP */
database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */

View File

@ -1877,7 +1877,9 @@ void Client::DyeArmor(DyeStruct* dye){
uint8 slot2=SlotConvert(i);
ItemInst* inst = this->m_inv.GetItem(slot2);
if(inst){
inst->SetColor((dye->dye[i].rgb.red*65536)+(dye->dye[i].rgb.green*256)+(dye->dye[i].rgb.blue));
uint32 armor_color = (dye->dye[i].rgb.red * 65536) + (dye->dye[i].rgb.green * 256) + (dye->dye[i].rgb.blue);
inst->SetColor(armor_color);
database.SaveCharacterMaterialColor(this->CharacterID(), slot2, armor_color);
database.SaveInventory(CharacterID(),inst,slot2);
if(dye->dye[i].rgb.use_tint)
m_pp.item_tint[i].rgb.use_tint = 0xFF;
@ -1898,7 +1900,7 @@ void Client::DyeArmor(DyeStruct* dye){
EQApplicationPacket* outapp=new EQApplicationPacket(OP_Dye,0);
QueuePacket(outapp);
safe_delete(outapp);
Save();
}
/*bool Client::DecreaseByItemType(uint32 type, uint8 amt) {

View File

@ -1145,6 +1145,28 @@ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Str
return true;
}
bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){
std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color) VALUES (%u, %u, %u)", character_id, slot_id, color); QueryDatabase(query);
LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color);
return true;
}
bool ZoneDatabase::LoadCharacterMaterial(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT slot, blue, green, red, use_tint, color FROM `character_material` WHERE `id` = %u LIMIT 9", character_id);
auto results = database.QueryDatabase(query); int i = 0; int r = 0;
for (auto row = results.begin(); row != results.end(); ++row) {
r = 0;
i = atoi(row[r]); /* Slot */ r++;
pp->item_tint[i].rgb.blue = atoi(row[r]); r++;
pp->item_tint[i].rgb.green = atoi(row[r]); r++;
pp->item_tint[i].rgb.red = atoi(row[r]); r++;
if (row[r] && atoi(row[r]) > 0){ pp->item_tint[i].rgb.use_tint = 0xFF; } r++;
pp->item_tint[i].color = atoi(row[r]); r++;
printf("Loading color: %u tint: %u \n", pp->item_tint[i].color, pp->item_tint[i].rgb.use_tint);
}
return true;
}
bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){
clock_t t = std::clock(); /* Function timer start */
if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; }

View File

@ -266,6 +266,7 @@ public:
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
bool LoadCharacterMaterial(uint32 character_id, PlayerProfile_Struct* pp);
/* Character Data Saves */
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
@ -274,6 +275,7 @@ public:
bool SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot);
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
/* Character Data Deletes */
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);