From 5cf748d1352e29ed439efb1ce9227ad22b3013c4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 27 Aug 2014 09:55:39 -0500 Subject: [PATCH 01/56] Initial work --- common/database.cpp | 390 ++++++++++++++++++++++++++++++++++++++++++++ common/database.h | 2 + world/net.cpp | 3 + zone/zonedb.cpp | 7 +- 4 files changed, 399 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 8d27d5b46..b90340ad9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -18,6 +18,7 @@ #include "../common/debug.h" #include "../common/rulesys.h" #include +#include #include #include #include @@ -771,6 +772,395 @@ void Database::GetCharName(uint32 char_id, char* name) { strcpy(name, row[0]); } +static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) +{ + if ((x != n) && (x % (n / 100 + 1) != 0)) return; + + float ratio = x / (float)n; + int c = ratio * w; + + std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; + for (int x = 0; xchecksum); + printf("name: %s \n", pp->name); + printf("last_name: %s \n", pp->last_name); + printf("gender: %i \n", pp->gender); + printf("race: %i \n", pp->race); + printf("class_: %i \n", pp->class_); + printf("unknown0112: %i \n", pp->unknown0112); + printf("level: %i \n", pp->level); + + printf("\n=== BIND DATA (Array Size 5) ===\n"); + for (i = 0; i < 5; i++){ + printf("Bind Num: %i ZoneID: %u x: %f y: %f z: %f heading: %f \n", i, pp->binds[i].zoneId, pp->binds[i].x, pp->binds[i].y, pp->binds[i].z, pp->binds[i].heading); + } + printf("\n"); + + printf("deity: %u \n", pp->deity); + printf("guild_id: %u \n", pp->guild_id); + printf("birthday: %u \n", pp->birthday); + printf("lastlogin: %u \n", pp->lastlogin); + printf("timePlayedMin: %u \n", pp->timePlayedMin); + printf("pvp: %u \n", pp->pvp); + printf("level2: %u \n", pp->level2); + printf("anon: %u \n", pp->anon); + printf("gm: %u \n", pp->gm); + printf("guildrank: %u \n", pp->guildrank); + printf("guildbanker: %u \n", pp->guildbanker); + printf("unknown0246[6]: %u \n", pp->unknown0246[6]); + printf("intoxication: %u \n", pp->intoxication); + + printf("\n=== Spell Slot Refresh spellSlotRefresh[MAX_PP_MEMSPELL] ===\n"); + for (i = 0; i < MAX_PP_MEMSPELL; i++){ + printf("Slot: %i Value: %u \n", i, pp->spellSlotRefresh[i]); + } + printf("\n\n"); + + printf("abilitySlotRefresh: %u \n", pp->abilitySlotRefresh); + printf("haircolor: %u \n", pp->haircolor); + printf("beardcolor: %u \n", pp->beardcolor); + printf("eyecolor1: %u \n", pp->eyecolor1); + printf("eyecolor2: %u \n", pp->eyecolor2); + printf("hairstyle: %u \n", pp->hairstyle); + printf("beard: %u \n", pp->beard); + printf("ability_time_seconds: %u \n", pp->ability_time_seconds); + printf("ability_number: %u \n", pp->ability_number); + printf("ability_time_minutes: %u \n", pp->ability_time_minutes); + printf("ability_time_hours: %u \n", pp->ability_time_hours); + + printf("\n=== Color Material Data ===\n"); + for (i = 0; i < 10; i++){ + printf("Slot: %i Blue: %u Green: %u Red: %i Use_Tint: %u Color: %u \n", 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); + } + printf("\n\n"); + + printf("\n=== AA Data ===\n"); + for (i = 0; i < MAX_PP_AA_ARRAY; i++){ + printf("ID: %u Value %u\n", pp->aa_array[i].AA, pp->aa_array[i].value); + } + printf("\n\n"); + + printf("%i unknown2384\n", pp->unknown2384); + printf("servername: %s \n", pp->servername); + printf("title: %s \n", pp->title); + printf("suffix: %s \n", pp->suffix); + printf("guildid2: %u \n", pp->guildid2); + printf("exp: %u \n", pp->exp); + printf("unknown2492: %u \n", pp->unknown2492); + printf("points: %u \n", pp->points); + printf("mana: %u \n", pp->mana); + printf("cur_hp: %u \n", pp->cur_hp); + printf("unknown2508: %u \n", pp->unknown2508); + printf("STR: %u \n", pp->STR); + printf("STA: %u \n", pp->STA); + printf("CHA: %u \n", pp->CHA); + printf("DEX: %u \n", pp->DEX); + printf("INT: %u \n", pp->INT); + printf("AGI: %u \n", pp->AGI); + printf("WIS: %u \n", pp->WIS); + printf("face: %u \n", pp->face); + printf("unknown2541[47]: %u \n", pp->unknown2541[47]); + printf("languages[MAX_PP_LANGUAGE]: %u \n", pp->languages[MAX_PP_LANGUAGE]); + + printf("\n=== languages[MAX_PP_LANGUAGE] ===\n"); + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + printf("ID: %u Value: %u \n", i, pp->languages[i]); + } + printf("\n\n"); + + printf("unknown2616[4]: %u \n", pp->unknown2616[4]); + + printf("\n=== Spell Book ===\n"); + for (i = 0; i < MAX_PP_SPELLBOOK; i++){ + printf("Spell Book Slot: %i Spell: %u \n", i, pp->spell_book[i]); + } + printf("\n\n"); + + printf("unknown4540[128]: %u \n", pp->unknown4540[128]); + + printf("\n=== mem_spells[MAX_PP_MEMSPELL] ===\n"); + for (i = 0; i < MAX_PP_MEMSPELL; i++){ + printf("ID: %u Value: %u \n", i, pp->mem_spells[i]); + } + printf("\n\n"); + + printf("unknown4704[32]: %u \n", pp->unknown4704[32]); + printf("y: %4.2f \n", pp->y); + printf("x: %4.2f \n", pp->x); + printf("z: %4.2f \n", pp->z); + printf("heading: %4.2f \n", pp->heading); + printf("unknown4752[4]: %u \n", pp->unknown4752[4]); + printf("platinum: %u \n", pp->platinum); + printf("gold: %u \n", pp->gold); + printf("silver: %u \n", pp->silver); + printf("copper: %u \n", pp->copper); + printf("platinum_bank: %u \n", pp->platinum_bank); + printf("gold_bank: %u \n", pp->gold_bank); + printf("silver_bank: %u \n", pp->silver_bank); + printf("copper_bank: %u \n", pp->copper_bank); + printf("platinum_cursor: %u \n", pp->platinum_cursor); + printf("gold_cursor: %u \n", pp->gold_cursor); + printf("silver_cursor: %u \n", pp->silver_cursor); + printf("copper_cursor: %u \n", pp->copper_cursor); + printf("platinum_shared: %u \n", pp->platinum_shared); + printf("unknown4808[24]: %u \n", pp->unknown4808[24]); + + printf("\n=== skills[MAX_PP_SKILL] ===\n"); + for (i = 0; i < MAX_PP_SKILL; i++){ + printf("ID: %u Value: %u \n", i, pp->skills[i]); + } + printf("\n\n"); + + printf("unknown5132[184]: %u \n", pp->unknown5132[184]); + printf("pvp2: %u \n", pp->pvp2); + printf("unknown5420: %u \n", pp->unknown5420); + printf("pvptype: %u \n", pp->pvptype); + printf("unknown5428: %u \n", pp->unknown5428); + printf("ability_down: %u \n", pp->ability_down); + printf("unknown5436[8]: %u \n", pp->unknown5436[8]); + printf("autosplit: %u \n", pp->autosplit); + printf("unknown5448[8]: %u \n", pp->unknown5448[8]); + printf("zone_change_count: %u \n", pp->zone_change_count); + printf("unknown5460[16]: %u \n", pp->unknown5460[16]); + printf("drakkin_heritage: %u \n", pp->drakkin_heritage); + printf("drakkin_tattoo: %u \n", pp->drakkin_tattoo); + printf("drakkin_details: %u \n", pp->drakkin_details); + printf("expansions: %u \n", pp->expansions); + printf("toxicity: %u \n", pp->toxicity); + printf("unknown5496: %s \n", pp->unknown5496); + printf("hunger_level: %i \n", pp->hunger_level); + printf("thirst_level: %i \n", pp->thirst_level); + printf("ability_up: %u \n", pp->ability_up); + printf("unknown5524: %s \n", pp->unknown5524); + printf("zone_id: %u \n", pp->zone_id); + printf("zoneInstance: %u \n", pp->zoneInstance); + + // SpellBuff_Struct buffs[BUFF_COUNT]; + + printf("groupMembers: %s \n", pp->groupMembers); + printf("unknown6428: %s \n", pp->unknown6428); + printf("entityid: %u \n", pp->entityid); + printf("leadAAActive: %u \n", pp->leadAAActive); + printf("unknown7092: %u \n", pp->unknown7092); + printf("ldon_points_guk: %i \n", pp->ldon_points_guk); + printf("ldon_points_mir: %i \n", pp->ldon_points_mir); + printf("ldon_points_mmc: %i \n", pp->ldon_points_mmc); + printf("ldon_points_ruj: %i \n", pp->ldon_points_ruj); + printf("ldon_points_tak: %i \n", pp->ldon_points_tak); + printf("ldon_points_available: %i \n", pp->ldon_points_available); + printf("ldon_wins_guk: %i \n", pp->ldon_wins_guk); + printf("ldon_wins_mir: %i \n", pp->ldon_wins_mir); + printf("ldon_wins_mmc: %i \n", pp->ldon_wins_mmc); + printf("ldon_wins_ruj: %i \n", pp->ldon_wins_ruj); + printf("ldon_wins_tak: %i \n", pp->ldon_wins_tak); + printf("ldon_losses_guk: %i \n", pp->ldon_losses_guk); + printf("ldon_losses_mir: %i \n", pp->ldon_losses_mir); + printf("ldon_losses_mmc: %i \n", pp->ldon_losses_mmc); + printf("ldon_losses_ruj: %i \n", pp->ldon_losses_ruj); + printf("ldon_losses_tak: %i \n", pp->ldon_losses_tak); + printf("unknown7160[72]: %u \n", pp->unknown7160[72]); + printf("tribute_time_remaining: %u \n", pp->tribute_time_remaining); + printf("showhelm: %u \n", pp->showhelm); + printf("career_tribute_points: %u \n", pp->career_tribute_points); + printf("unknown7244: %u \n", pp->unknown7244); + printf("tribute_points: %u \n", pp->tribute_points); + printf("unknown7252: %u \n", pp->unknown7252); + printf("tribute_active: %u \n", pp->tribute_active); + + printf("\n=== Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE] ===\n"); + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + printf("ID: %u Tribute: %u Tier: %u \n", i, pp->tributes[i].tribute, pp->tributes[i].tier); + } + printf("\n\n"); + + // Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE]; + // /*7264*/ Disciplines_Struct disciplines; + + printf("\n=== Disciplines_Struct disciplines ===\n"); + for (i = 0; i < MAX_PP_DISCIPLINES; i++){ + printf("ID: %u Disc Value: %u \n", i, pp->disciplines.values[i]); + } + printf("\n\n"); + + printf("\n=== recastTimers[MAX_RECAST_TYPES] ===\n"); + for (i = 0; i < MAX_RECAST_TYPES; i++){ + printf("ID: %u Value: %u \n", i, pp->recastTimers[i]); + } + printf("\n\n"); + + printf("unknown7780: %s \n", pp->unknown7780); + printf("endurance: %u \n", pp->endurance); + printf("group_leadership_exp: %u \n", pp->group_leadership_exp); + printf("raid_leadership_exp: %u \n", pp->raid_leadership_exp); + printf("group_leadership_points: %u \n", pp->group_leadership_points); + printf("raid_leadership_points: %u \n", pp->raid_leadership_points); + + // LeadershipAA_Struct leader_abilities; + + printf("\n=== LeadershipAA_Struct leader_abilities ===\n"); + for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ + printf("ID: %u Rank: %u \n", i, pp->leader_abilities.ranks[i]); + } + printf("\n\n"); + + printf("unknown8088[132]: %u \n", pp->unknown8088[132]); + printf("air_remaining: %u \n", pp->air_remaining); + printf("PVPKills: %u \n", pp->PVPKills); + printf("PVPDeaths: %u \n", pp->PVPDeaths); + printf("PVPCurrentPoints: %u \n", pp->PVPCurrentPoints); + printf("PVPCareerPoints: %u \n", pp->PVPCareerPoints); + printf("PVPBestKillStreak: %u \n", pp->PVPBestKillStreak); + printf("PVPWorstDeathStreak: %u \n", pp->PVPWorstDeathStreak); + printf("PVPCurrentKillStreak: %u \n", pp->PVPCurrentKillStreak); + + // PVPStatsEntry_Struct PVPLastKill; + + printf("\n=== PVPStatsEntry_Struct PVPLastKill ===\n"); + printf("Char Name: %s Level: %u Race: %u Class: %u Zone: %u Time: %u Points: %u \n", pp->PVPLastKill.Name, pp->PVPLastKill.Level, pp->PVPLastKill.Race, pp->PVPLastKill.Class, pp->PVPLastKill.Zone, pp->PVPLastKill.Time, pp->PVPLastKill.Points); + printf("\n\n"); + + // /*8304*/ PVPStatsEntry_Struct PVPLastDeath; + + printf("\n=== PVPStatsEntry_Struct PVPLastDeath ===\n"); + printf("Char Name: %s Level: %u Race: %u Class: %u Zone: %u Time: %u Points: %u \n", pp->PVPLastDeath.Name, pp->PVPLastDeath.Level, pp->PVPLastDeath.Race, pp->PVPLastDeath.Class, pp->PVPLastDeath.Zone, pp->PVPLastDeath.Time, pp->PVPLastDeath.Points); + printf("\n\n"); + + printf("PVPNumberOfKillsInLast24Hours: %u \n", pp->PVPNumberOfKillsInLast24Hours); + + // PVPStatsEntry_Struct PVPRecentKills[50]; + + printf("\n===PVPStatsEntry_Struct PVPRecentKills[50] ===\n"); + for (i = 0; i < 50; i++){ + printf("ID: %u Char Name: %s Level: %u Race: %u Class: %u Zone: %u Time: %u Points: %u \n", i, pp->PVPRecentKills[i].Name, pp->PVPRecentKills[i].Level, pp->PVPRecentKills[i].Race, pp->PVPRecentKills[i].Class, pp->PVPRecentKills[i].Zone, pp->PVPRecentKills[i].Time, pp->PVPRecentKills[i].Points); + } + printf("\n\n"); + + printf("aapoints_spent: %u \n", pp->aapoints_spent); + printf("expAA: %u \n", pp->expAA); + printf("aapoints: %u \n", pp->aapoints); + printf("unknown12844[36]: %u \n", pp->unknown12844[36]); + + // Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT]; + + printf("\n=== Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT] ===\n"); + uint16 si = 0; + for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + // BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE]; + for (si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + printf("ID: %u item_id: %u icon: %u items name: %s name: %s\n", i, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].items[si].item_name, pp->bandoliers[i].name); + } + } + printf("\n\n"); + + printf("unknown14160[4506]: %u \n", pp->unknown14160[4506]); + + // SuspendedMinion_Struct SuspendedMinion; // No longer in use (In DB) + + // printf("\n=== SuspendedMinion_Struct SuspendedMinion ===\n"); + // printf("SpellID: %u HP: %u Mana: %u \n", i, pp->leader_abilities.ranks[i]); + + // printf("\n\n"); + + printf("timeentitledonaccount: %u \n", pp->timeentitledonaccount); + + // PotionBelt_Struct potionbelt; //there should be 3 more of these + + printf("\n=== PotionBelt_Struct potionbelt ===\n"); + for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ + printf("ID: %u Icon: %u Item ID: %u Item Name: %s\n", i, pp->potionbelt.items[i].icon, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].item_name); + } + printf("\n\n"); + + printf("unknown19568[8]: %u \n", pp->unknown19568[8]); + printf("currentRadCrystals: %u \n", pp->currentRadCrystals); + printf("careerRadCrystals: %u \n", pp->careerRadCrystals); + printf("currentEbonCrystals: %u \n", pp->currentEbonCrystals); + printf("careerEbonCrystals: %u \n", pp->careerEbonCrystals); + printf("groupAutoconsent: %u \n", pp->groupAutoconsent); + printf("raidAutoconsent: %u \n", pp->raidAutoconsent); + printf("guildAutoconsent: %u \n", pp->guildAutoconsent); + printf("unknown19595[5]: %u \n", pp->unknown19595[5]); + printf("RestTimer: %u \n", pp->RestTimer); + + + printf("\n"); + } + + mysql_free_result(result2); + } + } + mysql_free_result(result); + } + return true; +} + bool Database::LoadVariables() { char *query = nullptr; diff --git a/common/database.h b/common/database.h index f912c18d1..a22e6d406 100644 --- a/common/database.h +++ b/common/database.h @@ -217,6 +217,8 @@ public: uint32 GetRaidID(const char* name); const char *GetRaidLeaderName(uint32 rid); + bool Database::CheckDatabaseConversions(); + /* * Database Variables */ diff --git a/world/net.cpp b/world/net.cpp index 4bfdc3c1a..f308fc1be 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -276,6 +276,9 @@ int main(int argc, char** argv) { _log(WORLD__INIT, "HTTP world service disabled."); } + _log(WORLD__INIT, "Checking Database Conversions.."); + database.CheckDatabaseConversions(); + _log(WORLD__INIT, "Loading variables.."); database.LoadVariables(); _log(WORLD__INIT, "Loading zones.."); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 787e3a94e..725f6395a 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -858,9 +858,10 @@ void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) } bool ZoneDatabase::GetCharacterInfoForLogin(const char* name, uint32* character_id, -char* current_zone, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, -uint32* pplen, uint32* guilddbid, uint8* guildrank, -uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8 *firstlogon) { + char* current_zone, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, + uint32* pplen, uint32* guilddbid, uint8* guildrank, + uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8 *firstlogon) { + char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; uint32 querylen; From 4071d88290d32e66c10f60ce85178e2d20bea292 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 31 Aug 2014 02:53:59 -0500 Subject: [PATCH 02/56] At point of commit: Basic character data, currency and AA are being loaded/saved from the database, currently working on the rest right now. - Character blob removed from load for testing. Lots of cleanup yet to be done so don't judge code yet. Saves: - Two FULL saves when looting a corpse, this has been reduced to just currency saves on initial loot and trimmed to one save since AddToMoneyPP did it already - Every time a player moves coin with any situation (Splits/Trades/Merchant/Skills/Bank Coin Exchange/Coin Moves), a full save is made, this is now just a currency save - Every time a player skilled up at a skill vendor, a full blob save hit was made, this is not just a currency hit --- common/database.cpp | 389 +++++++++++++++++++++++++-- common/debug.h | 18 +- common/shareddb.cpp | 5 +- world/net.cpp | 6 +- zone/aa.cpp | 6 +- zone/client.cpp | 160 +++++------ zone/client.h | 4 + zone/client_logs.cpp | 5 +- zone/client_packet.cpp | 221 +++++++--------- zone/client_process.cpp | 2 +- zone/command.cpp | 4 +- zone/corpse.cpp | 3 +- zone/zonedb.cpp | 569 +++++++++++++++++++++++++++++++++++++++- zone/zonedb.h | 15 +- zone/zoning.cpp | 2 +- 15 files changed, 1140 insertions(+), 269 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index b90340ad9..92df542f8 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -80,7 +80,7 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf); HandleMysqlError(errnum); - return false; + return false; } else { @@ -555,7 +555,7 @@ bool Database::DeleteCharacter(char *name) return true; } -// Store new character information into the character_ and inventory tables +/* This only for new Character creation storing */ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext) { char query[256+sizeof(PlayerProfile_Struct)*2+sizeof(ExtendedProfile_Struct)*2+5]; @@ -639,7 +639,6 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven i++; } - return true; } @@ -772,8 +771,7 @@ void Database::GetCharName(uint32 char_id, char* name) { strcpy(name, row[0]); } -static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) -{ +static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { if ((x != n) && (x % (n / 100 + 1) != 0)) return; float ratio = x / (float)n; @@ -787,31 +785,46 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) bool Database::CheckDatabaseConversions() { /* Set all of this ugliness */ - char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf2[MYSQL_ERRMSG_SIZE]; - char *query = 0; char *query2 = 0; - uint32 querylen; uint32 querylen2; - MYSQL_RES *result; MYSQL_RES *result2; - MYSQL_ROW row2; MYSQL_ROW row; + char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf2[MYSQL_ERRMSG_SIZE]; char errbuf3[MYSQL_ERRMSG_SIZE]; + char *query = 0; char *query2 = 0; char *query3 = 0; + uint32 querylen; uint32 querylen2; uint32 querylen3; + MYSQL_RES *result; MYSQL_RES *result2; MYSQL_RES *result3; + MYSQL_ROW row; MYSQL_ROW row2; MYSQL_ROW row3; unsigned long* lengths; PlayerProfile_Struct* pp; uint32 pplen = 0; uint32 i; - + int character_id = 0; + int account_id = 0; int number_of_characters = 0; - int printppdebug = 1; + int printppdebug = 0; int runconvert = 0; - printf("CheckDatabase Running.... \n"); + /* Check For Legacy Storage Method */ + std::string rquery = StringFormat("SELECT `profile` FROM `character_` LIMIT 1"); + auto results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + runconvert = 1; + printf("\n\n::: Legacy Character Data Binary Blob Storage Detected... \n"); + printf("----------------------------------------------------------\n\n"); + printf(" Database currently has character data being stored via \n"); + printf(" the legacy character storage method and will proceed with converting...\n\n"); + printf(" It is recommended that you backup your database \n"); + printf(" before continuing the automatic conversion proces...\n\n"); + printf("----------------------------------------------------------\n\n"); + std::cout << "Press ENTER to continue....." << std::endl << std::endl; + std::cin.ignore(1); + } - printf("Running character binary blob to database conversion... \n", number_of_characters); - /* Get the number of characters */ - querylen = MakeAnyLenString(&query, "SELECT COUNT(`id`) FROM `character_`"); - if (RunQuery(query, querylen, errbuf, &result)) { - row = mysql_fetch_row(result); - number_of_characters = atoi(row[0]); - printf("Number of Characters in Database: %i \n", number_of_characters); - safe_delete_array(query); - mysql_free_result(result); + if (runconvert == 1){ + printf("Running character binary blob to database conversion... \n", number_of_characters); + /* Get the number of characters */ + rquery = StringFormat("SELECT COUNT(`id`) FROM `character_`"); + results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + number_of_characters = atoi(row[0]); + printf("Number of Characters in Database: %i \n", number_of_characters); + } } // querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); @@ -821,12 +834,13 @@ bool Database::CheckDatabaseConversions() { safe_delete_array(query); while (row = mysql_fetch_row(result)) { char_iter_count++; - querylen2 = MakeAnyLenString(&query2, "SELECT `id`, `profile`, `name`, `level` FROM `character_` WHERE `id` = %i", atoi(row[0])); + querylen2 = MakeAnyLenString(&query2, "SELECT `id`, `profile`, `name`, `level`, `account_id` FROM `character_` WHERE `id` = %i", atoi(row[0])); if (RunQuery(query2, querylen2, errbuf2, &result2)){ safe_delete_array(query2); row2 = mysql_fetch_row(result2); - pp = (PlayerProfile_Struct*)row2[1]; - + 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)) { @@ -842,11 +856,325 @@ bool Database::CheckDatabaseConversions() { /* Loading Status on conversion */ if (runconvert == 1){ std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; - loadbar(char_iter_count, number_of_characters, 50); + loadbar(char_iter_count, number_of_characters, 50); + + /* Run Currency Convert */ + std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," + "platinum_bank, gold_bank, silver_bank, copper_bank," + "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " + "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" + "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", + character_id, + pp->platinum, + pp->gold, + pp->silver, + pp->copper, + pp->platinum_bank, + pp->gold_bank, + pp->silver_bank, + pp->copper_bank, + pp->platinum_cursor, + pp->gold_cursor, + pp->silver_cursor, + pp->copper_cursor, + pp->currentRadCrystals, + pp->careerRadCrystals, + pp->currentEbonCrystals, + pp->careerEbonCrystals + ); + auto results = QueryDatabase(rquery); + + /* Run Character Data Convert */ + rquery = StringFormat( + "REPLACE INTO `character_data` (" + " id, " + " account_id, " + " `name`, " + " last_name, " + " gender, " + " race, " + " class, " + " `level`, " + " deity, " + " birthday, " + " last_login, " + " time_played, " + " pvp_status, " + " level2, " + " anon, " + " gm, " + " intoxication, " + " hair_color, " + " beard_color, " + " eye_color_1, " + " eye_color_2, " + " hair_style, " + " beard, " + " ability_time_seconds, " + " ability_number, " + " ability_time_minutes, " + " ability_time_hours, " + " title, " + " suffix, " + " exp, " + " points, " + " mana, " + " cur_hp, " + " str, " + " sta, " + " cha, " + " dex, " + " `int`, " + " agi, " + " wis, " + " face, " + " y, " + " x, " + " z, " + " heading, " + " pvp2, " + " pvp_type, " + " autosplit_enabled, " + " zone_change_count, " + " drakkin_heritage, " + " drakkin_tattoo, " + " drakkin_details, " + " toxicity, " + " hunger_level, " + " thirst_level, " + " ability_up, " + " zone_id, " + " zone_instance, " + " leadership_exp_on, " + " ldon_points_guk, " + " ldon_points_mir, " + " ldon_points_mmc, " + " ldon_points_ruj, " + " ldon_points_tak, " + " ldon_points_available, " + " tribute_time_remaining, " + " show_helm, " + " career_tribute_points, " + " tribute_points, " + " tribute_active, " + " endurance, " + " group_leadership_exp, " + " raid_leadership_exp, " + " group_leadership_points, " + " raid_leadership_points, " + " air_remaining, " + " pvp_kills, " + " pvp_deaths, " + " pvp_current_points, " + " pvp_career_points, " + " pvp_best_kill_streak, " + " pvp_worst_death_streak, " + " pvp_current_kill_streak, " + " aa_points_spent, " + " aa_exp, " + " aa_points, " + " group_auto_consent, " + " raid_auto_consent, " + " guild_auto_consent, " + " RestTimer) " + "VALUES (" + "%u," // id " id, " + "%u," // account_id " account_id, " + "'%s'," // `name` pp->name, " `name`, " + "'%s'," // last_name pp->last_name, " last_name, " + "%u," // gender pp->gender, " gender, " + "%u," // race pp->race, " race, " + "%u," // class pp->class_, " class, " + "%u," // `level` pp->level, " `level`, " + "%u," // deity pp->deity, " deity, " + "%u," // birthday pp->birthday, " birthday, " + "%u," // last_login pp->lastlogin, " last_login, " + "%u," // time_played pp->timePlayedMin, " time_played, " + "%u," // pvp_status pp->pvp, " pvp_status, " + "%u," // level2 pp->level2, " level2, " + "%u," // anon pp->anon, " anon, " + "%u," // gm pp->gm, " gm, " + "%u," // intoxication pp->intoxication, " intoxication, " + "%u," // hair_color pp->haircolor, " hair_color, " + "%u," // beard_color pp->beardcolor, " beard_color, " + "%u," // eye_color_1 pp->eyecolor1, " eye_color_1, " + "%u," // eye_color_2 pp->eyecolor2, " eye_color_2, " + "%u," // hair_style pp->hairstyle, " hair_style, " + "%u," // beard pp->beard, " beard, " + "%u," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " + "%u," // ability_number pp->ability_number, " ability_number, " + "%u," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " + "%u," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " + "'%s'," // title pp->title, " title, " + "'%s'," // suffix pp->suffix, " suffix, " + "%u," // exp pp->exp, " exp, " + "%u," // points pp->points, " points, " + "%u," // mana pp->mana, " mana, " + "%u," // cur_hp pp->cur_hp, " cur_hp, " + "%u," // str pp->STR, " str, " + "%u," // sta pp->STA, " sta, " + "%u," // cha pp->CHA, " cha, " + "%u," // dex pp->DEX, " dex, " + "%u," // `int` pp->INT, " `int`, " + "%u," // agi pp->AGI, " agi, " + "%u," // wis pp->WIS, " wis, " + "%u," // face pp->face, " face, " + "%f," // y pp->y, " y, " + "%f," // x pp->x, " x, " + "%f," // z pp->z, " z, " + "%f," // heading pp->heading, " heading, " + "%u," // pvp2 pp->pvp2, " pvp2, " + "%u," // pvp_type pp->pvptype, " pvp_type, " + "%u," // autosplit_enabled pp->autosplit, " autosplit_enabled, " + "%u," // zone_change_count pp->zone_change_count, " zone_change_count, " + "%u," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " + "%u," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " + "%u," // drakkin_details pp->drakkin_details, " drakkin_details, " + "%u," // toxicity pp->toxicity, " toxicity, " + "%u," // hunger_level pp->hunger_level, " hunger_level, " + "%u," // thirst_level pp->thirst_level, " thirst_level, " + "%u," // ability_up pp->ability_up, " ability_up, " + "%u," // zone_id pp->zone_id, " zone_id, " + "%u," // zone_instance pp->zoneInstance, " zone_instance, " + "%u," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " + "%u," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " + "%u," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " + "%u," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " + "%u," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " + "%u," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " + "%u," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " + "%u," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " + "%u," // show_helm pp->showhelm, " show_helm, " + "%u," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " + "%u," // tribute_points pp->tribute_points, " tribute_points, " + "%u," // tribute_active pp->tribute_active, " tribute_active, " + "%u," // endurance pp->endurance, " endurance, " + "%u," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " + "%u," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " + "%u," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " + "%u," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " + "%u," // air_remaining pp->air_remaining, " air_remaining, " + "%u," // pvp_kills pp->PVPKills, " pvp_kills, " + "%u," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " + "%u," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " + "%u," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " + "%u," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " + "%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " + "%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " + "%u," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " + "%u," // aa_exp pp->expAA, " aa_exp, " + "%u," // aa_points pp->aapoints, " aa_points, " + "%u," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " + "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " + "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " + "%u" // RestTimer pp->RestTimer, " RestTimer) " + ")", + character_id, + account_id, + pp->name, + pp->last_name, + pp->gender, + pp->race, + pp->class_, + pp->level, + pp->deity, + pp->birthday, + pp->lastlogin, + pp->timePlayedMin, + pp->pvp, + pp->level2, + pp->anon, + pp->gm, + pp->intoxication, + pp->haircolor, + pp->beardcolor, + pp->eyecolor1, + pp->eyecolor2, + pp->hairstyle, + pp->beard, + pp->ability_time_seconds, + pp->ability_number, + pp->ability_time_minutes, + pp->ability_time_hours, + pp->title, + pp->suffix, + pp->exp, + pp->points, + pp->mana, + pp->cur_hp, + pp->STR, + pp->STA, + pp->CHA, + pp->DEX, + pp->INT, + pp->AGI, + pp->WIS, + pp->face, + pp->y, + pp->x, + pp->z, + pp->heading, + pp->pvp2, + pp->pvptype, + pp->autosplit, + pp->zone_change_count, + pp->drakkin_heritage, + pp->drakkin_tattoo, + pp->drakkin_details, + pp->toxicity, + pp->hunger_level, + pp->thirst_level, + pp->ability_up, + pp->zone_id, + pp->zoneInstance, + pp->leadAAActive, + pp->ldon_points_guk, + pp->ldon_points_mir, + pp->ldon_points_mmc, + pp->ldon_points_ruj, + pp->ldon_points_tak, + pp->ldon_points_available, + pp->tribute_time_remaining, + pp->showhelm, + pp->career_tribute_points, + pp->tribute_points, + pp->tribute_active, + pp->endurance, + pp->group_leadership_exp, + pp->raid_leadership_exp, + pp->group_leadership_points, + pp->raid_leadership_points, + pp->air_remaining, + pp->PVPKills, + pp->PVPDeaths, + pp->PVPCurrentPoints, + pp->PVPCareerPoints, + pp->PVPBestKillStreak, + pp->PVPWorstDeathStreak, + pp->PVPCurrentKillStreak, + pp->aapoints_spent, + pp->expAA, + pp->aapoints, + pp->groupAutoconsent, + pp->raidAutoconsent, + pp->guildAutoconsent, + pp->RestTimer + ); + results = QueryDatabase(rquery); + /* Run AA Convert */ + for (i = 0; i < MAX_PP_AA_ARRAY; i++){ + if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ + std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", + character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + auto results = QueryDatabase(rquery); + } + } + printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); } /* Print out the entire Player Profile for testing */ - if (printppdebug == 1){ + if (printppdebug == 1) { printf("ID: %i \n", atoi(row[0])); printf("checksum: %i \n", pp->checksum); printf("name: %s \n", pp->name); @@ -947,7 +1275,7 @@ bool Database::CheckDatabaseConversions() { printf("\n=== mem_spells[MAX_PP_MEMSPELL] ===\n"); for (i = 0; i < MAX_PP_MEMSPELL; i++){ - printf("ID: %u Value: %u \n", i, pp->mem_spells[i]); + printf("ID: %u Value: %u \n", i, pp->mem_spells[i]); } printf("\n\n"); @@ -957,6 +1285,7 @@ bool Database::CheckDatabaseConversions() { printf("z: %4.2f \n", pp->z); printf("heading: %4.2f \n", pp->heading); printf("unknown4752[4]: %u \n", pp->unknown4752[4]); + printf("platinum: %u \n", pp->platinum); printf("gold: %u \n", pp->gold); printf("silver: %u \n", pp->silver); @@ -972,6 +1301,8 @@ bool Database::CheckDatabaseConversions() { printf("platinum_shared: %u \n", pp->platinum_shared); printf("unknown4808[24]: %u \n", pp->unknown4808[24]); + + printf("\n=== skills[MAX_PP_SKILL] ===\n"); for (i = 0; i < MAX_PP_SKILL; i++){ printf("ID: %u Value: %u \n", i, pp->skills[i]); @@ -1140,7 +1471,7 @@ bool Database::CheckDatabaseConversions() { printf("unknown19568[8]: %u \n", pp->unknown19568[8]); printf("currentRadCrystals: %u \n", pp->currentRadCrystals); - printf("careerRadCrystals: %u \n", pp->careerRadCrystals); + printf("careerRadCrystals: %u \n", pp->careerRadCrystals); printf("currentEbonCrystals: %u \n", pp->currentEbonCrystals); printf("careerEbonCrystals: %u \n", pp->careerEbonCrystals); printf("groupAutoconsent: %u \n", pp->groupAutoconsent); diff --git a/common/debug.h b/common/debug.h index 6184e4cbc..5e2fff368 100644 --- a/common/debug.h +++ b/common/debug.h @@ -80,14 +80,15 @@ public: ~EQEMuLog(); enum LogIDs { - Status = 0, //this must stay the first entry in this list - Normal, - Error, - Debug, - Quest, - Commands, - Crash, - MaxLogID + Status = 0, /* This must stay the first entry in this list */ + Normal, /* Normal Logs */ + Error, /* Error Logs */ + Debug, /* Debug Logs */ + Quest, /* Quest Logs */ + Commands, /* Issued Comamnds */ + Crash, /* Crash Logs */ + Save, /* Client Saves */ + MaxLogID /* Max, used in functions to get the max log ID */ }; //these are callbacks called for each @@ -113,6 +114,7 @@ private: Mutex MOpen; Mutex MLog[MaxLogID]; FILE* fp[MaxLogID]; + /* LogStatus: bitwise variable 1 = output to file 2 = output to stdout diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 8e999da54..c10e87856 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "shareddb.h" #include "mysql.h" @@ -1270,9 +1271,11 @@ bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerPr uint32 affected_rows = 0; bool ret = false; + clock_t t = std::clock(); /* Function timer start */ if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { ret = (affected_rows != 0); } + LogFile->write(EQEMuLog::Status, "SharedDatabase::SetPlayerProfile SetPlayerProfile_MQ done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); if (!ret) { LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); @@ -1292,7 +1295,7 @@ uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint if (!current_instance) current_instance = pp->zoneInstance; - if(strlen(pp->name) == 0) // Sanity check in case pp never loaded + if(strlen(pp->name) == 0) /* Sanity check in case pp never loaded */ return false; end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); diff --git a/world/net.cpp b/world/net.cpp index f308fc1be..2d186c1af 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -222,9 +222,8 @@ int main(int argc, char** argv) { else if (strcasecmp(argv[1], "flag") == 0) { if (argc == 4) { if (Seperator::IsNumber(argv[3])) { - if (atoi(argv[3]) >= 0 && atoi(argv[3]) <= 255) { - if (database.SetAccountStatus(argv[2], atoi(argv[3]))) { + if (database.SetAccountStatus(argv[2], atoi(argv[3]))){ std::cout << "Account flagged: Username='" << argv[2] << "', status=" << argv[3] << std::endl; return 0; } @@ -277,8 +276,7 @@ int main(int argc, char** argv) { } _log(WORLD__INIT, "Checking Database Conversions.."); - database.CheckDatabaseConversions(); - + database.CheckDatabaseConversions(); _log(WORLD__INIT, "Loading variables.."); database.LoadVariables(); _log(WORLD__INIT, "Loading zones.."); diff --git a/zone/aa.cpp b/zone/aa.cpp index 2964dc6f3..390174cf5 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1048,8 +1048,12 @@ void Client::BuyAA(AA_Action* action) mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level + 1); m_pp.aapoints -= real_cost; + + /* Do Player Profile rank calculations and set player profile */ + SaveAA(); + /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ + // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); - Save(); if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) && ((aa2->max_level == (cur_level + 1)) && aa2->sof_next_id)){ SendAA(aa2->id); diff --git a/zone/client.cpp b/zone/client.cpp index 37740b472..0065d31c5 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -479,60 +479,27 @@ void Client::ReportConnectingState() { }; } -bool Client::Save(uint8 iCommitNow) { -#if 0 -// Orig. Offset: 344 / 0x00000000 -// Length: 36 / 0x00000024 - unsigned char rawData[36] = +inline double clock_diff_to_sec(long clock_diff) { - 0x0D, 0x30, 0xE1, 0x30, 0x1E, 0x10, 0x22, 0x10, 0x20, 0x10, 0x21, 0x10, 0x1C, 0x20, 0x1F, 0x10, - 0x7C, 0x10, 0x68, 0x10, 0x51, 0x10, 0x78, 0x10, 0xBD, 0x10, 0xD2, 0x10, 0xCD, 0x10, 0xD1, 0x10, - 0x01, 0x10, 0x6D, 0x10 -} ; - for (int tmp = 0;tmp <=35;tmp++){ - m_pp.unknown0256[89+tmp] = rawData[tmp]; - } -#endif + return double(clock_diff) / CLOCKS_PER_SEC; +} - if(!ClientDataLoaded()) - return false; - - m_pp.x = x_pos; - m_pp.y = y_pos; - m_pp.z = z_pos; - m_pp.guildrank=guildrank; - m_pp.heading = heading; - - // Temp Hack for signed values until we get the root of the problem changed over to signed... - if (m_pp.copper < 0) { m_pp.copper = 0; } - if (m_pp.silver < 0) { m_pp.silver = 0; } - if (m_pp.gold < 0) { m_pp.gold = 0; } - if (m_pp.platinum < 0) { m_pp.platinum = 0; } - if (m_pp.copper_bank < 0) { m_pp.copper_bank = 0; } - if (m_pp.silver_bank < 0) { m_pp.silver_bank = 0; } - if (m_pp.gold_bank < 0) { m_pp.gold_bank = 0; } - if (m_pp.platinum_bank < 0) { m_pp.platinum_bank = 0; } - - - int spentpoints=0; - for(int a=0;a < MAX_PP_AA_ARRAY;a++) { +bool Client::SaveAA(){ + clock_t t = std::clock(); /* Function timer start */ + /* Save Player AA */ + int spentpoints = 0; + for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { uint32 points = aa[a]->value; - if(points > HIGHEST_AA_VALUE) // Unifying this - { + if (points > HIGHEST_AA_VALUE) { aa[a]->value = HIGHEST_AA_VALUE; points = HIGHEST_AA_VALUE; } - if (points > 0) - { - SendAA_Struct* curAA = zone->FindAA(aa[a]->AA-aa[a]->value+1); - if(curAA) - { - for (int rank=0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA-aa[a]->value + 1 + rank); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { + if (points > 0) { + SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1); + if (curAA) { + for (int rank = 0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank); + if (RequiredLevel != AARequiredLevelAndCost.end()) { spentpoints += RequiredLevel->second.Cost; } else @@ -541,36 +508,58 @@ bool Client::Save(uint8 iCommitNow) { } } } - - m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; - - if (GetHP() <= 0) { - m_pp.cur_hp = GetMaxHP(); + m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; + for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { + if (aa[a]->AA > 0 && aa[a]->value){ + std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", + character_id, a, aa[a]->AA, aa[a]->value); + auto results = database.QueryDatabase(rquery); + } } - else - m_pp.cur_hp = GetHP(); + LogFile->write(EQEMuLog::Status, "Issuing Client AA Save... CID: %i Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + return true; +} + +bool Client::Save(uint8 iCommitNow) { + if(!ClientDataLoaded()) + return false; + + clock_t t = std::clock(); /* Function timer start */ + + /* Wrote current basics to PP for saves */ + m_pp.x = x_pos; + m_pp.y = y_pos; + m_pp.z = z_pos; + m_pp.guildrank = guildrank; + m_pp.heading = heading; + + /* Mana and HP */ + if (GetHP() <= 0) { m_pp.cur_hp = GetMaxHP(); } + else { m_pp.cur_hp = GetHP(); } m_pp.mana = cur_mana; m_pp.endurance = cur_end; + /* Save Character Currency */ + database.SaveCharacterCurrency(this->CharacterID(), &m_pp); + + /* Save Character AA */ + SaveAA(); + + /* Save Character Buffs */ database.SaveBuffs(this); + /* Total Time Played */ TotalSecondsPlayed += (time(nullptr) - m_pp.lastlogin); m_pp.timePlayedMin = (TotalSecondsPlayed / 60); m_pp.RestTimer = rest_timer.GetRemainingTime() / 1000; - if(GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)) - GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); - - if(GetMercTimer()->Enabled()) { - GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); - } - - if (GetMerc() && !dead) { - - } else { - memset(&m_mercinfo, 0, sizeof(struct MercInfo)); - } + /* Save Mercs */ + if (GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)){ GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); } + if(GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); } + if (GetMerc() && !dead) { } + else { memset(&m_mercinfo, 0, sizeof(struct MercInfo)); } m_pp.lastlogin = time(nullptr); if (pQueuedSaveWorkID) { @@ -591,19 +580,17 @@ bool Client::Save(uint8 iCommitNow) { } database.SavePetInfo(this); - if(tribute_timer.Enabled()) { - m_pp.tribute_time_remaining = tribute_timer.GetRemainingTime(); - } else { - m_pp.tribute_time_remaining = 0xFFFFFFFF; - m_pp.tribute_active = 0; - } + if(tribute_timer.Enabled()) { m_pp.tribute_time_remaining = tribute_timer.GetRemainingTime(); } + else { m_pp.tribute_time_remaining = 0xFFFFFFFF; m_pp.tribute_active = 0; } p_timers.Store(&database); -// printf("Dumping inventory on save:\n"); -// m_inv.dumpEntireInventory(); - + /* Save Character Task */ SaveTaskState(); + + /* Save Character Data */ + database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); + if (iCommitNow <= 1) { char* query = 0; uint32_breakdown workpt; @@ -632,7 +619,7 @@ bool Client::Save(uint8 iCommitNow) { /* Mirror Character Data */ database.StoreCharacterLookup(this->CharacterID()); - + LogFile->write(EQEMuLog::Status, "Client::Save %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } @@ -2115,7 +2102,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) { m_pp.copper = copperpp; if(updateclient) SendMoneyUpdate(); - Save(); + SaveCurrency(); return true; } silver -= copper; @@ -2130,7 +2117,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) { m_pp.copper += (silver-(m_pp.silver*10)); if(updateclient) SendMoneyUpdate(); - Save(); + SaveCurrency(); return true; } @@ -2150,7 +2137,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) { m_pp.copper += coppertest; if(updateclient) SendMoneyUpdate(); - Save(); + SaveCurrency(); return true; } @@ -2168,7 +2155,7 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) { if(updateclient) SendMoneyUpdate(); RecalcWeight(); - Save(); + SaveCurrency(); return true; } } @@ -2234,7 +2221,7 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){ RecalcWeight(); - Save(); + SaveCurrency(); LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); } @@ -2270,7 +2257,7 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat SendMoneyUpdate(); RecalcWeight(); - Save(); + SaveCurrency(); #if (EQDEBUG>=5) LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", @@ -2807,11 +2794,6 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { m_pp.item_material[MaterialArms] = item->Material; else if (in_slot==MainWrist1) m_pp.item_material[MaterialWrist] = item->Material; - /* - // non-live behavior - else if (in_slot==SLOT_BRACER02) - m_pp.item_material[MaterialWrist] = item->Material; - */ else if (in_slot==MainHands) m_pp.item_material[MaterialHands] = item->Material; else if (in_slot==MainLegs) @@ -5734,7 +5716,7 @@ void Client::AddCrystals(uint32 Radiant, uint32 Ebon) m_pp.currentEbonCrystals += Ebon; m_pp.careerEbonCrystals += Ebon; - Save(); + SaveCurrency(); SendCrystalCounts(); } diff --git a/zone/client.h b/zone/client.h index d3aed5540..a490d73c4 100644 --- a/zone/client.h +++ b/zone/client.h @@ -313,6 +313,10 @@ public: bool Save(uint8 iCommitNow); // 0 = delayed, 1=async now, 2=sync now void SaveBackup(); + /* New PP Save Functions */ + bool SaveCurrency(){ return database.SaveCharacterCurrency(this->CharacterID(), &m_pp); } + bool SaveAA(); + inline bool ClientDataLoaded() const { return client_data_loaded; } inline bool Connected() const { return (client_state == CLIENT_CONNECTED); } inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); } diff --git a/zone/client_logs.cpp b/zone/client_logs.cpp index e51a51996..7ce3d5aab 100644 --- a/zone/client_logs.cpp +++ b/zone/client_logs.cpp @@ -33,14 +33,12 @@ void ClientLogs::subscribe(EQEMuLog::LogIDs id, Client *c) { if(c == nullptr) return; - //make sure they arnt allready subscribed. - std::vector::iterator cur,end; cur = entries[id].begin(); end = entries[id].end(); for(; cur != end; ++cur) { if(*cur == c) { - printf("%s was allready subscribed to %d\n", c->GetName(), id); + printf("%s was already subscribed to %d\n", c->GetName(), id); return; } } @@ -100,6 +98,7 @@ void ClientLogs::msg(EQEMuLog::LogIDs id, const char *buf) { for(; cur != end; ++cur) { if(!(*cur)->InZone()) continue; + (*cur)->Message(CLIENT_LOG_CHANNEL, buf); } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 91d99490f..abf044caa 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8698,6 +8698,8 @@ void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { break; } case DBA_b1_Entity_Client_Save: { + clock_t t = std::clock(); /* Function timer start */ + char errbuf[MYSQL_ERRMSG_SIZE]; uint32 affected_rows = 0; DBAsyncQuery* dbaq = dbaw->PopAnswer(); @@ -8713,6 +8715,8 @@ void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { Message(13, "errbuf: %s", errbuf); } pQueuedSaveWorkID = 0; + + LogFile->write(EQEMuLog::Status, "Client::DBAWComplete Save Character Async done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); break; } default: { @@ -8761,12 +8765,17 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { } } - // This should be a part of the PlayerProfile BLOB, but we don't want to modify that - // The player inspect message is retrieved from the db on load, then saved as new updates come in..no mods to Client::Save() - database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); + /* Load Character Currency into PP */ + database.LoadCharacterCurrency(CharacterID(), &m_pp); + /* Load Character Data from DB into PP */ + database.LoadCharacterData(CharacterID(), &m_pp); + /* Move to another method when can, this is pointless... */ + database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); + /* Load Character Currency*/ + database.LoadCharacterCurrency(CharacterID(), &m_pp); conn_state = PlayerProfileLoaded; - + /* Set Current zone */ m_pp.zone_id = zone->GetZoneID(); m_pp.zoneInstance = zone->GetInstanceID(); @@ -8820,7 +8829,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { base_race = m_pp.race; gender = m_pp.gender; base_gender = m_pp.gender; - deity = m_pp.deity;//FYI: DEITY_AGNOSTIC = 396; still valid? + deity = m_pp.deity; //FYI: DEITY_AGNOSTIC = 396; still valid? haircolor = m_pp.haircolor; beardcolor = m_pp.beardcolor; eyecolor1 = m_pp.eyecolor1; @@ -8833,8 +8842,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { drakkin_details = m_pp.drakkin_details; //if we zone in with invalid Z, fix it. - if (zone->zonemap != nullptr) { - + if (zone->zonemap != nullptr) { Map::Vertex me; me.x = GetX(); me.y = GetY(); @@ -8871,19 +8879,13 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { if (m_pp.gm && admin < minStatusToBeGM) m_pp.gm = 0; - if (m_pp.platinum < 0 || m_pp.gold < 0 || m_pp.silver < 0 || m_pp.copper < 0 ) - { - m_pp.platinum = 0; - m_pp.gold = 0; - m_pp.silver = 0; - m_pp.copper = 0; - } + + /* Load Guild */ if (!IsInAGuild()) { m_pp.guild_id = GUILD_NONE; } - else - { + else { m_pp.guild_id = GuildID(); if(zone->GetZoneID() == RuleI(World, GuildBankZoneID)) @@ -8895,120 +8897,89 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { switch (race) { case OGRE: - size = 9; - break; + size = 9; break; case TROLL: - size = 8; - break; - case VAHSHIR: - case BARBARIAN: - size = 7; - break; - case HUMAN: - case HIGH_ELF: - case ERUDITE: - case IKSAR: - case DRAKKIN: - size = 6; - break; + size = 8; break; + case VAHSHIR: case BARBARIAN: + size = 7; break; + case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN: + size = 6; break; case HALF_ELF: - size = 5.5; - break; - case WOOD_ELF: - case DARK_ELF: - case FROGLOK: - size = 5; - break; + size = 5.5; break; + case WOOD_ELF: case DARK_ELF: case FROGLOK: + size = 5; break; case DWARF: - size = 4; - break; + size = 4; break; case HALFLING: - size = 3.5; - break; + size = 3.5; break; case GNOME: - size = 3; - break; + size = 3; break; default: size = 0; } - //validate skills - //im not sure I follow this logic... commenting for now... - /* - if(Admin() < minStatusToHaveInvalidSkills) { - SkillType sk; - for (sk = _1H_BLUNT; sk <= HIGHEST_SKILL; sk = (SkillType)(sk+1)) { - //int cap = GetSkillCap(sk-1); - int cap = MaxSkill(sk-1, GetClass(), GetLevel()); - if (cap >= 254) - m_pp.skills[sk] = cap; - } - } - */ - - //validate adventure points, this cap is arbitrary at 2,000,000,000 - if(m_pp.ldon_points_guk < 0) - m_pp.ldon_points_guk = 0; - if(m_pp.ldon_points_guk > 0x77359400) - m_pp.ldon_points_guk = 0x77359400; - if(m_pp.ldon_points_mir < 0) - m_pp.ldon_points_mir = 0; - if(m_pp.ldon_points_mir > 0x77359400) - m_pp.ldon_points_mir = 0x77359400; - if(m_pp.ldon_points_mmc < 0) - m_pp.ldon_points_mmc = 0; - if(m_pp.ldon_points_mmc > 0x77359400) - m_pp.ldon_points_mmc = 0x77359400; - if(m_pp.ldon_points_ruj < 0) - m_pp.ldon_points_ruj = 0; - if(m_pp.ldon_points_ruj > 0x77359400) - m_pp.ldon_points_ruj = 0x77359400; - if(m_pp.ldon_points_tak < 0) - m_pp.ldon_points_tak = 0; - if(m_pp.ldon_points_tak > 0x77359400) - m_pp.ldon_points_tak = 0x77359400; - if(m_pp.ldon_points_available < 0) - m_pp.ldon_points_available = 0; - if(m_pp.ldon_points_available > 0x77359400) - m_pp.ldon_points_available = 0x77359400; - + /* Check for Invalid points */ + if (m_pp.ldon_points_guk < 0 || m_pp.ldon_points_guk > 2000000000){ m_pp.ldon_points_guk = 0; } + if (m_pp.ldon_points_mir < 0 || m_pp.ldon_points_mir > 2000000000){ m_pp.ldon_points_mir = 0; } + if (m_pp.ldon_points_mmc < 0 || m_pp.ldon_points_mmc > 2000000000){ m_pp.ldon_points_mmc = 0; } + if (m_pp.ldon_points_ruj < 0 || m_pp.ldon_points_ruj > 2000000000){ m_pp.ldon_points_ruj = 0; } + if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } + if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } + if(GetSkill(SkillSwimming) < 100) - SetSkill(SkillSwimming,100); + SetSkill(SkillSwimming, 100); - //pull AAs from the PP - for(uint32 a=0; a < MAX_PP_AA_ARRAY; a++){ - //set up our AA pointer + + + /* Load Character AA's */ + //database.LoadCharacterAA(this->CharacterID(), &m_pp, &aa, &aa_points); + + /* Initialize AA's */ + for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ aa[a] = &m_pp.aa_array[a]; - - + } + std::string query = StringFormat( + "SELECT " + "slot, " + "aa_id, " + "aa_value " + "FROM " + "`character_alternate_abilities` " + "WHERE `id` = %i ORDER BY `slot`", this->CharacterID()); + auto results = database.QueryDatabase(query); int si = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + si = atoi(row[0]); + m_pp.aa_array[si].AA = atoi(row[1]); + m_pp.aa_array[si].value = atoi(row[1]); + aa[si]->AA = atoi(row[1]); + aa[si]->value = atoi(row[2]); + } + for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ uint32 id = aa[a]->AA; //watch for invalid AA IDs - if(id == aaNone) + if (id == aaNone) continue; - if(id >= aaHighestID) { + if (id >= aaHighestID) { + aa[a]->AA = aaNone; + aa[a]->value = 0; + continue; + } + if (aa[a]->value == 0) { + aa[a]->AA = aaNone; + continue; + } + if (aa[a]->value > HIGHEST_AA_VALUE) { aa[a]->AA = aaNone; aa[a]->value = 0; continue; } - //watch for invalid AA values - if(aa[a]->value == 0) { - aa[a]->AA = aaNone; - continue; - } - if(aa[a]->value > HIGHEST_AA_VALUE) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - - if(aa[a]->value > 1) //hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) - aa_points[(id - aa[a]->value +1)] = aa[a]->value; + if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ + aa_points[(id - aa[a]->value + 1)] = aa[a]->value; else aa_points[id] = aa[a]->value; } - if(SPDAT_RECORDS > 0) { for(uint32 z=0;z 0){ @@ -9128,6 +9101,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { m_pp.z = zone->newzone_data.safe_z; } + /* Get Expansions from variables table and ship via PP */ char val[20] = {0}; if (database.GetVariable("Expansions", val, 20)) m_pp.expansions = atoi(val); @@ -9143,14 +9117,11 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { if(IsValidSpell(m_pp.mem_spells[i])) m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000; - if(m_pp.class_==SHADOWKNIGHT || m_pp.class_==PALADIN) - { + /* Ability slot refresh send SK/PAL */ + if(m_pp.class_==SHADOWKNIGHT || m_pp.class_==PALADIN) { uint32 abilitynum=0; - if(m_pp.class_==SHADOWKNIGHT) - abilitynum = pTimerHarmTouch; - else - abilitynum = pTimerLayHands; - + if (m_pp.class_ == SHADOWKNIGHT){ abilitynum = pTimerHarmTouch; } + else{ abilitynum = pTimerLayHands; } uint32 remaining = p_timers.GetRemainingTime(abilitynum); if(remaining > 0 && remaining < 15300) @@ -9174,16 +9145,16 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; - // Reset rest timer if the durations have been lowered in the database + /* Reset rest timer if the durations have been lowered in the database */ if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) m_pp.RestTimer = 0; - //This checksum should disappear once dynamic structs are in... each struct strategy will do it + /* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct)-4); outapp = new EQApplicationPacket(OP_PlayerProfile,sizeof(PlayerProfile_Struct)); - // The entityid field in the Player Profile is used by the Client in relation to Group Leadership AA + /* The entityid field in the Player Profile is used by the Client in relation to Group Leadership AA */ m_pp.entityid = GetID(); memcpy(outapp->pBuffer,&m_pp,outapp->size); outapp->priority = 6; @@ -9193,9 +9164,11 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { rest_timer.Start(m_pp.RestTimer * 1000); database.LoadPetInfo(this); - //this was moved before the spawn packets are sent - //in hopes that it adds more consistency... - //Remake pet + /* + This was moved before the spawn packets are sent + in hopes that it adds more consistency... + Remake pet + */ if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); @@ -9208,7 +9181,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { } m_petinfo.SpellID = 0; } - // Moved here so it's after where we load the pet data. + /* Moved here so it's after where we load the pet data. */ if(!GetAA(aaPersistentMinion)) memset(&m_suspendedminion, 0, sizeof(PetInfo)); @@ -12894,13 +12867,13 @@ void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app) { SummonItem(RuleI(Zone, EbonCrystalItemID), GetEbonCrystals()); m_pp.currentEbonCrystals = 0; m_pp.careerEbonCrystals = 0; - Save(); + SaveCurrency(); SendCrystalCounts(); } else { SummonItem(RuleI(Zone, EbonCrystalItemID), cr->amount); m_pp.currentEbonCrystals -= cr->amount; m_pp.careerEbonCrystals -= cr->amount; - Save(); + SaveCurrency(); SendCrystalCounts(); } } else if(cr->type == 4) { @@ -12908,13 +12881,13 @@ void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app) { SummonItem(RuleI(Zone, RadiantCrystalItemID), GetRadiantCrystals()); m_pp.currentRadCrystals = 0; m_pp.careerRadCrystals = 0; - Save(); + SaveCurrency(); SendCrystalCounts(); } else { SummonItem(RuleI(Zone, RadiantCrystalItemID), cr->amount); m_pp.currentRadCrystals -= cr->amount; m_pp.careerRadCrystals -= cr->amount; - Save(); + SaveCurrency(); SendCrystalCounts(); } } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index e39cef0bd..fd8cb3740 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1582,7 +1582,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) safe_delete(outapp); } - Save(); + SaveCurrency(); } void Client::OPGMTraining(const EQApplicationPacket *app) diff --git a/zone/command.cpp b/zone/command.cpp index b14a173bc..011cb0f09 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6273,13 +6273,13 @@ void command_setcrystals(Client *c, const Seperator *sep) { t->SetRadiantCrystals(atoi(sep->arg[2])); t->SendCrystalCounts(); - t->Save(); + t->SaveCurrency(); } else if(!strcasecmp(sep->arg[1], "ebon")) { t->SetEbonCrystals(atoi(sep->arg[2])); t->SendCrystalCounts(); - t->Save(); + t->SaveCurrency(); } else { diff --git a/zone/corpse.cpp b/zone/corpse.cpp index aa7841a64..083dc0b12 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -971,8 +971,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } RemoveCash(); - Save(); - client->Save(); + Save(); } outapp->priority = 6; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 725f6395a..e7bad016c 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -5,6 +5,7 @@ #include "../common/extprofile.h" #include "../common/guilds.h" #include "../common/rulesys.h" +#include "../common/rdtsc.h" #include "zone.h" #include "client.h" #include "merc.h" @@ -13,6 +14,7 @@ #include #include #include +#include extern Zone* zone; @@ -893,12 +895,575 @@ bool ZoneDatabase::GetCharacterInfoForLogin(const char* name, uint32* character_ #define StructDist(in, f1, f2) (uint32(&in->f2)-uint32(&in->f1)) + +bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "`name`, " + "last_name, " + "gender, " + "race, " + "class, " + "`level`, " + "deity, " + "birthday, " + "last_login, " + "time_played, " + "pvp_status, " + "level2, " + "anon, " + "gm, " + "intoxication, " + "hair_color, " + "beard_color, " + "eye_color_1, " + "eye_color_2, " + "hair_style, " + "beard, " + "ability_time_seconds, " + "ability_number, " + "ability_time_minutes, " + "ability_time_hours, " + "title, " + "suffix, " + "exp, " + "points, " + "mana, " + "cur_hp, " + "str, " + "sta, " + "cha, " + "dex, " + "`int`, " + "agi, " + "wis, " + "face, " + "y, " + "x, " + "z, " + "heading, " + "pvp2, " + "pvp_type, " + "autosplit_enabled, " + "zone_change_count, " + "drakkin_heritage, " + "drakkin_tattoo, " + "drakkin_details, " + "toxicity, " + "hunger_level, " + "thirst_level, " + "ability_up, " + "zone_id, " + "zone_instance, " + "leadership_exp_on, " + "ldon_points_guk, " + "ldon_points_mir, " + "ldon_points_mmc, " + "ldon_points_ruj, " + "ldon_points_tak, " + "ldon_points_available, " + "tribute_time_remaining, " + "show_helm, " + "career_tribute_points, " + "tribute_points, " + "tribute_active, " + "endurance, " + "group_leadership_exp, " + "raid_leadership_exp, " + "group_leadership_points, " + "raid_leadership_points, " + "air_remaining, " + "pvp_kills, " + "pvp_deaths, " + "pvp_current_points, " + "pvp_career_points, " + "pvp_best_kill_streak, " + "pvp_worst_death_streak, " + "pvp_current_kill_streak, " + "aa_points_spent, " + "aa_exp, " + "aa_points, " + "group_auto_consent, " + "raid_auto_consent, " + "guild_auto_consent, " + "RestTimer " + "FROM " + "character_data " + "WHERE `id` = %i ", character_id); + auto results = database.QueryDatabase(query); int r = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + strcpy(pp->name, row[r]); r++; + strcpy(pp->last_name, row[r]); r++; + pp->gender = atoi(row[r]); r++; + pp->race = atoi(row[r]); r++; + pp->class_ = atoi(row[r]); r++; + pp->level = atoi(row[r]); r++; + pp->deity = atoi(row[r]); r++; + pp->birthday = atoi(row[r]); r++; + pp->lastlogin = atoi(row[r]); r++; + pp->timePlayedMin = atoi(row[r]); r++; + pp->pvp = atoi(row[r]); r++; + pp->level2 = atoi(row[r]); r++; + pp->anon = atoi(row[r]); r++; + pp->gm = atoi(row[r]); r++; + pp->intoxication = atoi(row[r]); r++; + pp->haircolor = atoi(row[r]); r++; + pp->beardcolor = atoi(row[r]); r++; + pp->eyecolor1 = atoi(row[r]); r++; + pp->eyecolor2 = atoi(row[r]); r++; + pp->hairstyle = atoi(row[r]); r++; + pp->beard = atoi(row[r]); r++; + pp->ability_time_seconds = atoi(row[r]); r++; + pp->ability_number = atoi(row[r]); r++; + pp->ability_time_minutes = atoi(row[r]); r++; + pp->ability_time_hours = atoi(row[r]); r++; + strcpy(pp->title, row[r]); r++; + strcpy(pp->suffix, row[r]); r++; + pp->exp = atoi(row[r]); r++; + pp->points = atoi(row[r]); r++; + pp->mana = atoi(row[r]); r++; + pp->cur_hp = atoi(row[r]); r++; + pp->STR = atoi(row[r]); r++; + pp->STA = atoi(row[r]); r++; + pp->CHA = atoi(row[r]); r++; + pp->DEX = atoi(row[r]); r++; + pp->INT = atoi(row[r]); r++; + pp->AGI = atoi(row[r]); r++; + pp->WIS = atoi(row[r]); r++; + pp->face = atoi(row[r]); r++; + pp->y = atof(row[r]); r++; + pp->x = atof(row[r]); r++; + pp->z = atof(row[r]); r++; + pp->heading = atof(row[r]); r++; + pp->pvp2 = atoi(row[r]); r++; + pp->pvptype = atoi(row[r]); r++; + pp->autosplit = atoi(row[r]); r++; + pp->zone_change_count = atoi(row[r]); r++; + pp->drakkin_heritage = atoi(row[r]); r++; + pp->drakkin_tattoo = atoi(row[r]); r++; + pp->drakkin_details = atoi(row[r]); r++; + pp->toxicity = atoi(row[r]); r++; + pp->hunger_level = atoi(row[r]); r++; + pp->thirst_level = atoi(row[r]); r++; + pp->ability_up = atoi(row[r]); r++; + pp->zone_id = atoi(row[r]); r++; + pp->zoneInstance = atoi(row[r]); r++; + pp->leadAAActive = atoi(row[r]); r++; + pp->ldon_points_guk = atoi(row[r]); r++; + pp->ldon_points_mir = atoi(row[r]); r++; + pp->ldon_points_mmc = atoi(row[r]); r++; + pp->ldon_points_ruj = atoi(row[r]); r++; + pp->ldon_points_tak = atoi(row[r]); r++; + pp->ldon_points_available = atoi(row[r]); r++; + pp->tribute_time_remaining = atoi(row[r]); r++; + pp->showhelm = atoi(row[r]); r++; + pp->career_tribute_points = atoi(row[r]); r++; + pp->tribute_points = atoi(row[r]); r++; + pp->tribute_active = atoi(row[r]); r++; + pp->endurance = atoi(row[r]); r++; + pp->group_leadership_exp = atoi(row[r]); r++; + pp->raid_leadership_exp = atoi(row[r]); r++; + pp->group_leadership_points = atoi(row[r]); r++; + pp->raid_leadership_points = atoi(row[r]); r++; + pp->air_remaining = atoi(row[r]); r++; + pp->PVPKills = atoi(row[r]); r++; + pp->PVPDeaths = atoi(row[r]); r++; + pp->PVPCurrentPoints = atoi(row[r]); r++; + pp->PVPCareerPoints = atoi(row[r]); r++; + pp->PVPBestKillStreak = atoi(row[r]); r++; + pp->PVPWorstDeathStreak = atoi(row[r]); r++; + pp->PVPCurrentKillStreak = atoi(row[r]); r++; + pp->aapoints_spent = atoi(row[r]); r++; + pp->expAA = atoi(row[r]); r++; + pp->aapoints = atoi(row[r]); r++; + pp->groupAutoconsent = atoi(row[r]); r++; + pp->raidAutoconsent = atoi(row[r]); r++; + pp->guildAutoconsent = atoi(row[r]); r++; + pp->RestTimer = atoi(row[r]); r++; + LogFile->write(EQEMuLog::Status, "Loading Character Data for character ID: %i, done", character_id); + } + return true; +} + +bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "platinum, " + "gold, " + "silver, " + "copper, " + "platinum_bank, " + "gold_bank, " + "silver_bank, " + "copper_bank, " + "platinum_cursor, " + "gold_cursor, " + "silver_cursor, " + "copper_cursor, " + "radiant_crystals, " + "career_radiant_crystals," + "ebon_crystals, " + "career_ebon_crystals " + "FROM " + "character_currency " + "WHERE `id` = %i ", character_id); + auto results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + pp->platinum = atoi(row[0]); + pp->gold = atoi(row[1]); + pp->silver = atoi(row[2]); + pp->copper = atoi(row[3]); + pp->platinum_bank = atoi(row[4]); + pp->gold_bank = atoi(row[5]); + pp->silver_bank = atoi(row[6]); + pp->copper_bank = atoi(row[7]); + pp->platinum_cursor = atoi(row[8]); + pp->gold_cursor = atoi(row[9]); + pp->silver_cursor = atoi(row[10]); + pp->copper_cursor = atoi(row[11]); + pp->currentRadCrystals = atoi(row[12]); + pp->careerRadCrystals = atoi(row[13]); + pp->currentEbonCrystals = atoi(row[14]); + pp->careerEbonCrystals = atoi(row[15]); + LogFile->write(EQEMuLog::Status, "Loading Currency for character ID: %i, done", character_id); + } + return true; +} + +bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){ + clock_t t = std::clock(); /* Function timer start */ + std::string query = StringFormat( + "REPLACE INTO `character_data` (" + " id, " + " account_id, " + " `name`, " + " last_name, " + " gender, " + " race, " + " class, " + " `level`, " + " deity, " + " birthday, " + " last_login, " + " time_played, " + " pvp_status, " + " level2, " + " anon, " + " gm, " + " intoxication, " + " hair_color, " + " beard_color, " + " eye_color_1, " + " eye_color_2, " + " hair_style, " + " beard, " + " ability_time_seconds, " + " ability_number, " + " ability_time_minutes, " + " ability_time_hours, " + " title, " + " suffix, " + " exp, " + " points, " + " mana, " + " cur_hp, " + " str, " + " sta, " + " cha, " + " dex, " + " `int`, " + " agi, " + " wis, " + " face, " + " y, " + " x, " + " z, " + " heading, " + " pvp2, " + " pvp_type, " + " autosplit_enabled, " + " zone_change_count, " + " drakkin_heritage, " + " drakkin_tattoo, " + " drakkin_details, " + " toxicity, " + " hunger_level, " + " thirst_level, " + " ability_up, " + " zone_id, " + " zone_instance, " + " leadership_exp_on, " + " ldon_points_guk, " + " ldon_points_mir, " + " ldon_points_mmc, " + " ldon_points_ruj, " + " ldon_points_tak, " + " ldon_points_available, " + " tribute_time_remaining, " + " show_helm, " + " career_tribute_points, " + " tribute_points, " + " tribute_active, " + " endurance, " + " group_leadership_exp, " + " raid_leadership_exp, " + " group_leadership_points, " + " raid_leadership_points, " + " air_remaining, " + " pvp_kills, " + " pvp_deaths, " + " pvp_current_points, " + " pvp_career_points, " + " pvp_best_kill_streak, " + " pvp_worst_death_streak, " + " pvp_current_kill_streak, " + " aa_points_spent, " + " aa_exp, " + " aa_points, " + " group_auto_consent, " + " raid_auto_consent, " + " guild_auto_consent, " + " RestTimer) " + "VALUES (" + "%i," // id " id, " + "%i," // account_id " account_id, " + "'%s'," // `name` pp->name, " `name`, " + "'%s'," // last_name pp->last_name, " last_name, " + "%i," // gender pp->gender, " gender, " + "%i," // race pp->race, " race, " + "%i," // class pp->class_, " class, " + "%i," // `level` pp->level, " `level`, " + "%i," // deity pp->deity, " deity, " + "%i," // birthday pp->birthday, " birthday, " + "%i," // last_login pp->lastlogin, " last_login, " + "%i," // time_played pp->timePlayedMin, " time_played, " + "%i," // pvp_status pp->pvp, " pvp_status, " + "%i," // level2 pp->level2, " level2, " + "%i," // anon pp->anon, " anon, " + "%i," // gm pp->gm, " gm, " + "%i," // intoxication pp->intoxication, " intoxication, " + "%i," // hair_color pp->haircolor, " hair_color, " + "%i," // beard_color pp->beardcolor, " beard_color, " + "%i," // eye_color_1 pp->eyecolor1, " eye_color_1, " + "%i," // eye_color_2 pp->eyecolor2, " eye_color_2, " + "%i," // hair_style pp->hairstyle, " hair_style, " + "%i," // beard pp->beard, " beard, " + "%i," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " + "%i," // ability_number pp->ability_number, " ability_number, " + "%i," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " + "%i," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " + "'%s'," // title pp->title, " title, " " + "'%s'," // suffix pp->suffix, " suffix, " + "%i," // exp pp->exp, " exp, " + "%i," // points pp->points, " points, " + "%i," // mana pp->mana, " mana, " + "%i," // cur_hp pp->cur_hp, " cur_hp, " + "%i," // str pp->STR, " str, " + "%i," // sta pp->STA, " sta, " + "%i," // cha pp->CHA, " cha, " + "%i," // dex pp->DEX, " dex, " + "%i," // `int` pp->INT, " `int`, " + "%i," // agi pp->AGI, " agi, " + "%i," // wis pp->WIS, " wis, " + "%i," // face pp->face, " face, " + "%f," // y pp->y, " y, " + "%f," // x pp->x, " x, " + "%f," // z pp->z, " z, " + "%f," // heading pp->heading, " heading, " + "%i," // pvp2 pp->pvp2, " pvp2, " + "%i," // pvp_type pp->pvptype, " pvp_type, " + "%i," // autosplit_enabled pp->autosplit, " autosplit_enabled, " + "%i," // zone_change_count pp->zone_change_count, " zone_change_count, " + "%i," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " + "%i," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " + "%i," // drakkin_details pp->drakkin_details, " drakkin_details, " + "%i," // toxicity pp->toxicity, " toxicity, " + "%i," // hunger_level pp->hunger_level, " hunger_level, " + "%i," // thirst_level pp->thirst_level, " thirst_level, " + "%i," // ability_up pp->ability_up, " ability_up, " + "%i," // zone_id pp->zone_id, " zone_id, " + "%i," // zone_instance pp->zoneInstance, " zone_instance, " + "%i," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " + "%i," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " + "%i," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " + "%i," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " + "%i," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " + "%i," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " + "%i," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " + "%i," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " + "%i," // show_helm pp->showhelm, " show_helm, " + "%i," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " + "%i," // tribute_points pp->tribute_points, " tribute_points, " + "%i," // tribute_active pp->tribute_active, " tribute_active, " + "%i," // endurance pp->endurance, " endurance, " + "%i," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " + "%i," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " + "%i," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " + "%i," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " + "%i," // air_remaining pp->air_remaining, " air_remaining, " + "%i," // pvp_kills pp->PVPKills, " pvp_kills, " + "%i," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " + "%i," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " + "%i," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " + "%i," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " + "%i," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " + "%i," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " + "%i," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " + "%i," // aa_exp pp->expAA, " aa_exp, " + "%i," // aa_points pp->aapoints, " aa_points, " + "%i," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " + "%i," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " + "%i," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " + "%i" // RestTimer pp->RestTimer, " RestTimer) " + ")", + character_id, + account_id, + pp->name, + pp->last_name, + pp->gender, + pp->race, + pp->class_, + pp->level, + pp->deity, + pp->birthday, + pp->lastlogin, + pp->timePlayedMin, + pp->pvp, + pp->level2, + pp->anon, + pp->gm, + pp->intoxication, + pp->haircolor, + pp->beardcolor, + pp->eyecolor1, + pp->eyecolor2, + pp->hairstyle, + pp->beard, + pp->ability_time_seconds, + pp->ability_number, + pp->ability_time_minutes, + pp->ability_time_hours, + pp->title, + pp->suffix, + pp->exp, + pp->points, + pp->mana, + pp->cur_hp, + pp->STR, + pp->STA, + pp->CHA, + pp->DEX, + pp->INT, + pp->AGI, + pp->WIS, + pp->face, + pp->y, + pp->x, + pp->z, + pp->heading, + pp->pvp2, + pp->pvptype, + pp->autosplit, + pp->zone_change_count, + pp->drakkin_heritage, + pp->drakkin_tattoo, + pp->drakkin_details, + pp->toxicity, + pp->hunger_level, + pp->thirst_level, + pp->ability_up, + pp->zone_id, + pp->zoneInstance, + pp->leadAAActive, + pp->ldon_points_guk, + pp->ldon_points_mir, + pp->ldon_points_mmc, + pp->ldon_points_ruj, + pp->ldon_points_tak, + pp->ldon_points_available, + pp->tribute_time_remaining, + pp->showhelm, + pp->career_tribute_points, + pp->tribute_points, + pp->tribute_active, + pp->endurance, + pp->group_leadership_exp, + pp->raid_leadership_exp, + pp->group_leadership_points, + pp->raid_leadership_points, + pp->air_remaining, + pp->PVPKills, + pp->PVPDeaths, + pp->PVPCurrentPoints, + pp->PVPCareerPoints, + pp->PVPBestKillStreak, + pp->PVPWorstDeathStreak, + pp->PVPCurrentKillStreak, + pp->aapoints_spent, + pp->expAA, + pp->aapoints, + pp->groupAutoconsent, + pp->raidAutoconsent, + pp->guildAutoconsent, + pp->RestTimer + ); + auto results = database.QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + return true; +} + +bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp){ + if (pp->copper < 0) { pp->copper = 0; } + if (pp->silver < 0) { pp->silver = 0; } + if (pp->gold < 0) { pp->gold = 0; } + if (pp->platinum < 0) { pp->platinum = 0; } + if (pp->copper_bank < 0) { pp->copper_bank = 0; } + if (pp->silver_bank < 0) { pp->silver_bank = 0; } + if (pp->gold_bank < 0) { pp->gold_bank = 0; } + if (pp->platinum_bank < 0) { pp->platinum_bank = 0; } + std::string query = StringFormat( + "REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," + "platinum_bank, gold_bank, silver_bank, copper_bank," + "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " + "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" + "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", + character_id, + pp->platinum, + pp->gold, + pp->silver, + pp->copper, + pp->platinum_bank, + pp->gold_bank, + pp->silver_bank, + pp->copper_bank, + pp->platinum_cursor, + pp->gold_cursor, + pp->silver_cursor, + pp->copper_cursor, + pp->currentRadCrystals, + pp->careerRadCrystals, + pp->currentEbonCrystals, + pp->careerEbonCrystals); + auto results = database.QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id); + return true; +} + +bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level){ + std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value)" + " VALUES (%u, %u, %u)", + character_id, aa_id, current_level); + auto results = QueryDatabase(rquery); + LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %i, aa_id: %u current_level: %i", character_id, aa_id, current_level); + return true; +} + // Process results of GetCharacterInfoForLogin() // Query this processes: SELECT id,profile,zonename,x,y,z,guild,guildrank,extprofile,class,level FROM character_ WHERE id=%i bool ZoneDatabase::GetCharacterInfoForLogin_result(MYSQL_RES* result, uint32* character_id, char* current_zone, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32* pplen, uint32* guilddbid, uint8* guildrank, - uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8* firstlogon) { + uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8* firstlogon) { MYSQL_ROW row; unsigned long* lengths; @@ -908,7 +1473,7 @@ bool ZoneDatabase::GetCharacterInfoForLogin_result(MYSQL_RES* result, lengths = mysql_fetch_lengths(result); if (pp && pplen) { if (lengths[1] == sizeof(PlayerProfile_Struct)) { - memcpy(pp, row[1], sizeof(PlayerProfile_Struct)); + // memcpy(pp, row[1], sizeof(PlayerProfile_Struct)); } else { LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetCharacterInfo Expected: %i, Got: %i", sizeof(PlayerProfile_Struct), lengths[1]); diff --git a/zone/zonedb.h b/zone/zonedb.h index 218654dc1..d0e70b995 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -252,8 +252,9 @@ public: bool GetAccountInfoForLogin(uint32 account_id, int16* admin = 0, char* account_name = 0, uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = 0); bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0, - uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr, - uint32* account_creation = 0); + uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr, + uint32* account_creation = 0); + bool GetCharacterInfoForLogin_result(MYSQL_RES* result, uint32* character_id = 0, char* current_zone = 0, PlayerProfile_Struct* pp = 0, Inventory* inv = 0, ExtendedProfile_Struct *ext = 0, uint32* pplen = 0, uint32* guilddbid = 0, uint8* guildrank = 0, uint8 *class_= 0, uint8 *level = 0, bool *LFP = 0, @@ -268,6 +269,16 @@ public: void SavePetInfo(Client *c); void RemoveTempFactions(Client *c); + /* Player Profile Loaders */ + bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + + /* Player Profile Saves */ + + bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); + /* * Character Inventory */ diff --git a/zone/zoning.cpp b/zone/zoning.cpp index b50e43d33..1b64fef3c 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -354,7 +354,7 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc m_pp.zoneInstance = instance_id; //Force a save so its waiting for them when they zone - Save(2); + Save(2); if (zone_id == zone->GetZoneID() && instance_id == zone->GetInstanceID()) { // No need to ask worldserver if we're zoning to ourselves (most From 5d8ea5752d075ddff043667a625219a47dc57c4a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 31 Aug 2014 03:23:42 -0500 Subject: [PATCH 03/56] Added automatic table creation in conversion process. More will come when more tables are added --- common/database.cpp | 337 ++++++++++++++++++++++++++++++++------------ 1 file changed, 247 insertions(+), 90 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 92df542f8..0996f6b0c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -825,6 +825,162 @@ bool Database::CheckDatabaseConversions() { number_of_characters = atoi(row[0]); printf("Number of Characters in Database: %i \n", number_of_characters); } + + /* Check for table `character_data` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_data'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_data` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_data` ( " + " `id` int(11) NOT NULL AUTO_INCREMENT, " + " `account_id` int(11) NOT NULL DEFAULT '0', " + " `name` varchar(64) NOT NULL, " + " `last_name` varchar(64) NOT NULL, " + " `gender` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `race` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `class` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `deity` tinyint(11) UNSIGNED NOT NULL, " + " `birthday` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `last_login` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `time_played` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_status` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `intoxication` int(11) UNSIGNED NOT NULL, " + " `hair_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `beard_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `eye_color_1` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `eye_color_2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `hair_style` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `beard` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ability_time_seconds` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ability_number` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ability_time_minutes` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ability_time_hours` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `title` varchar(32) NOT NULL, " + " `suffix` varchar(32) NOT NULL, " + " `exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `mana` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `cur_hp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `str` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `sta` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `cha` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `dex` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `int` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `agi` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `wis` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `face` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `y` float NOT NULL DEFAULT '0', " + " `x` float NOT NULL DEFAULT '0', " + " `z` float NOT NULL DEFAULT '0', " + " `heading` float NOT NULL DEFAULT '0', " + " `pvp2` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_type` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `autosplit_enabled` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `zone_change_count` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `leadership_exp_on` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ldon_points_guk` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ldon_points_mir` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ldon_points_mmc` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ldon_points_ruj` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ldon_points_tak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ldon_points_available` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `tribute_time_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `show_helm` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `tribute_active` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `endurance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `group_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `raid_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `group_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `raid_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `air_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_kills` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_deaths` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_current_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_career_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_best_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_worst_death_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `pvp_current_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_points_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `group_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `raid_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `guild_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `RestTimer` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY (`id`), " + " UNIQUE KEY `name` (`name`), " + " KEY `account_id` (`account_id`) " + " ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; " + ); + results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_currency` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_currency'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_currency` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_currency` ( " + " `id` int(11) NOT NULL AUTO_INCREMENT, " + " `platinum` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `radiant_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_radiant_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY (`id`), " + " KEY `id` (`id`) " + " ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; " + ); + results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_alternate_abilities` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_alternate_abilities'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_alternate_abilities` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_alternate_abilities` ( " + " `id` int(11) NOT NULL AUTO_INCREMENT, " + " `slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_value` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY(`id`,`slot`), " + " KEY `id` (`id`) " + " ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + ); + results = QueryDatabase(rquery); + printf(" done...\n"); + } + printf("Starting conversion...\n\n"); } // querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); @@ -978,96 +1134,96 @@ bool Database::CheckDatabaseConversions() { " guild_auto_consent, " " RestTimer) " "VALUES (" - "%u," // id " id, " - "%u," // account_id " account_id, " - "'%s'," // `name` pp->name, " `name`, " - "'%s'," // last_name pp->last_name, " last_name, " - "%u," // gender pp->gender, " gender, " - "%u," // race pp->race, " race, " - "%u," // class pp->class_, " class, " - "%u," // `level` pp->level, " `level`, " - "%u," // deity pp->deity, " deity, " - "%u," // birthday pp->birthday, " birthday, " - "%u," // last_login pp->lastlogin, " last_login, " - "%u," // time_played pp->timePlayedMin, " time_played, " - "%u," // pvp_status pp->pvp, " pvp_status, " - "%u," // level2 pp->level2, " level2, " - "%u," // anon pp->anon, " anon, " - "%u," // gm pp->gm, " gm, " - "%u," // intoxication pp->intoxication, " intoxication, " - "%u," // hair_color pp->haircolor, " hair_color, " - "%u," // beard_color pp->beardcolor, " beard_color, " - "%u," // eye_color_1 pp->eyecolor1, " eye_color_1, " - "%u," // eye_color_2 pp->eyecolor2, " eye_color_2, " - "%u," // hair_style pp->hairstyle, " hair_style, " - "%u," // beard pp->beard, " beard, " - "%u," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " - "%u," // ability_number pp->ability_number, " ability_number, " - "%u," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " - "%u," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " - "'%s'," // title pp->title, " title, " - "'%s'," // suffix pp->suffix, " suffix, " - "%u," // exp pp->exp, " exp, " - "%u," // points pp->points, " points, " - "%u," // mana pp->mana, " mana, " - "%u," // cur_hp pp->cur_hp, " cur_hp, " - "%u," // str pp->STR, " str, " - "%u," // sta pp->STA, " sta, " - "%u," // cha pp->CHA, " cha, " - "%u," // dex pp->DEX, " dex, " - "%u," // `int` pp->INT, " `int`, " - "%u," // agi pp->AGI, " agi, " - "%u," // wis pp->WIS, " wis, " - "%u," // face pp->face, " face, " - "%f," // y pp->y, " y, " - "%f," // x pp->x, " x, " - "%f," // z pp->z, " z, " - "%f," // heading pp->heading, " heading, " - "%u," // pvp2 pp->pvp2, " pvp2, " - "%u," // pvp_type pp->pvptype, " pvp_type, " - "%u," // autosplit_enabled pp->autosplit, " autosplit_enabled, " - "%u," // zone_change_count pp->zone_change_count, " zone_change_count, " - "%u," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " - "%u," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " - "%u," // drakkin_details pp->drakkin_details, " drakkin_details, " - "%u," // toxicity pp->toxicity, " toxicity, " - "%u," // hunger_level pp->hunger_level, " hunger_level, " - "%u," // thirst_level pp->thirst_level, " thirst_level, " - "%u," // ability_up pp->ability_up, " ability_up, " - "%u," // zone_id pp->zone_id, " zone_id, " - "%u," // zone_instance pp->zoneInstance, " zone_instance, " - "%u," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " - "%u," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " - "%u," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " - "%u," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " - "%u," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " - "%u," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " - "%u," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " - "%u," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " - "%u," // show_helm pp->showhelm, " show_helm, " - "%u," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " - "%u," // tribute_points pp->tribute_points, " tribute_points, " - "%u," // tribute_active pp->tribute_active, " tribute_active, " - "%u," // endurance pp->endurance, " endurance, " - "%u," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " - "%u," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " - "%u," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " - "%u," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " - "%u," // air_remaining pp->air_remaining, " air_remaining, " - "%u," // pvp_kills pp->PVPKills, " pvp_kills, " - "%u," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " - "%u," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " - "%u," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " - "%u," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " - "%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " - "%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " - "%u," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " - "%u," // aa_exp pp->expAA, " aa_exp, " - "%u," // aa_points pp->aapoints, " aa_points, " - "%u," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " - "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " - "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " - "%u" // RestTimer pp->RestTimer, " RestTimer) " + "%u," // id + "%u," // account_id + "'%s'," // `name` pp->name, + "'%s'," // last_name pp->last_name, + "%u," // gender pp->gender, + "%u," // race pp->race, + "%u," // class pp->class_, + "%u," // `level` pp->level, + "%u," // deity pp->deity, + "%u," // birthday pp->birthday, + "%u," // last_login pp->lastlogin, + "%u," // time_played pp->timePlayedMin, + "%u," // pvp_status pp->pvp, + "%u," // level2 pp->level2, + "%u," // anon pp->anon, + "%u," // gm pp->gm, + "%u," // intoxication pp->intoxication, + "%u," // hair_color pp->haircolor, + "%u," // beard_color pp->beardcolor, + "%u," // eye_color_1 pp->eyecolor1, + "%u," // eye_color_2 pp->eyecolor2, + "%u," // hair_style pp->hairstyle, + "%u," // beard pp->beard, + "%u," // ability_time_seconds pp->ability_time_seconds, + "%u," // ability_number pp->ability_number, + "%u," // ability_time_minutes pp->ability_time_minutes, + "%u," // ability_time_hours pp->ability_time_hours, + "'%s'," // title pp->title, + "'%s'," // suffix pp->suffix, + "%u," // exp pp->exp, + "%u," // points pp->points, + "%u," // mana pp->mana, + "%u," // cur_hp pp->cur_hp, + "%u," // str pp->STR, + "%u," // sta pp->STA, + "%u," // cha pp->CHA, + "%u," // dex pp->DEX, + "%u," // `int` pp->INT, + "%u," // agi pp->AGI, + "%u," // wis pp->WIS, + "%u," // face pp->face, + "%f," // y pp->y, + "%f," // x pp->x, + "%f," // z pp->z, + "%f," // heading pp->heading, + "%u," // pvp2 pp->pvp2, + "%u," // pvp_type pp->pvptype, + "%u," // autosplit_enabled pp->autosplit, + "%u," // zone_change_count pp->zone_change_count, + "%u," // drakkin_heritage pp->drakkin_heritage, + "%u," // drakkin_tattoo pp->drakkin_tattoo, + "%u," // drakkin_details pp->drakkin_details, + "%u," // toxicity pp->toxicity, + "%u," // hunger_level pp->hunger_level, + "%u," // thirst_level pp->thirst_level, + "%u," // ability_up pp->ability_up, + "%u," // zone_id pp->zone_id, + "%u," // zone_instance pp->zoneInstance, + "%u," // leadership_exp_on pp->leadAAActive, + "%u," // ldon_points_guk pp->ldon_points_guk, + "%u," // ldon_points_mir pp->ldon_points_mir, + "%u," // ldon_points_mmc pp->ldon_points_mmc, + "%u," // ldon_points_ruj pp->ldon_points_ruj, + "%u," // ldon_points_tak pp->ldon_points_tak, + "%u," // ldon_points_available pp->ldon_points_available, + "%u," // tribute_time_remaining pp->tribute_time_remaining, + "%u," // show_helm pp->showhelm, + "%u," // career_tribute_points pp->career_tribute_points, + "%u," // tribute_points pp->tribute_points, + "%u," // tribute_active pp->tribute_active, + "%u," // endurance pp->endurance, + "%u," // group_leadership_exp pp->group_leadership_exp, + "%u," // raid_leadership_exp pp->raid_leadership_exp, + "%u," // group_leadership_points pp->group_leadership_points, + "%u," // raid_leadership_points pp->raid_leadership_points, + "%u," // air_remaining pp->air_remaining, + "%u," // pvp_kills pp->PVPKills, + "%u," // pvp_deaths pp->PVPDeaths, + "%u," // pvp_current_points pp->PVPCurrentPoints, + "%u," // pvp_career_points pp->PVPCareerPoints, + "%u," // pvp_best_kill_streak pp->PVPBestKillStreak, + "%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, + "%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, + "%u," // aa_points_spent pp->aapoints_spent, + "%u," // aa_exp pp->expAA, + "%u," // aa_points pp->aapoints, + "%u," // group_auto_consent pp->groupAutoconsent, + "%u," // raid_auto_consent pp->raidAutoconsent, + "%u," // guild_auto_consent pp->guildAutoconsent, + "%u" // RestTimer pp->RestTimer, ")", character_id, account_id, @@ -1161,6 +1317,7 @@ bool Database::CheckDatabaseConversions() { pp->RestTimer ); results = QueryDatabase(rquery); + /* Run AA Convert */ for (i = 0; i < MAX_PP_AA_ARRAY; i++){ if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ From 8dda7ddd04fab80b3dd9796ff476612ff073a57e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 31 Aug 2014 05:52:36 -0500 Subject: [PATCH 04/56] Added the following tables to player profile automatic conversion during world bootup: `character_bind_home`; `character_alternate_abilities`; `character_currency`; `character_data`; `character_spells`; `character_memmed_spells`; `character_disciplines`; --- common/database.cpp | 366 +++++++++++++++++++++++++++++------------ zone/client_packet.cpp | 29 +--- 2 files changed, 265 insertions(+), 130 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0996f6b0c..a5bce5a52 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -831,9 +831,9 @@ bool Database::CheckDatabaseConversions() { results = QueryDatabase(rquery); if (results.RowCount() == 0){ printf("Table: `character_data` doesn't exist... creating..."); - rquery = StringFormat( + rquery = StringFormat( " CREATE TABLE `character_data` ( " - " `id` int(11) NOT NULL AUTO_INCREMENT, " + " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " " `account_id` int(11) NOT NULL DEFAULT '0', " " `name` varchar(64) NOT NULL, " " `last_name` varchar(64) NOT NULL, " @@ -928,7 +928,7 @@ bool Database::CheckDatabaseConversions() { " KEY `account_id` (`account_id`) " " ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; " ); - results = QueryDatabase(rquery); + QueryDatabase(rquery); printf(" done...\n"); } /* Check for table `character_currency` */ @@ -938,7 +938,7 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_currency` doesn't exist... creating..."); rquery = StringFormat( " CREATE TABLE `character_currency` ( " - " `id` int(11) NOT NULL AUTO_INCREMENT, " + " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " " `platinum` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `gold` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `silver` int(11) UNSIGNED NOT NULL DEFAULT 0, " @@ -958,8 +958,8 @@ bool Database::CheckDatabaseConversions() { " PRIMARY KEY (`id`), " " KEY `id` (`id`) " " ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; " - ); - results = QueryDatabase(rquery); + ); + QueryDatabase(rquery); printf(" done...\n"); } /* Check for table `character_alternate_abilities` */ @@ -969,23 +969,130 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_alternate_abilities` doesn't exist... creating..."); rquery = StringFormat( " CREATE TABLE `character_alternate_abilities` ( " - " `id` int(11) NOT NULL AUTO_INCREMENT, " + " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " " `slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " " `aa_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " " `aa_value` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " " PRIMARY KEY(`id`,`slot`), " " KEY `id` (`id`) " " ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " - ); - results = QueryDatabase(rquery); + ); + QueryDatabase(rquery); printf(" done...\n"); } + /* Check for table `character_bind_home` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_bind_home'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_bind_home` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_bind_home` ( " + " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + " `zone_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + " `instance_id` mediumint(11) UNSIGNED NOT NULL DEFAULT '0', " + " `x` float NOT NULL DEFAULT '0', " + " `y` float NOT NULL DEFAULT '0', " + " `z` float NOT NULL DEFAULT '0', " + " `heading` float NOT NULL DEFAULT '0', " + " PRIMARY KEY(`id`), " + " KEY `id` (`id`) " + " ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_languages` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_languages'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_languages` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_languages` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`lang_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `lang_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_skills` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_skills'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_skills` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_skills` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`skill_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `skill_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_spells` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_spells'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_spells` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_spells` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `slot_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_memmed_spells` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_memmed_spells'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_memmed_spells` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_memmed_spells` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `slot_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_disciplines` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_disciplines'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_disciplines` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_disciplines` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`disc_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `disc_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + + /* Done */ printf("Starting conversion...\n\n"); } // 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"); + querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 100"); if (RunQuery(query, querylen, errbuf, &result)) { safe_delete_array(query); while (row = mysql_fetch_row(result)) { @@ -1012,7 +1119,7 @@ bool Database::CheckDatabaseConversions() { /* Loading Status on conversion */ if (runconvert == 1){ std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; - loadbar(char_iter_count, number_of_characters, 50); + loadbar(char_iter_count, number_of_characters, 50); /* Run Currency Convert */ std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," @@ -1037,9 +1144,9 @@ bool Database::CheckDatabaseConversions() { pp->careerRadCrystals, pp->currentEbonCrystals, pp->careerEbonCrystals - ); + ); auto results = QueryDatabase(rquery); - + /* Run Character Data Convert */ rquery = StringFormat( "REPLACE INTO `character_data` (" @@ -1134,96 +1241,96 @@ bool Database::CheckDatabaseConversions() { " guild_auto_consent, " " RestTimer) " "VALUES (" - "%u," // id - "%u," // account_id - "'%s'," // `name` pp->name, - "'%s'," // last_name pp->last_name, - "%u," // gender pp->gender, - "%u," // race pp->race, - "%u," // class pp->class_, - "%u," // `level` pp->level, - "%u," // deity pp->deity, - "%u," // birthday pp->birthday, - "%u," // last_login pp->lastlogin, - "%u," // time_played pp->timePlayedMin, - "%u," // pvp_status pp->pvp, - "%u," // level2 pp->level2, - "%u," // anon pp->anon, - "%u," // gm pp->gm, - "%u," // intoxication pp->intoxication, - "%u," // hair_color pp->haircolor, - "%u," // beard_color pp->beardcolor, - "%u," // eye_color_1 pp->eyecolor1, - "%u," // eye_color_2 pp->eyecolor2, - "%u," // hair_style pp->hairstyle, - "%u," // beard pp->beard, - "%u," // ability_time_seconds pp->ability_time_seconds, - "%u," // ability_number pp->ability_number, - "%u," // ability_time_minutes pp->ability_time_minutes, - "%u," // ability_time_hours pp->ability_time_hours, - "'%s'," // title pp->title, - "'%s'," // suffix pp->suffix, - "%u," // exp pp->exp, - "%u," // points pp->points, - "%u," // mana pp->mana, - "%u," // cur_hp pp->cur_hp, - "%u," // str pp->STR, - "%u," // sta pp->STA, - "%u," // cha pp->CHA, - "%u," // dex pp->DEX, - "%u," // `int` pp->INT, - "%u," // agi pp->AGI, - "%u," // wis pp->WIS, - "%u," // face pp->face, - "%f," // y pp->y, - "%f," // x pp->x, - "%f," // z pp->z, - "%f," // heading pp->heading, - "%u," // pvp2 pp->pvp2, - "%u," // pvp_type pp->pvptype, - "%u," // autosplit_enabled pp->autosplit, - "%u," // zone_change_count pp->zone_change_count, - "%u," // drakkin_heritage pp->drakkin_heritage, - "%u," // drakkin_tattoo pp->drakkin_tattoo, - "%u," // drakkin_details pp->drakkin_details, - "%u," // toxicity pp->toxicity, - "%u," // hunger_level pp->hunger_level, - "%u," // thirst_level pp->thirst_level, - "%u," // ability_up pp->ability_up, - "%u," // zone_id pp->zone_id, - "%u," // zone_instance pp->zoneInstance, - "%u," // leadership_exp_on pp->leadAAActive, - "%u," // ldon_points_guk pp->ldon_points_guk, - "%u," // ldon_points_mir pp->ldon_points_mir, - "%u," // ldon_points_mmc pp->ldon_points_mmc, - "%u," // ldon_points_ruj pp->ldon_points_ruj, - "%u," // ldon_points_tak pp->ldon_points_tak, - "%u," // ldon_points_available pp->ldon_points_available, - "%u," // tribute_time_remaining pp->tribute_time_remaining, - "%u," // show_helm pp->showhelm, - "%u," // career_tribute_points pp->career_tribute_points, - "%u," // tribute_points pp->tribute_points, - "%u," // tribute_active pp->tribute_active, - "%u," // endurance pp->endurance, - "%u," // group_leadership_exp pp->group_leadership_exp, - "%u," // raid_leadership_exp pp->raid_leadership_exp, - "%u," // group_leadership_points pp->group_leadership_points, - "%u," // raid_leadership_points pp->raid_leadership_points, - "%u," // air_remaining pp->air_remaining, - "%u," // pvp_kills pp->PVPKills, - "%u," // pvp_deaths pp->PVPDeaths, - "%u," // pvp_current_points pp->PVPCurrentPoints, - "%u," // pvp_career_points pp->PVPCareerPoints, - "%u," // pvp_best_kill_streak pp->PVPBestKillStreak, - "%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, - "%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, - "%u," // aa_points_spent pp->aapoints_spent, - "%u," // aa_exp pp->expAA, - "%u," // aa_points pp->aapoints, - "%u," // group_auto_consent pp->groupAutoconsent, - "%u," // raid_auto_consent pp->raidAutoconsent, - "%u," // guild_auto_consent pp->guildAutoconsent, - "%u" // RestTimer pp->RestTimer, + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%u," // toxicity + "%u," // hunger_level + "%u," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_points + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_streak + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent + "%u" // RestTimer ")", character_id, account_id, @@ -1321,13 +1428,58 @@ bool Database::CheckDatabaseConversions() { /* Run AA Convert */ for (i = 0; i < MAX_PP_AA_ARRAY; i++){ if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ - std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - auto results = QueryDatabase(rquery); + QueryDatabase(rquery); + } + } + + /* Run Bind Home Convert */ + rquery = StringFormat("REPLACE INTO `character_bind_home` (id, zone_id, instance_id, x, y, z, heading)" + " VALUES (%u, %u, %u, %f, %f, %f, %f)", + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); + QueryDatabase(rquery); + + /* Run Language Convert */ + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + if (pp->languages[i] > 0){ + rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); + QueryDatabase(rquery); + } + } + + /* Run Skill Convert */ + for (i = 0; i < MAX_PP_SKILL; i++){ + if (pp->skills[i] > 0){ + rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); + QueryDatabase(rquery); + } + } + + /* Run Spell Convert */ + for (i = 0; i < MAX_PP_SPELLBOOK; i++){ + if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295){ + rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); + QueryDatabase(rquery); + } + } + + /* Run Max Memmed Spell Convert */ + for (i = 0; i < MAX_PP_MEMSPELL; i++){ + if (pp->mem_spells[i] > 0){ + rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + QueryDatabase(rquery); + } + } + + /* Run Discipline Convert */ + for (i = 0; i < MAX_PP_DISCIPLINES; i++){ + if (pp->disciplines.values[i] > 0){ + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, disc_id) VALUES (%u, %u)", character_id, pp->disciplines.values[i]); + QueryDatabase(rquery); } } - printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); } /* Print out the entire Player Profile for testing */ @@ -1646,6 +1798,8 @@ bool Database::CheckDatabaseConversions() { } mysql_free_result(result); } + if (runconvert == 1){ printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); } + return true; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index abf044caa..da5e62dc5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8786,31 +8786,15 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { if(!RuleB(Character, MaintainIntoxicationAcrossZones)) m_pp.intoxication = 0; - //uint32 aalen = database.GetPlayerAlternateAdv(account_id, name, &aa); - //if (aalen == 0) { - // std::cout << "Client dropped: !GetPlayerAlternateAdv, name=" << name << std::endl; - // return false; - //} - - - - //////////////////////////////////////////////////////////// // Player Profile Packet - // Try to find the EQ ID for the guild, if doesnt exist, guild has been deleted. - - // Clear memory, but leave it in the DB (no reason not to, guild might be restored?) - strcpy(name, m_pp.name); - strcpy(lastname, m_pp.last_name); if((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1)||(m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) { m_pp.x = zone->safe_x(); m_pp.y = zone->safe_y(); m_pp.z = zone->safe_z(); } - //these now come from the database, and it is the authority. - if(class_ > 0) - m_pp.class_ = class_; - else - class_ = m_pp.class_; + + class_ = m_pp.class_; + if(level > 0) { if(m_pp.level != level) { //they changed their level in the database... not ideal, but oh well.. @@ -8882,9 +8866,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) { /* Load Guild */ - if (!IsInAGuild()) { - m_pp.guild_id = GUILD_NONE; - } + if (!IsInAGuild()) { m_pp.guild_id = GUILD_NONE; } else { m_pp.guild_id = GuildID(); @@ -9483,8 +9465,7 @@ void Client::CompleteConnect() { } /* Sends appearances for all mobs not doing anim_stand aka sitting, looting, playing dead */ - entity_list.SendZoneAppearance(this); - + entity_list.SendZoneAppearance(this); /* Sends the Nimbus particle effects (up to 3) for any mob using them */ entity_list.SendNimbusEffects(this); From f8439fd6e6165748ceed3345eb94ad8279584b6b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 31 Aug 2014 07:52:52 -0500 Subject: [PATCH 05/56] Made many adjustments to character load code. Removed bool Client::FinishConnState2(DBAsyncWork* dbaw) Removed all async character loads Removed bool GetAccountInfoForLogin Removed bool GetAccountInfoForLogin_result Removed bool GetCharacterInfoForLogin_result Removed bool GetCharacterInfoForLogin Added: bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list); bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp); --- common/database.cpp | 2 +- zone/client_packet.cpp | 1064 +++++++++++++++++++--------------------- zone/effects.cpp | 4 - zone/zonedb.cpp | 249 ++-------- zone/zonedb.h | 18 +- 5 files changed, 540 insertions(+), 797 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a5bce5a52..429da0e42 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1092,7 +1092,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 1"); if (RunQuery(query, querylen, errbuf, &result)) { safe_delete_array(query); while (row = mysql_fetch_row(result)) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index da5e62dc5..9b2af6c45 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -538,29 +538,511 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) client->Disconnect(); } - char* query = 0; - uint32_breakdown workpt; - workpt.b4() = DBA_b4_Entity; - workpt.w2_3() = GetID(); - workpt.b1() = DBA_b1_Entity_Client_InfoForLogin; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read); - dbaw->AddQuery(1, &query, MakeAnyLenString(&query, - "SELECT status,name,lsaccount_id,gmspeed,revoked,hideme,time_creation FROM account WHERE id=%i", - account_id)); - //DO NOT FORGET TO EDIT ZoneDatabase::GetCharacterInfoForLogin if you change this - dbaw->AddQuery(2, &query, MakeAnyLenString(&query, - "SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon" - " FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", - character_id)); - dbaw->AddQuery(3, &query, MakeAnyLenString(&query, - "SELECT faction_id,current_value FROM faction_values WHERE temp = 0 AND char_id = %i", - character_id)); - if (!(pDBAsyncWorkID = dbasync->AddWork(&dbaw))) { - safe_delete(dbaw); - LogFile->write(EQEMuLog::Error,"dbasync->AddWork() returned false, client crash"); - client_state = CLIENT_KICKED; - return; + uint32 pplen = 0; + EQApplicationPacket* outapp = 0; + MYSQL_RES* result = 0; + bool loaditems = 0; + uint32 i; + std::string query; + unsigned long* lengths; + + /* Set item materials */ + for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) + if (m_pp.item_tint[i].rgb.use_tint == 1) + m_pp.item_tint[i].rgb.use_tint = 0xFF; + + uint32 cid = CharacterID(); + character_id = cid; + + database.RemoveTempFactions(this); + database.LoadCharacterFactionValues(cid, factionvalues); + /* Load Character Account Data: Temp until I move */ + query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %i", this->AccountID()); + auto results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + if (admin){ admin = atoi(row[0]); } + if (account_name){ strcpy(account_name, row[1]); } + if (lsaccountid && atoi(row[2]) > 0){ lsaccountid = atoi(row[2]); } + else{ lsaccountid = 0; } + if (gmspeed){ gmspeed = atoi(row[3]); } + if (revoked){ revoked = atoi(row[4]); } + if (gmhideme){ gmhideme = atoi(row[5]); } + if (account_creation){ account_creation = atoul(row[6]); } } + /* Load Character Legacy Data: Temp until I move */ + query = StringFormat("id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", cid); + results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + m_pp.lastlogin = time(nullptr); + + if (RuleB(Character, SharedBankPlat)) + m_pp.platinum_shared = database.GetSharedPlatinum(database.GetAccountIDByChar(cid)); + + if (guildrank) { + if (row[7] != nullptr) + guildrank = atoi(row[7]); + else + guildrank = GUILD_RANK_NONE; + } + // if (ext) { SetExtendedProfile(ext, row[8], lengths[8]); } + if (level){ level = atoi(row[10]); } + if (LFP){ LFP = atoi(row[11]); } + if (LFG){ LFG = atoi(row[12]); } + if (firstlogon){ firstlogon = atoi(row[15]); } + } + /* Load Character Inventory */ + loaditems = database.GetInventory(cid, &m_inv); + /* Load Character Currency into PP */ + database.LoadCharacterCurrency(cid, &m_pp); + /* Load Character Data from DB into PP */ + database.LoadCharacterData(cid, &m_pp); + /* Move to another method when can, this is pointless... */ + database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); + /* Load Character Currency */ + database.LoadCharacterCurrency(cid, &m_pp); + /* Load Character Skills */ + database.LoadCharacterSkills(cid, &m_pp); + /* Load Character Disciplines */ + database.LoadCharacterDisciplines(cid, &m_pp); + + if (gmhideme) { trackable = false; } + + conn_state = PlayerProfileLoaded; + + /* Set Current zone */ + // m_pp.zone_id = zone->GetZoneID(); + // m_pp.zoneInstance = zone->GetInstanceID(); + + TotalSecondsPlayed = m_pp.timePlayedMin * 60; + + max_AAXP = RuleI(AA, ExpPerPoint); + + if (!RuleB(Character, MaintainIntoxicationAcrossZones)) + m_pp.intoxication = 0; + + if ((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1) || (m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) { + m_pp.x = zone->safe_x(); + m_pp.y = zone->safe_y(); + m_pp.z = zone->safe_z(); + } + + /* If too far below ground, then fix */ + float ground_z = GetGroundZ(m_pp.x, m_pp.y, m_pp.z); + if (m_pp.z < (ground_z - 500)) + m_pp.z = ground_z; + + class_ = m_pp.class_; + + level = m_pp.level; + x_pos = m_pp.x; + y_pos = m_pp.y; + z_pos = m_pp.z; + heading = m_pp.heading; + race = m_pp.race; + base_race = m_pp.race; + gender = m_pp.gender; + base_gender = m_pp.gender; + deity = m_pp.deity; //FYI: DEITY_AGNOSTIC = 396; still valid? + haircolor = m_pp.haircolor; + beardcolor = m_pp.beardcolor; + eyecolor1 = m_pp.eyecolor1; + eyecolor2 = m_pp.eyecolor2; + hairstyle = m_pp.hairstyle; + luclinface = m_pp.face; + beard = m_pp.beard; + drakkin_heritage = m_pp.drakkin_heritage; + drakkin_tattoo = m_pp.drakkin_tattoo; + drakkin_details = m_pp.drakkin_details; + + if (m_pp.gm && admin < minStatusToBeGM) + m_pp.gm = 0; + + /* Load Guild */ + if (!IsInAGuild()) { m_pp.guild_id = GUILD_NONE; } + else { + m_pp.guild_id = GuildID(); + + if (zone->GetZoneID() == RuleI(World, GuildBankZoneID)) + GuildBanker = (guild_mgr.IsGuildLeader(GuildID(), CharacterID()) || guild_mgr.GetBankerFlag(CharacterID())); + } + + m_pp.guildbanker = GuildBanker; + + switch (race) + { + case OGRE: + size = 9; break; + case TROLL: + size = 8; break; + case VAHSHIR: case BARBARIAN: + size = 7; break; + case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN: + size = 6; break; + case HALF_ELF: + size = 5.5; break; + case WOOD_ELF: case DARK_ELF: case FROGLOK: + size = 5; break; + case DWARF: + size = 4; break; + case HALFLING: + size = 3.5; break; + case GNOME: + size = 3; break; + default: + size = 0; + } + + /* Check for Invalid points */ + if (m_pp.ldon_points_guk < 0 || m_pp.ldon_points_guk > 2000000000){ m_pp.ldon_points_guk = 0; } + if (m_pp.ldon_points_mir < 0 || m_pp.ldon_points_mir > 2000000000){ m_pp.ldon_points_mir = 0; } + if (m_pp.ldon_points_mmc < 0 || m_pp.ldon_points_mmc > 2000000000){ m_pp.ldon_points_mmc = 0; } + if (m_pp.ldon_points_ruj < 0 || m_pp.ldon_points_ruj > 2000000000){ m_pp.ldon_points_ruj = 0; } + if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } + if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } + + if (GetSkill(SkillSwimming) < 100) + SetSkill(SkillSwimming, 100); + + /* Initialize AA's : Move to function eventually */ + for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ aa[a] = &m_pp.aa_array[a]; } + query = StringFormat( + "SELECT " + "slot, " + "aa_id, " + "aa_value " + "FROM " + "`character_alternate_abilities` " + "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); + results = database.QueryDatabase(query); i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); + m_pp.aa_array[i].AA = atoi(row[1]); + m_pp.aa_array[i].value = atoi(row[1]); + aa[i]->AA = atoi(row[1]); + aa[i]->value = atoi(row[2]); + } + for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ + uint32 id = aa[a]->AA; + //watch for invalid AA IDs + if (id == aaNone) + continue; + if (id >= aaHighestID) { + aa[a]->AA = aaNone; + aa[a]->value = 0; + continue; + } + if (aa[a]->value == 0) { + aa[a]->AA = aaNone; + continue; + } + if (aa[a]->value > HIGHEST_AA_VALUE) { + aa[a]->AA = aaNone; + aa[a]->value = 0; + continue; + } + + if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ + aa_points[(id - aa[a]->value + 1)] = aa[a]->value; + else + aa_points[id] = aa[a]->value; + } + + if (SPDAT_RECORDS > 0) + { + for (uint32 z = 0; z= (uint32)SPDAT_RECORDS) + UnmemSpell(z, false); + } + + database.LoadBuffs(this); + uint32 max_slots = GetMaxBuffSlots(); + for (int i = 0; i < max_slots; i++) { + if (buffs[i].spellid != SPELL_UNKNOWN) { + m_pp.buffs[i].spellid = buffs[i].spellid; + m_pp.buffs[i].bard_modifier = 10; + m_pp.buffs[i].slotid = 2; + m_pp.buffs[i].player_id = 0x2211; + m_pp.buffs[i].level = buffs[i].casterlevel; + m_pp.buffs[i].effect = 0; + m_pp.buffs[i].duration = buffs[i].ticsremaining; + m_pp.buffs[i].counters = buffs[i].counters; + } + else { + m_pp.buffs[i].spellid = SPELLBOOK_UNKNOWN; + m_pp.buffs[i].bard_modifier = 10; + m_pp.buffs[i].slotid = 0; + m_pp.buffs[i].player_id = 0; + m_pp.buffs[i].level = 0; + m_pp.buffs[i].effect = 0; + m_pp.buffs[i].duration = 0; + m_pp.buffs[i].counters = 0; + } + } + } + + /* Load Character Key Ring */ + KeyRingLoad(); + + /* Send Group Members via PP */ + uint32 groupid = database.GetGroupID(GetName()); + Group* group = nullptr; + if (groupid > 0){ + group = entity_list.GetGroupByID(groupid); + if (!group) { //nobody from our is here... start a new group + group = new Group(groupid); + if (group->GetID() != 0) + entity_list.AddGroup(group, groupid); + else //error loading group members... + { + delete group; + group = nullptr; + } + } //else, somebody from our group is already here... + + if (group) + group->UpdatePlayer(this); + else + database.SetGroupID(GetName(), 0, CharacterID()); //cannot re-establish group, kill it + + } + else { //no group id + //clear out the group junk in our PP + uint32 xy = 0; + for (xy = 0; xy < MAX_GROUP_MEMBERS; xy++) + memset(m_pp.groupMembers[xy], 0, 64); + } + + if (group){ + // If the group leader is not set, pull the group leader infomrmation from the database. + if (!group->GetLeader()){ + char ln[64]; + char MainTankName[64]; + char AssistName[64]; + char PullerName[64]; + char NPCMarkerName[64]; + GroupLeadershipAA_Struct GLAA; + memset(ln, 0, 64); + strcpy(ln, database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, &GLAA)); + Client *c = entity_list.GetClientByName(ln); + if (c) + group->SetLeader(c); + + group->SetMainTank(MainTankName); + group->SetMainAssist(AssistName); + group->SetPuller(PullerName); + group->SetNPCMarker(NPCMarkerName); + group->SetGroupAAs(&GLAA); + + //group->NotifyMainTank(this, 1); + //group->NotifyMainAssist(this, 1); + //group->NotifyPuller(this, 1); + + // If we are the leader, force an update of our group AAs to other members in the zone, in case + // we purchased a new one while out-of-zone. + if (group->IsLeader(this)) + group->SendLeadershipAAUpdate(); + + } + LFG = false; + } + +#ifdef BOTS + Bot::LoadAndSpawnAllZonedBots(this); +#endif + + CalcBonuses(); + if (m_pp.cur_hp <= 0) + m_pp.cur_hp = GetMaxHP(); + + SetHP(m_pp.cur_hp); + Mob::SetMana(m_pp.mana); + SetEndurance(m_pp.endurance); + + if (IsLFP()) { + // Update LFP in case any (or all) of our group disbanded while we were zoning. + UpdateLFP(); + } + + if (m_pp.z <= zone->newzone_data.underworld) { + m_pp.x = zone->newzone_data.safe_x; + m_pp.y = zone->newzone_data.safe_y; + m_pp.z = zone->newzone_data.safe_z; + } + + /* Get Expansions from variables table and ship via PP */ + char val[20] = { 0 }; + if (database.GetVariable("Expansions", val, 20)) + m_pp.expansions = atoi(val); + else + m_pp.expansions = 0x3FF; + + p_timers.SetCharID(CharacterID()); + if (!p_timers.Load(&database)) { + LogFile->write(EQEMuLog::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID()); + } + + for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + if (IsValidSpell(m_pp.mem_spells[i])) + m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000; + + /* Ability slot refresh send SK/PAL */ + if (m_pp.class_ == SHADOWKNIGHT || m_pp.class_ == PALADIN) { + uint32 abilitynum = 0; + if (m_pp.class_ == SHADOWKNIGHT){ abilitynum = pTimerHarmTouch; } + else{ abilitynum = pTimerLayHands; } + + uint32 remaining = p_timers.GetRemainingTime(abilitynum); + if (remaining > 0 && remaining < 15300) + m_pp.abilitySlotRefresh = remaining * 1000; + else + m_pp.abilitySlotRefresh = 0; + } + +#ifdef _EQDEBUG + printf("Dumping inventory on load:\n"); + m_inv.dumpEntireInventory(); +#endif + + //lost in current PP + // strcpy(m_pp.servername,"eqemulator"); + + m_pp.air_remaining = 60; //Reset to max so they dont drown on zone in if its underwater + + if (zone->IsPVPZone()) + m_pp.pvp = 1; + + m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; + + /* Reset rest timer if the durations have been lowered in the database */ + if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) + m_pp.RestTimer = 0; + + /* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ + CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct)-4); + + outapp = new EQApplicationPacket(OP_PlayerProfile, sizeof(PlayerProfile_Struct)); + + /* The entityid field in the Player Profile is used by the Client in relation to Group Leadership AA */ + m_pp.entityid = GetID(); + memcpy(outapp->pBuffer, &m_pp, outapp->size); + outapp->priority = 6; + FastQueuePacket(&outapp); + + if (m_pp.RestTimer) + rest_timer.Start(m_pp.RestTimer * 1000); + + database.LoadPetInfo(this); + /* + This was moved before the spawn packets are sent + in hopes that it adds more consistency... + Remake pet + */ + if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) + { + MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); + if (GetPet() && GetPet()->IsNPC()) { + NPC *pet = GetPet()->CastToNPC(); + pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); + pet->CalcBonuses(); + pet->SetHP(m_petinfo.HP); + pet->SetMana(m_petinfo.Mana); + } + m_petinfo.SpellID = 0; + } + /* Moved here so it's after where we load the pet data. */ + if (!GetAA(aaPersistentMinion)) + memset(&m_suspendedminion, 0, sizeof(PetInfo)); + + /* Server Zone Entry Packet */ + outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); + ServerZoneEntry_Struct* sze = (ServerZoneEntry_Struct*)outapp->pBuffer; + + FillSpawnStruct(&sze->player, CastToMob()); + sze->player.spawn.curHp = 1; + sze->player.spawn.NPC = 0; + sze->player.spawn.z += 6; //arbitrary lift, seems to help spawning under zone. + outapp->priority = 6; + FastQueuePacket(&outapp); + + /* Zone Spawns Packet */ + entity_list.SendZoneSpawnsBulk(this); + entity_list.SendZoneCorpsesBulk(this); + entity_list.SendZonePVPUpdates(this); //hack until spawn struct is fixed. + + /* Time of Day packet */ + outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); + TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer; + zone->zone_time.getEQTimeOfDay(time(0), tod); + outapp->priority = 6; + FastQueuePacket(&outapp); + + /* Tribute Packets */ + DoTributeUpdate(); + if (m_pp.tribute_active) { + //restart the tribute timer where we left off + tribute_timer.Start(m_pp.tribute_time_remaining); + } + + /* + Character Inventory Packet + this is not quite where live sends inventory, they do it after tribute + */ + if (loaditems) { //dont load if a length error occurs + BulkSendInventoryItems(); + + // Send stuff on the cursor which isnt sent in bulk + iter_queue it; + for (it = m_inv.cursor_begin(); it != m_inv.cursor_end(); ++it) { + // First item cursor is sent in bulk inventory packet + if (it == m_inv.cursor_begin()) + continue; + const ItemInst *inst = *it; + SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + } + } + + /* Task Packets */ + LoadClientTaskState(); + + if (GetClientVersion() >= EQClientRoF) + { + outapp = new EQApplicationPacket(OP_ReqNewZone, 0); + Handle_Connect_OP_ReqNewZone(outapp); + safe_delete(outapp); + } + + if (ClientVersionBit & BIT_UnderfootAndLater) + { + outapp = new EQApplicationPacket(OP_XTargetResponse, 8); + outapp->WriteUInt32(GetMaxXTargets()); + outapp->WriteUInt32(0); + FastQueuePacket(&outapp); + } + + /* + Weather Packet + This shouldent be moved, this seems to be what the client + uses to advance to the next state (sending ReqNewZone) + */ + outapp = new EQApplicationPacket(OP_Weather, 12); + Weather_Struct *ws = (Weather_Struct *)outapp->pBuffer; + ws->val1 = 0x000000FF; + if (zone->zone_weather == 1) + ws->type = 0x31; // Rain + if (zone->zone_weather == 2) + { + outapp->pBuffer[8] = 0x01; + ws->type = 0x02; + } + outapp->priority = 6; + QueuePacket(outapp); + safe_delete(outapp); + + SetAttackTimer(); + + conn_state = ZoneInfoSent; + return; } @@ -8692,11 +9174,6 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { Entity::DBAWComplete(workpt_b1, dbaw); switch (workpt_b1) { - case DBA_b1_Entity_Client_InfoForLogin: { - if (!FinishConnState2(dbaw)) - client_state = CLIENT_ERROR; - break; - } case DBA_b1_Entity_Client_Save: { clock_t t = std::clock(); /* Function timer start */ @@ -8726,539 +9203,6 @@ void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { } } -bool Client::FinishConnState2(DBAsyncWork* dbaw) { - uint32 pplen = 0; - DBAsyncQuery* dbaq = 0; - EQApplicationPacket* outapp = 0; - MYSQL_RES* result = 0; - bool loaditems = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - uint32 i; - - for (i=1; i<=3; i++) { - dbaq = dbaw->PopAnswer(); - if (!dbaq) { - std::cout << "Error in FinishConnState2(): dbaq==0" << std::endl; - return false; - } - if (!dbaq->GetAnswer(errbuf, &result)) { - std::cout << "Error in FinishConnState2(): !dbaq[" << dbaq->QPT() << "]->GetAnswer(): " << errbuf << std::endl; - return false; - } - if (dbaq->QPT() == 1) { - database.GetAccountInfoForLogin_result(result, 0, account_name, &lsaccountid, &gmspeed, &revoked, &gmhideme, &account_creation); - if(gmhideme) - { - trackable = false; - } - } - else if (dbaq->QPT() == 2) { - loaditems = database.GetCharacterInfoForLogin_result(result, 0, 0, &m_pp, &m_inv, &m_epp, &pplen, &guild_id, &guildrank, &class_, &level, &LFP, &LFG, &MaxXTargets, &firstlogon); - } - else if (dbaq->QPT() == 3) { - database.RemoveTempFactions(this); - database.LoadFactionValues_result(result, factionvalues); - } - else { - std::cout << "Error in FinishConnState2(): dbaq->PQT() unknown" << std::endl; - return false; - } - } - - /* Load Character Currency into PP */ - database.LoadCharacterCurrency(CharacterID(), &m_pp); - /* Load Character Data from DB into PP */ - database.LoadCharacterData(CharacterID(), &m_pp); - /* Move to another method when can, this is pointless... */ - database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); - /* Load Character Currency*/ - database.LoadCharacterCurrency(CharacterID(), &m_pp); - - conn_state = PlayerProfileLoaded; - /* Set Current zone */ - m_pp.zone_id = zone->GetZoneID(); - m_pp.zoneInstance = zone->GetInstanceID(); - - TotalSecondsPlayed = m_pp.timePlayedMin * 60; - - max_AAXP = RuleI(AA, ExpPerPoint); - - if(!RuleB(Character, MaintainIntoxicationAcrossZones)) - m_pp.intoxication = 0; - - if((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1)||(m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) { - m_pp.x = zone->safe_x(); - m_pp.y = zone->safe_y(); - m_pp.z = zone->safe_z(); - } - - - class_ = m_pp.class_; - - if(level > 0) { - if(m_pp.level != level) { - //they changed their level in the database... not ideal, but oh well.. - m_pp.exp = GetEXPForLevel(level); - m_pp.level = level; - } - } else { - level = m_pp.level; - } - - x_pos = m_pp.x; - y_pos = m_pp.y; - z_pos = m_pp.z; - heading = m_pp.heading; - race = m_pp.race; - base_race = m_pp.race; - gender = m_pp.gender; - base_gender = m_pp.gender; - deity = m_pp.deity; //FYI: DEITY_AGNOSTIC = 396; still valid? - haircolor = m_pp.haircolor; - beardcolor = m_pp.beardcolor; - eyecolor1 = m_pp.eyecolor1; - eyecolor2 = m_pp.eyecolor2; - hairstyle = m_pp.hairstyle; - luclinface = m_pp.face; - beard = m_pp.beard; - drakkin_heritage = m_pp.drakkin_heritage; - drakkin_tattoo = m_pp.drakkin_tattoo; - drakkin_details = m_pp.drakkin_details; - - //if we zone in with invalid Z, fix it. - if (zone->zonemap != nullptr) { - Map::Vertex me; - me.x = GetX(); - me.y = GetY(); - me.z = GetZ() + (GetSize() == 0.0 ? 6 : GetSize()); - - Map::Vertex hit; - - if (zone->zonemap->FindBestZ(me, &hit) == BEST_Z_INVALID) - { -#if EQDEBUG >= 5 - LogFile->write(EQEMuLog::Debug, "Player %s started below the zone trying to fix! (%.3f, %.3f, %.3f)", GetName(), me.x, me.y, me.z); -#endif - me.z += 200; //arbitrary # - if (zone->zonemap->FindBestZ(me, &hit) != BEST_Z_INVALID) - { - //+10 so they dont stick in the ground - SendTo(me.x, me.y, hit.z + 10); - m_pp.z = hit.z + 10; - } - else - { - //one more, desperate try - me.z += 2000; - if (zone->zonemap->FindBestZ(me, &hit) != BEST_Z_INVALID) - { - //+10 so they dont stick in the ground - SendTo(me.x, me.y, hit.z + 10); - m_pp.z = hit.z + 10; - } - } - } - } - - if (m_pp.gm && admin < minStatusToBeGM) - m_pp.gm = 0; - - - - /* Load Guild */ - if (!IsInAGuild()) { m_pp.guild_id = GUILD_NONE; } - else { - m_pp.guild_id = GuildID(); - - if(zone->GetZoneID() == RuleI(World, GuildBankZoneID)) - GuildBanker = (guild_mgr.IsGuildLeader(GuildID(), CharacterID()) || guild_mgr.GetBankerFlag(CharacterID())); - } - - m_pp.guildbanker = GuildBanker; - - switch (race) - { - case OGRE: - size = 9; break; - case TROLL: - size = 8; break; - case VAHSHIR: case BARBARIAN: - size = 7; break; - case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN: - size = 6; break; - case HALF_ELF: - size = 5.5; break; - case WOOD_ELF: case DARK_ELF: case FROGLOK: - size = 5; break; - case DWARF: - size = 4; break; - case HALFLING: - size = 3.5; break; - case GNOME: - size = 3; break; - default: - size = 0; - } - - /* Check for Invalid points */ - if (m_pp.ldon_points_guk < 0 || m_pp.ldon_points_guk > 2000000000){ m_pp.ldon_points_guk = 0; } - if (m_pp.ldon_points_mir < 0 || m_pp.ldon_points_mir > 2000000000){ m_pp.ldon_points_mir = 0; } - if (m_pp.ldon_points_mmc < 0 || m_pp.ldon_points_mmc > 2000000000){ m_pp.ldon_points_mmc = 0; } - if (m_pp.ldon_points_ruj < 0 || m_pp.ldon_points_ruj > 2000000000){ m_pp.ldon_points_ruj = 0; } - if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } - if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } - - if(GetSkill(SkillSwimming) < 100) - SetSkill(SkillSwimming, 100); - - - - /* Load Character AA's */ - //database.LoadCharacterAA(this->CharacterID(), &m_pp, &aa, &aa_points); - - /* Initialize AA's */ - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ - aa[a] = &m_pp.aa_array[a]; - } - std::string query = StringFormat( - "SELECT " - "slot, " - "aa_id, " - "aa_value " - "FROM " - "`character_alternate_abilities` " - "WHERE `id` = %i ORDER BY `slot`", this->CharacterID()); - auto results = database.QueryDatabase(query); int si = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - si = atoi(row[0]); - m_pp.aa_array[si].AA = atoi(row[1]); - m_pp.aa_array[si].value = atoi(row[1]); - aa[si]->AA = atoi(row[1]); - aa[si]->value = atoi(row[2]); - } - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ - uint32 id = aa[a]->AA; - //watch for invalid AA IDs - if (id == aaNone) - continue; - if (id >= aaHighestID) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - if (aa[a]->value == 0) { - aa[a]->AA = aaNone; - continue; - } - if (aa[a]->value > HIGHEST_AA_VALUE) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - - if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ - aa_points[(id - aa[a]->value + 1)] = aa[a]->value; - else - aa_points[id] = aa[a]->value; - } - - if(SPDAT_RECORDS > 0) - { - for(uint32 z=0;z= (uint32)SPDAT_RECORDS) - UnmemSpell(z, false); - } - - database.LoadBuffs(this); - uint32 max_slots = GetMaxBuffSlots(); - for(int i = 0; i < max_slots; i++) { - if(buffs[i].spellid != SPELL_UNKNOWN) { - m_pp.buffs[i].spellid = buffs[i].spellid; - m_pp.buffs[i].bard_modifier = 10; - m_pp.buffs[i].slotid = 2; - m_pp.buffs[i].player_id = 0x2211; - m_pp.buffs[i].level = buffs[i].casterlevel; - m_pp.buffs[i].effect = 0; - m_pp.buffs[i].duration = buffs[i].ticsremaining; - m_pp.buffs[i].counters = buffs[i].counters; - } else { - m_pp.buffs[i].spellid = SPELLBOOK_UNKNOWN; - m_pp.buffs[i].bard_modifier = 10; - m_pp.buffs[i].slotid = 0; - m_pp.buffs[i].player_id = 0; - m_pp.buffs[i].level = 0; - m_pp.buffs[i].effect = 0; - m_pp.buffs[i].duration = 0; - m_pp.buffs[i].counters = 0; - } - } - } - - /* Load Character Key Ring */ - KeyRingLoad(); - - /* Send Group Members via PP */ - uint32 groupid = database.GetGroupID(GetName()); - Group* group = nullptr; - if(groupid > 0){ - group = entity_list.GetGroupByID(groupid); - if(!group) { //nobody from our is here... start a new group - group = new Group(groupid); - if(group->GetID() != 0) - entity_list.AddGroup(group, groupid); - else //error loading group members... - { - delete group; - group = nullptr; - } - } //else, somebody from our group is already here... - - if(group) - group->UpdatePlayer(this); - else - database.SetGroupID(GetName(), 0, CharacterID()); //cannot re-establish group, kill it - - } else { //no group id - //clear out the group junk in our PP - uint32 xy=0; - for(xy=0;xy < MAX_GROUP_MEMBERS;xy++) - memset(m_pp.groupMembers[xy], 0, 64); - } - - if(group){ - // If the group leader is not set, pull the group leader infomrmation from the database. - if(!group->GetLeader()){ - char ln[64]; - char MainTankName[64]; - char AssistName[64]; - char PullerName[64]; - char NPCMarkerName[64]; - GroupLeadershipAA_Struct GLAA; - memset(ln, 0, 64); - strcpy(ln, database.GetGroupLeadershipInfo(group->GetID(), ln, MainTankName, AssistName, PullerName, NPCMarkerName, &GLAA)); - Client *c = entity_list.GetClientByName(ln); - if(c) - group->SetLeader(c); - - group->SetMainTank(MainTankName); - group->SetMainAssist(AssistName); - group->SetPuller(PullerName); - group->SetNPCMarker(NPCMarkerName); - group->SetGroupAAs(&GLAA); - - //group->NotifyMainTank(this, 1); - //group->NotifyMainAssist(this, 1); - //group->NotifyPuller(this, 1); - - // If we are the leader, force an update of our group AAs to other members in the zone, in case - // we purchased a new one while out-of-zone. - if(group->IsLeader(this)) - group->SendLeadershipAAUpdate(); - - } - LFG = false; - } - -#ifdef BOTS - Bot::LoadAndSpawnAllZonedBots(this); -#endif - - CalcBonuses(); - if (m_pp.cur_hp <= 0) - m_pp.cur_hp = GetMaxHP(); - - SetHP(m_pp.cur_hp); - Mob::SetMana(m_pp.mana); - SetEndurance(m_pp.endurance); - - if(IsLFP()) { - // Update LFP in case any (or all) of our group disbanded while we were zoning. - UpdateLFP(); - } - - if(m_pp.z <= zone->newzone_data.underworld) { - m_pp.x = zone->newzone_data.safe_x; - m_pp.y = zone->newzone_data.safe_y; - m_pp.z = zone->newzone_data.safe_z; - } - - /* Get Expansions from variables table and ship via PP */ - char val[20] = {0}; - if (database.GetVariable("Expansions", val, 20)) - m_pp.expansions = atoi(val); - else - m_pp.expansions = 0x3FF; - - p_timers.SetCharID(CharacterID()); - if(!p_timers.Load(&database)) { - LogFile->write(EQEMuLog::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID()); - } - - for(unsigned int i =0 ; i < MAX_PP_MEMSPELL; ++i) - if(IsValidSpell(m_pp.mem_spells[i])) - m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000; - - /* Ability slot refresh send SK/PAL */ - if(m_pp.class_==SHADOWKNIGHT || m_pp.class_==PALADIN) { - uint32 abilitynum=0; - if (m_pp.class_ == SHADOWKNIGHT){ abilitynum = pTimerHarmTouch; } - else{ abilitynum = pTimerLayHands; } - - uint32 remaining = p_timers.GetRemainingTime(abilitynum); - if(remaining > 0 && remaining < 15300) - m_pp.abilitySlotRefresh = remaining * 1000; - else - m_pp.abilitySlotRefresh = 0; - } - -#ifdef _EQDEBUG - printf("Dumping inventory on load:\n"); - m_inv.dumpEntireInventory(); -#endif - -//lost in current PP -// strcpy(m_pp.servername,"eqemulator"); - - m_pp.air_remaining = 60; //Reset to max so they dont drown on zone in if its underwater - - if(zone->IsPVPZone()) - m_pp.pvp=1; - - m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; - - /* Reset rest timer if the durations have been lowered in the database */ - if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) - m_pp.RestTimer = 0; - - /* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ - CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct)-4); - - outapp = new EQApplicationPacket(OP_PlayerProfile,sizeof(PlayerProfile_Struct)); - - /* The entityid field in the Player Profile is used by the Client in relation to Group Leadership AA */ - m_pp.entityid = GetID(); - memcpy(outapp->pBuffer,&m_pp,outapp->size); - outapp->priority = 6; - FastQueuePacket(&outapp); - - if(m_pp.RestTimer) - rest_timer.Start(m_pp.RestTimer * 1000); - - database.LoadPetInfo(this); - /* - This was moved before the spawn packets are sent - in hopes that it adds more consistency... - Remake pet - */ - if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) - { - MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); - if (GetPet() && GetPet()->IsNPC()) { - NPC *pet = GetPet()->CastToNPC(); - pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); - pet->CalcBonuses(); - pet->SetHP(m_petinfo.HP); - pet->SetMana(m_petinfo.Mana); - } - m_petinfo.SpellID = 0; - } - /* Moved here so it's after where we load the pet data. */ - if(!GetAA(aaPersistentMinion)) - memset(&m_suspendedminion, 0, sizeof(PetInfo)); - - /* Server Zone Entry Packet */ - outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); - ServerZoneEntry_Struct* sze = (ServerZoneEntry_Struct*)outapp->pBuffer; - - FillSpawnStruct(&sze->player,CastToMob()); - sze->player.spawn.curHp=1; - sze->player.spawn.NPC=0; - sze->player.spawn.z += 6; //arbitrary lift, seems to help spawning under zone. - outapp->priority = 6; - FastQueuePacket(&outapp); - - /* Zone Spawns Packet */ - entity_list.SendZoneSpawnsBulk(this); - entity_list.SendZoneCorpsesBulk(this); - entity_list.SendZonePVPUpdates(this); //hack until spawn struct is fixed. - - /* Time of Day packet */ - outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); - TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer; - zone->zone_time.getEQTimeOfDay(time(0), tod); - outapp->priority = 6; - FastQueuePacket(&outapp); - - /* Tribute Packets */ - DoTributeUpdate(); - if(m_pp.tribute_active) { - //restart the tribute timer where we left off - tribute_timer.Start(m_pp.tribute_time_remaining); - } - - /* - Character Inventory Packet - this is not quite where live sends inventory, they do it after tribute - */ - if (loaditems) { //dont load if a length error occurs - BulkSendInventoryItems(); - - // Send stuff on the cursor which isnt sent in bulk - iter_queue it; - for (it=m_inv.cursor_begin();it!=m_inv.cursor_end();++it) { - // First item cursor is sent in bulk inventory packet - if (it==m_inv.cursor_begin()) - continue; - const ItemInst *inst=*it; - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); - } - } - - /* Task Packets */ - LoadClientTaskState(); - - if (GetClientVersion() >= EQClientRoF) - { - outapp = new EQApplicationPacket(OP_ReqNewZone, 0); - Handle_Connect_OP_ReqNewZone(outapp); - safe_delete(outapp); - } - - if(ClientVersionBit & BIT_UnderfootAndLater) - { - outapp = new EQApplicationPacket(OP_XTargetResponse, 8); - outapp->WriteUInt32(GetMaxXTargets()); - outapp->WriteUInt32(0); - FastQueuePacket(&outapp); - } - - /* - Weather Packet - This shouldent be moved, this seems to be what the client - uses to advance to the next state (sending ReqNewZone) - */ - outapp = new EQApplicationPacket(OP_Weather, 12); - Weather_Struct *ws = (Weather_Struct *) outapp->pBuffer; - ws->val1 = 0x000000FF; - if (zone->zone_weather == 1) - ws->type = 0x31; // Rain - if (zone->zone_weather == 2) - { - outapp->pBuffer[8] = 0x01; - ws->type = 0x02; - } - outapp->priority = 6; - QueuePacket(outapp); - safe_delete(outapp); - - SetAttackTimer(); - - conn_state = ZoneInfoSent; - - return true; -} - /* Finish client connecting state */ void Client::CompleteConnect() { UpdateWho(); diff --git a/zone/effects.cpp b/zone/effects.cpp index a24a6b39b..5e07d5f9a 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -616,13 +616,9 @@ bool Client::TrainDiscipline(uint32 itemid) { } void Client::SendDisciplineUpdate() { - //this dosent seem to work right now - EQApplicationPacket app(OP_DisciplineUpdate, sizeof(Disciplines_Struct)); Disciplines_Struct *d = (Disciplines_Struct*)app.pBuffer; - //dunno why I dont just send the one from m_pp memcpy(d, &m_pp.disciplines, sizeof(m_pp.disciplines)); - QueuePacket(&app); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e7bad016c..4eb0e64ab 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -370,41 +370,6 @@ void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){ safe_delete_array(bugtext); } - -bool ZoneDatabase::GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme, uint32* account_creation) { - MYSQL_ROW row; - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (admin) - *admin = atoi(row[0]); - if (account_name) - strcpy(account_name, row[1]); - if (lsaccountid) { - - if (row[2]) - *lsaccountid = atoi(row[2]); - else - *lsaccountid = 0; - - - } - if (gmspeed) - *gmspeed = atoi(row[3]); - if (revoked) - *revoked = atoi(row[4]); - if(gmhideme) - *gmhideme = atoi(row[5]); - if(account_creation) - *account_creation = atoul(row[6]); - - return true; - } - else { - return false; - } -} - - bool ZoneDatabase::SetSpecialAttkFlag(uint8 id, const char* flag) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; @@ -859,43 +824,8 @@ void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) } -bool ZoneDatabase::GetCharacterInfoForLogin(const char* name, uint32* character_id, - char* current_zone, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, - uint32* pplen, uint32* guilddbid, uint8* guildrank, - uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8 *firstlogon) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 querylen; - MYSQL_RES *result; - - bool ret = false; - - //DO NOT FORGET TO EDIT Client::Handle_Connect_OP_ZoneEntry if you change this. - - if (character_id && *character_id) { - // searching by ID should be a lil bit faster - querylen = MakeAnyLenString(&query, "SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", *character_id); - } - else { - querylen = MakeAnyLenString(&query, "SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE name='%s'", name); - } - - if (RunQuery(query, querylen, errbuf, &result)) { - ret = GetCharacterInfoForLogin_result(result, character_id, current_zone, pp, inv, ext, pplen, guilddbid, guildrank, class_, level, LFP, LFG, NumXTargets, firstlogon); - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "GetCharacterInfoForLogin query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - #define StructDist(in, f1, f2) (uint32(&in->f2)-uint32(&in->f1)) - bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat( "SELECT " @@ -1085,6 +1015,38 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* return true; } +bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & val_list) { + std::string query = StringFormat("SELECT faction_id,current_value FROM faction_values WHERE char_id = %i", character_id); + auto results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); } + return true; +} + +bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "disc_id " + "FROM " + "`character_disciplines`" + "WHERE `id` = %u ORDER BY `disc_id`", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; } + return true; +} + +bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "skill_id, " + "`value` " + "FROM " + "`character_skills` " + "WHERE `id` = %u ORDER BY `skill_id`", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->skills[i] = atoi(row[1]); } + return true; +} + bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat( "SELECT " @@ -1458,103 +1420,6 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur return true; } -// Process results of GetCharacterInfoForLogin() -// Query this processes: SELECT id,profile,zonename,x,y,z,guild,guildrank,extprofile,class,level FROM character_ WHERE id=%i -bool ZoneDatabase::GetCharacterInfoForLogin_result(MYSQL_RES* result, - uint32* character_id, char* current_zone, PlayerProfile_Struct* pp, Inventory* inv, - ExtendedProfile_Struct *ext, uint32* pplen, uint32* guilddbid, uint8* guildrank, - uint8 *class_, uint8 *level, bool *LFP, bool *LFG, uint8 *NumXTargets, uint8* firstlogon) { - - MYSQL_ROW row; - unsigned long* lengths; - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - lengths = mysql_fetch_lengths(result); - if (pp && pplen) { - if (lengths[1] == sizeof(PlayerProfile_Struct)) { - // memcpy(pp, row[1], sizeof(PlayerProfile_Struct)); - } else { - LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetCharacterInfo Expected: %i, Got: %i", - sizeof(PlayerProfile_Struct), lengths[1]); - return false; - } - - *pplen = lengths[1]; - pp->zone_id = GetZoneID(row[2]); - pp->zoneInstance = atoi(row[13]); - - pp->x = atof(row[3]); - pp->y = atof(row[4]); - pp->z = atof(row[5]); - - pp->lastlogin = time(nullptr); - - if (pp->x == -1 && pp->y == -1 && pp->z == -1) - GetSafePoints(pp->zone_id, database.GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z); - } - - uint32 char_id = atoi(row[0]); - if (RuleB(Character, SharedBankPlat)) - pp->platinum_shared = database.GetSharedPlatinum(GetAccountIDByChar(char_id)); - if (character_id) - *character_id = char_id; - if (current_zone) - strcpy(current_zone, row[2]); - - if (guilddbid) { - if(row[6] != nullptr) - *guilddbid = atoi(row[6]); - else - *guilddbid = GUILD_NONE; - } - if (guildrank) { - if(row[7] != nullptr) - *guildrank = atoi(row[7]); - else - *guildrank = GUILD_RANK_NONE; - } - - if(ext) { - //SetExtendedProfile handles any conversion - SetExtendedProfile(ext, row[8], lengths[8]); - } - - if(class_) - *class_ = atoi(row[9]); - - if(level) - *level = atoi(row[10]); - - if(LFP) - *LFP = atoi(row[11]); - - if(LFG) - *LFG = atoi(row[12]); - - if(NumXTargets) - { - *NumXTargets = atoi(row[14]); - } - - - if(firstlogon) - { - *firstlogon = atoi(row[15]); - } - - // Fix use_tint, previously it was set to 1 for a dyed slot, client wants it set to 0xFF - for(int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) - if(pp->item_tint[i].rgb.use_tint == 1) - pp->item_tint[i].rgb.use_tint = 0xFF; - - // Retrieve character inventory - return GetInventory(char_id, inv); - } - - return false; -} - bool ZoneDatabase::NoRentExpired(const char* name){ char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; @@ -2812,31 +2677,6 @@ bool ZoneDatabase::SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz) { } //End new timezone functions. -/* - solar: this is never actually called, client_process starts an async query - instead and uses GetAccountInfoForLogin_result to process it.. - */ -bool ZoneDatabase::GetAccountInfoForLogin(uint32 account_id, int16* admin, char* account_name, uint32* lsaccountid, uint8* gmspeed, bool* revoked,bool* gmhideme) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT status, name, lsaccount_id, gmspeed, revoked, hideme FROM account WHERE id=%i", account_id), errbuf, &result)) { - safe_delete_array(query); - bool ret = GetAccountInfoForLogin_result(result, admin, account_name, lsaccountid, gmspeed, revoked,gmhideme); - mysql_free_result(result); - return ret; - } - else - { - std::cerr << "Error in GetAccountInfoForLogin query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return false; -} - void ZoneDatabase::RefreshGroupFromDB(Client *c){ if(!c){ return; @@ -3568,31 +3408,6 @@ bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race return true; } -bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map & val_list) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT faction_id,current_value FROM faction_values WHERE char_id = %i",char_id), errbuf, &result)) { - safe_delete_array(query); - bool ret = LoadFactionValues_result(result, val_list); - mysql_free_result(result); - return ret; - } - else { - std::cerr << "Error in LoadFactionValues query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } - return false; -} - -bool ZoneDatabase::LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list) { - MYSQL_ROW row; - while((row = mysql_fetch_row(result))) { - val_list[atoi(row[0])] = atoi(row[1]); - } - return true; -} - //o-------------------------------------------------------------- //| Name: GetFactionName; rembrant, Dec. 16 //o-------------------------------------------------------------- diff --git a/zone/zonedb.h b/zone/zonedb.h index d0e70b995..ce32e919f 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -249,20 +249,7 @@ public: void StoreCharacterLookup(uint32 char_id); bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs); uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs); - bool GetAccountInfoForLogin(uint32 account_id, int16* admin = 0, char* account_name = 0, - uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = 0); - bool GetAccountInfoForLogin_result(MYSQL_RES* result, int16* admin = 0, char* account_name = 0, - uint32* lsaccountid = 0, uint8* gmspeed = 0, bool* revoked = 0, bool* gmhideme = nullptr, - uint32* account_creation = 0); - bool GetCharacterInfoForLogin_result(MYSQL_RES* result, uint32* character_id = 0, char* current_zone = 0, - PlayerProfile_Struct* pp = 0, Inventory* inv = 0, ExtendedProfile_Struct *ext = 0, uint32* pplen = 0, - uint32* guilddbid = 0, uint8* guildrank = 0, uint8 *class_= 0, uint8 *level = 0, bool *LFP = 0, - bool *LFG = 0, uint8 *NumXTargets = 0, uint8* firstlogon = 0); - bool GetCharacterInfoForLogin(const char* name, uint32* character_id = 0, char* current_zone = 0, - PlayerProfile_Struct* pp = 0, Inventory* inv = 0, ExtendedProfile_Struct *ext = 0, uint32* pplen = 0, - uint32* guilddbid = 0, uint8* guildrank = 0, uint8 *class_ = 0, uint8 *level = 0, bool *LFP = 0, - bool *LFG = 0, uint8 *NumXTargets = 0, uint8* firstlogon = 0); void SaveBuffs(Client *c); void LoadBuffs(Client *c); void LoadPetInfo(Client *c); @@ -270,6 +257,9 @@ public: void RemoveTempFactions(Client *c); /* Player Profile Loaders */ + bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list); + bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); @@ -321,8 +311,6 @@ public: bool GetFactionIdsForNPC(uint32 nfl_id, std::list *faction_list, int32* primary_faction = 0); // neotokyo: improve faction handling bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001 bool LoadFactionData(); - bool LoadFactionValues(uint32 char_id, faction_map & val_list); - bool LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list); /* * AAs From ca430e24942aa3d82837be7b604ecabf85976f01 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 31 Aug 2014 17:52:43 -0500 Subject: [PATCH 06/56] Fix void Database::GetCharName(uint32 char_id, char* name) Increased MAX_PP_SPELLBOOK to 720 for UF/RoF Increased MAX_PP_MEMSPELL to 12 Implemented up to 12 spell slots Fix for public_note default value in bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) Updated all CastSpell entries to use the appropriate slot type defines located now in zone/common.h Fixed Guild Loading from character_data Fixed #guild list Refactored Merchantlist loading Refactored Temp Merchantlist loading Gutted most of dbasync Added: LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp); LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp); LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp); LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp); SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot); SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); Removed Zone::LoadTempMerchantData_result(MYSQL_RES* result) Removed Zone::LoadMerchantData_result(MYSQL_RES* result) Removed SharedDatabase::GetPlayerProfile Removed SharedDatabase::SetPlayerProfile Removed SharedDatabase::SetPlayerProfile_MQ Removed Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) from zone.cpp --- common/database.cpp | 23 +-- common/eq_packet_structs.h | 4 +- common/guild_base.cpp | 2 +- common/patches/underfoot.cpp | 3 +- common/patches/underfoot_structs.h | 3 +- common/shareddb.cpp | 100 ------------ common/shareddb.h | 3 - world/worlddb.cpp | 5 +- zone/aa.cpp | 7 +- zone/bot.h | 4 +- zone/client.cpp | 52 +++--- zone/client.h | 7 +- zone/client_packet.cpp | 254 ++++++++++++++--------------- zone/command.cpp | 6 +- zone/common.h | 4 + zone/mob.h | 2 +- zone/spells.cpp | 8 +- zone/zone.cpp | 164 ++++++------------- zone/zone.h | 3 - zone/zonedb.cpp | 250 ++++++++++++++++++---------- zone/zonedb.h | 16 +- zone/zonedbasync.cpp | 24 --- 22 files changed, 423 insertions(+), 521 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 429da0e42..fcfab3c52 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -758,17 +758,18 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID void Database::GetCharName(uint32 char_id, char* name) { - std::string query = StringFormat("SELECT name FROM character_ WHERE id='%i'", char_id); + std::string query = StringFormat("SELECT `name` FROM `character_data` WHERE id='%i'", char_id); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in GetCharName query '" << query << "' " << results.ErrorMessage() << std::endl; - return; + return; } auto row = results.begin(); - strcpy(name, row[0]); + for (auto row = results.begin(); row != results.end(); ++row) { + strcpy(name, row[0]); + } } static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { @@ -849,7 +850,7 @@ bool Database::CheckDatabaseConversions() { " `level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " " `anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " " `gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - " `intoxication` int(11) UNSIGNED NOT NULL, " + " `intoxication` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `hair_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " " `beard_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " " `eye_color_1` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " @@ -885,9 +886,9 @@ bool Database::CheckDatabaseConversions() { " `drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " - " `toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " - " `hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " - " `thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `toxicity` int(11) NOT NULL DEFAULT 0, " + " `hunger_level` int(11) NOT NULL DEFAULT 0, " + " `thirst_level` int(11) NOT NULL DEFAULT 0, " " `ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " @@ -1092,7 +1093,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 1"); + querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 100"); if (RunQuery(query, querylen, errbuf, &result)) { safe_delete_array(query); while (row = mysql_fetch_row(result)) { @@ -1147,6 +1148,8 @@ bool Database::CheckDatabaseConversions() { ); auto results = QueryDatabase(rquery); + if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } + /* Run Character Data Convert */ rquery = StringFormat( "REPLACE INTO `character_data` (" diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index d2fbcbb76..d6ffd119b 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -801,8 +801,8 @@ struct SuspendedMinion_Struct ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF -static const uint32 MAX_PP_MEMSPELL = 9; +static const uint32 MAX_PP_SPELLBOOK = 720; // Increased to 480 to support SoF +static const uint32 MAX_PP_MEMSPELL = 12; static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size static const uint32 MAX_PP_AA_ARRAY = 240; static const uint32 MAX_GROUP_MEMBERS = 6; diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 8f6144270..99e54934e 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -751,7 +751,7 @@ bool BaseGuildManager::DBSetGuild(uint32 charid, uint32 guild_id, uint8 rank) { std::string query; if(guild_id != GUILD_NONE) { - query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank) VALUES(%d,%d,%d)", charid, guild_id, rank); + query = StringFormat("REPLACE INTO guild_members (char_id,guild_id,rank,public_note) VALUES(%d,%d,%d,'')", charid, guild_id, rank); auto results = m_db->QueryDatabase(query); if (!results.Success()) { diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index bdac3c72b..1eab127d5 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -479,7 +479,6 @@ ENCODE(OP_PlayerProfile) { uint32 r; eq->available_slots=0xffffffff; - memset(eq->unknown06284, 0xff, sizeof(eq->unknown06284)); memset(eq->unknown07284, 0xff, sizeof(eq->unknown07284)); // OUT(checksum); @@ -546,7 +545,7 @@ ENCODE(OP_PlayerProfile) { OUT(gold); OUT(silver); OUT(copper); - OUT(platinum_cursor); + OUT(platinum_cursor); OUT(gold_cursor); OUT(silver_cursor); OUT(copper_cursor); diff --git a/common/patches/underfoot_structs.h b/common/patches/underfoot_structs.h index ee7286dab..860fdd34a 100644 --- a/common/patches/underfoot_structs.h +++ b/common/patches/underfoot_structs.h @@ -766,7 +766,7 @@ struct BindStruct { ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 25; // -static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Underfoot now +static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Underfoot static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size static const uint32 MAX_PP_AA_ARRAY = 300; //was 299 @@ -879,7 +879,6 @@ struct PlayerProfile_Struct /*04216*/ uint8 face; // Player face - Actually uint32? /*04217*/ uint8 unknown04217[147]; // was [175] /*04364*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920] -/*06284*/ uint8 unknown06284[960]; // Spacer for the end of the book for now (pages 60 to 90) /*07244*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized /*07284*/ uint8 unknown07284[28]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*07312*/ uint32 platinum; // Platinum Pieces on player diff --git a/common/shareddb.cpp b/common/shareddb.cpp index c10e87856..e4336b02f 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1209,106 +1209,6 @@ bool SharedDatabase::LoadNPCFactionLists() { return true; } -// Get the player profile and inventory for the given account "account_id" and -// character name "name". Return true if the character was found, otherwise false. -// False will also be returned if there is a database error. -bool SharedDatabase::GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone, uint32 *current_instance) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - unsigned long* lengths; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile,zonename,x,y,z,extprofile,instanceid FROM character_ WHERE account_id=%i AND name='%s'", account_id, name), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(PlayerProfile_Struct)) { - memcpy(pp, row[0], sizeof(PlayerProfile_Struct)); - - if (current_zone) - strcpy(current_zone, row[1]); - pp->zone_id = GetZoneID(row[1]); - pp->x = atof(row[2]); - pp->y = atof(row[3]); - pp->z = atof(row[4]); - pp->zoneInstance = atoi(row[6]); - if (pp->x == -1 && pp->y == -1 && pp->z == -1) - GetSafePoints(pp->zone_id, GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z); - - if(current_instance) - *current_instance = pp->zoneInstance; - - if(ext) { - //SetExtendedProfile handles any conversion - SetExtendedProfile(ext, row[5], lengths[5]); - } - - // Retrieve character inventory - ret = GetInventory(account_id, name, inv); - } - else { - LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetPlayerProfile. Found: %i, Expected: %i", - lengths[0], sizeof(PlayerProfile_Struct)); - } - } - - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "GetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 affected_rows = 0; - bool ret = false; - - clock_t t = std::clock(); /* Function timer start */ - if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { - ret = (affected_rows != 0); - } - LogFile->write(EQEMuLog::Status, "SharedDatabase::SetPlayerProfile SetPlayerProfile_MQ done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); - - if (!ret) { - LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -// Generate SQL for updating player profile -uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - *query = new char[396 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 4]; - char* end = *query; - if (!current_zone) - current_zone = pp->zone_id; - - if (!current_instance) - current_instance = pp->zoneInstance; - - if(strlen(pp->name) == 0) /* Sanity check in case pp never loaded */ - return false; - - end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); - end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end,"\', extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end,"\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); - - return (uint32) (end - (*query)); -} - - - // Create appropriate ItemInst class ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) { diff --git a/common/shareddb.h b/common/shareddb.h index 0fd72426c..5401bfa0a 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -40,9 +40,6 @@ public: bool SetGMSpeed(uint32 account_id, uint8 gmspeed); uint8 GetGMSpeed(uint32 account_id); bool SetHideMe(uint32 account_id, uint8 hideme); - bool GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone = 0, uint32 *current_instance = 0); - bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); - uint32 SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); int32 DeleteStalePlayerCorpses(); int32 DeleteStalePlayerBackups(); void GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 7a07c6f6f..02dfa4290 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -41,11 +41,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* MYSQL_ROW row; Inventory *inv; + /* Initialize Variables */ for (int i=0; i<10; i++) { strcpy(cs->name[i], ""); cs->zone[i] = 0; cs->level[i] = 0; - cs->tutorial[i] = 0; + cs->tutorial[i] = 0; cs->gohome[i] = 0; } @@ -165,7 +166,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* 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); + // SetPlayerProfile(account_id,char_id,pp,inv,ext, 0, 0, 5); } mysql_free_result(result2); } diff --git a/zone/aa.cpp b/zone/aa.cpp index 390174cf5..2af81a619 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -300,7 +300,7 @@ void Client::ActivateAA(aaID activate){ return; } } else { - if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { + if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { //Reset on failed cast SendAATimer(AATimerID, 0, 0xFFFFFF); Message_StringID(15,ABILITY_FAILED); @@ -525,7 +525,7 @@ void Client::HandleAAAction(aaID activate) { //cast the spell, if we have one if(IsValidSpell(spell_id)) { int aatid = GetAATimerID(activate); - if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { + if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) { SendAATimer(aatid, 0, 0xFFFFFF); Message_StringID(15,ABILITY_FAILED); p_timers.Clear(&database, pTimerAAStart + aatid); @@ -1822,8 +1822,7 @@ void ZoneDatabase::LoadAAs(SendAA_Struct **load){ } AALevelCost_Struct aalcs; - for (auto row = results.begin(); row != results.end(); ++row) - { + for (auto row = results.begin(); row != results.end(); ++row) { aalcs.Level = atoi(row[1]); aalcs.Cost = atoi(row[2]); AARequiredLevelAndCost[atoi(row[0])] = aalcs; diff --git a/zone/bot.h b/zone/bot.h index 9c1ec9cb2..7601dd00c 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -311,11 +311,11 @@ public: virtual float GetAOERange(uint16 spell_id); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr); + virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF); + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF); // Bot Action Command Methods bool MesmerizeTarget(Mob* target); diff --git a/zone/client.cpp b/zone/client.cpp index 0065d31c5..975e61dc1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -545,7 +545,7 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterCurrency(this->CharacterID(), &m_pp); /* Save Character AA */ - SaveAA(); + // SaveAA(); /* Save Character Buffs */ database.SaveBuffs(this); @@ -591,31 +591,31 @@ bool Client::Save(uint8 iCommitNow) { /* Save Character Data */ database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); - if (iCommitNow <= 1) { - char* query = 0; - uint32_breakdown workpt; - workpt.b4() = DBA_b4_Entity; - workpt.w2_3() = GetID(); - workpt.b1() = DBA_b1_Entity_Client_Save; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); - dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); - if (iCommitNow == 0){ - pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); - } - else { - dbasync->AddWork(&dbaw, 0); - SaveBackup(); - } - safe_delete_array(query); - return true; - } - else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { - SaveBackup(); - } - else { - std::cerr << "Failed to update player profile" << std::endl; - return false; - } + // if (iCommitNow <= 1) { + // char* query = 0; + // uint32_breakdown workpt; + // workpt.b4() = DBA_b4_Entity; + // workpt.w2_3() = GetID(); + // workpt.b1() = DBA_b1_Entity_Client_Save; + // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); + // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); + // if (iCommitNow == 0){ + // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); + // } + // else { + // dbasync->AddWork(&dbaw, 0); + // SaveBackup(); + // } + // safe_delete_array(query); + // return true; + // } + // else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { + // SaveBackup(); + // } + // else { + // std::cerr << "Failed to update player profile" << std::endl; + // return false; + // } /* Mirror Character Data */ database.StoreCharacterLookup(this->CharacterID()); diff --git a/zone/client.h b/zone/client.h index a490d73c4..bab48e8ea 100644 --- a/zone/client.h +++ b/zone/client.h @@ -37,6 +37,7 @@ class Client; #include "../common/item_struct.h" #include "../common/clientversions.h" +#include "common.h" #include "zonedb.h" #include "errno.h" #include "mob.h" @@ -102,11 +103,6 @@ enum { //scribing argument to MemorizeSpell memSpellSpellbar = 3 }; -#define USE_ITEM_SPELL_SLOT 10 -#define POTION_BELT_SPELL_SLOT 11 -#define DISCIPLINE_SPELL_SLOT 10 -#define ABILITY_SPELL_SLOT 9 - //Modes for the zoning state of the client. typedef enum { ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac @@ -239,7 +235,6 @@ public: void KeyRingList(); virtual bool IsClient() const { return true; } virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw); - bool FinishConnState2(DBAsyncWork* dbaw); void CompleteConnect(); bool TryStacking(ItemInst* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 9b2af6c45..9921298fe 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -506,19 +506,18 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if(strlen(cze->char_name) > 63) return; - conn_state = ReceivedZoneEntry; - + conn_state = ReceivedZoneEntry; ClientVersion = Connection()->ClientVersion(); ClientVersionBit = 1 << (ClientVersion - 1); - // Antighost code - // tmp var is so the search doesnt find this object + /* Antighost code + tmp var is so the search doesnt find this object + */ Client* client = entity_list.GetClientByName(cze->char_name); if (!zone->GetAuth(ip, cze->char_name, &WID, &account_id, &character_id, &admin, lskey, &tellsoff)) { LogFile->write(EQEMuLog::Error, "GetAuth() returned false kicking client"); - if (client != 0) - { + if (client != 0) { client->Save(); client->Kick(); } @@ -527,7 +526,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) return; } + strcpy(name, cze->char_name); + /* Check for Client Spoofing */ if (client != 0) { struct in_addr ghost_addr; ghost_addr.s_addr = eqs->GetRemoteIP(); @@ -554,8 +555,10 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) uint32 cid = CharacterID(); character_id = cid; + /* Flush and reload factions */ database.RemoveTempFactions(this); database.LoadCharacterFactionValues(cid, factionvalues); + /* Load Character Account Data: Temp until I move */ query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %i", this->AccountID()); auto results = database.QueryDatabase(query); @@ -565,74 +568,75 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (lsaccountid && atoi(row[2]) > 0){ lsaccountid = atoi(row[2]); } else{ lsaccountid = 0; } if (gmspeed){ gmspeed = atoi(row[3]); } - if (revoked){ revoked = atoi(row[4]); } + if (revoked){ revoked = atoi(row[4]); } if (gmhideme){ gmhideme = atoi(row[5]); } if (account_creation){ account_creation = atoul(row[6]); } } + /* Load Character Legacy Data: Temp until I move */ - query = StringFormat("id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", cid); + query = StringFormat("SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", cid); results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { m_pp.lastlogin = time(nullptr); - + if (row[6]){ + guild_id = atoi(row[6]); + if (guildrank) { + if (row[7] != nullptr){ guildrank = atoi(row[7]); } + else{ guildrank = GUILD_RANK_NONE; } + } + } if (RuleB(Character, SharedBankPlat)) m_pp.platinum_shared = database.GetSharedPlatinum(database.GetAccountIDByChar(cid)); - if (guildrank) { - if (row[7] != nullptr) - guildrank = atoi(row[7]); - else - guildrank = GUILD_RANK_NONE; - } // if (ext) { SetExtendedProfile(ext, row[8], lengths[8]); } if (level){ level = atoi(row[10]); } if (LFP){ LFP = atoi(row[11]); } if (LFG){ LFG = atoi(row[12]); } if (firstlogon){ firstlogon = atoi(row[15]); } } - /* Load Character Inventory */ - loaditems = database.GetInventory(cid, &m_inv); - /* Load Character Currency into PP */ - database.LoadCharacterCurrency(cid, &m_pp); - /* Load Character Data from DB into PP */ - database.LoadCharacterData(cid, &m_pp); - /* Move to another method when can, this is pointless... */ - database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); - /* Load Character Currency */ - database.LoadCharacterCurrency(cid, &m_pp); - /* Load Character Skills */ - database.LoadCharacterSkills(cid, &m_pp); - /* Load Character Disciplines */ - database.LoadCharacterDisciplines(cid, &m_pp); + + loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ + database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ + 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... */ + database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency */ + database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */ + database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ + database.LoadCharacterSpellBook(cid, &m_pp); /* Load Character Spell Book */ + database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */ + database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */ + /* If GM, not trackable */ if (gmhideme) { trackable = false; } - + /* Set Con State for Reporting */ conn_state = PlayerProfileLoaded; - - /* Set Current zone */ + // m_pp.zone_id = zone->GetZoneID(); // m_pp.zoneInstance = zone->GetInstanceID(); + /* Set Total Seconds Played */ TotalSecondsPlayed = m_pp.timePlayedMin * 60; - + /* Set Max AA XP */ max_AAXP = RuleI(AA, ExpPerPoint); - + /* If we can maintain intoxication across zones, check for it */ if (!RuleB(Character, MaintainIntoxicationAcrossZones)) - m_pp.intoxication = 0; - + m_pp.intoxication = 0; + strcpy(name, m_pp.name); + strcpy(lastname, m_pp.last_name); + /* If PP is set to wierd coordinates */ if ((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1) || (m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) { m_pp.x = zone->safe_x(); m_pp.y = zone->safe_y(); m_pp.z = zone->safe_z(); - } - + } /* If too far below ground, then fix */ float ground_z = GetGroundZ(m_pp.x, m_pp.y, m_pp.z); if (m_pp.z < (ground_z - 500)) m_pp.z = ground_z; - class_ = m_pp.class_; - + /* Set Mob variables for spawn */ + class_ = m_pp.class_; level = m_pp.level; x_pos = m_pp.x; y_pos = m_pp.y; @@ -642,7 +646,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) base_race = m_pp.race; gender = m_pp.gender; base_gender = m_pp.gender; - deity = m_pp.deity; //FYI: DEITY_AGNOSTIC = 396; still valid? + deity = m_pp.deity; haircolor = m_pp.haircolor; beardcolor = m_pp.beardcolor; eyecolor1 = m_pp.eyecolor1; @@ -654,42 +658,41 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) drakkin_tattoo = m_pp.drakkin_tattoo; drakkin_details = m_pp.drakkin_details; + /* If GM not set in DB, and does not meet min status to be GM, reset */ if (m_pp.gm && admin < minStatusToBeGM) m_pp.gm = 0; /* Load Guild */ if (!IsInAGuild()) { m_pp.guild_id = GUILD_NONE; } else { - m_pp.guild_id = GuildID(); - + m_pp.guild_id = GuildID(); if (zone->GetZoneID() == RuleI(World, GuildBankZoneID)) GuildBanker = (guild_mgr.IsGuildLeader(GuildID(), CharacterID()) || guild_mgr.GetBankerFlag(CharacterID())); } - m_pp.guildbanker = GuildBanker; switch (race) { - case OGRE: - size = 9; break; - case TROLL: - size = 8; break; - case VAHSHIR: case BARBARIAN: - size = 7; break; - case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN: - size = 6; break; - case HALF_ELF: - size = 5.5; break; - case WOOD_ELF: case DARK_ELF: case FROGLOK: - size = 5; break; - case DWARF: - size = 4; break; - case HALFLING: - size = 3.5; break; - case GNOME: - size = 3; break; - default: - size = 0; + case OGRE: + size = 9; break; + case TROLL: + size = 8; break; + case VAHSHIR: case BARBARIAN: + size = 7; break; + case HUMAN: case HIGH_ELF: case ERUDITE: case IKSAR: case DRAKKIN: + size = 6; break; + case HALF_ELF: + size = 5.5; break; + case WOOD_ELF: case DARK_ELF: case FROGLOK: + size = 5; break; + case DWARF: + size = 4; break; + case HALFLING: + size = 3.5; break; + case GNOME: + size = 3; break; + default: + size = 0; } /* Check for Invalid points */ @@ -700,6 +703,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } + /* Set Swimming Skill 100 by default if under 100 */ if (GetSkill(SkillSwimming) < 100) SetSkill(SkillSwimming, 100); @@ -859,29 +863,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) Mob::SetMana(m_pp.mana); SetEndurance(m_pp.endurance); - if (IsLFP()) { - // Update LFP in case any (or all) of our group disbanded while we were zoning. - UpdateLFP(); - } - - if (m_pp.z <= zone->newzone_data.underworld) { - m_pp.x = zone->newzone_data.safe_x; - m_pp.y = zone->newzone_data.safe_y; - m_pp.z = zone->newzone_data.safe_z; - } + /* Update LFP in case any (or all) of our group disbanded while we were zoning. */ + if (IsLFP()) { UpdateLFP(); } /* Get Expansions from variables table and ship via PP */ char val[20] = { 0 }; - if (database.GetVariable("Expansions", val, 20)) - m_pp.expansions = atoi(val); - else - m_pp.expansions = 0x3FF; + if (database.GetVariable("Expansions", val, 20)){ m_pp.expansions = atoi(val); } + else{ m_pp.expansions = 0x3FF; } p_timers.SetCharID(CharacterID()); if (!p_timers.Load(&database)) { LogFile->write(EQEMuLog::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID()); } + /* Load Spell Slot Refresh from Currently Memoried Spells */ for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) if (IsValidSpell(m_pp.mem_spells[i])) m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000; @@ -904,14 +899,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_inv.dumpEntireInventory(); #endif - //lost in current PP - // strcpy(m_pp.servername,"eqemulator"); - - m_pp.air_remaining = 60; //Reset to max so they dont drown on zone in if its underwater - + /* Reset to max so they dont drown on zone in if its underwater */ + m_pp.air_remaining = 60; + /* Check for PVP Zone status*/ if (zone->IsPVPZone()) m_pp.pvp = 1; - + /* Time entitled on Account: Move to account */ m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; /* Reset rest timer if the durations have been lowered in the database */ @@ -934,9 +927,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadPetInfo(this); /* - This was moved before the spawn packets are sent - in hopes that it adds more consistency... - Remake pet + This was moved before the spawn packets are sent + in hopes that it adds more consistency... + Remake pet */ if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { @@ -985,16 +978,15 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* - Character Inventory Packet - this is not quite where live sends inventory, they do it after tribute + Character Inventory Packet + this is not quite where live sends inventory, they do it after tribute */ - if (loaditems) { //dont load if a length error occurs + if (loaditems) { /* Dont load if a length error occurs */ BulkSendInventoryItems(); - - // Send stuff on the cursor which isnt sent in bulk + /* Send stuff on the cursor which isnt sent in bulk */ iter_queue it; for (it = m_inv.cursor_begin(); it != m_inv.cursor_end(); ++it) { - // First item cursor is sent in bulk inventory packet + /* First item cursor is sent in bulk inventory packet */ if (it == m_inv.cursor_begin()) continue; const ItemInst *inst = *it; @@ -1005,15 +997,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Task Packets */ LoadClientTaskState(); - if (GetClientVersion() >= EQClientRoF) - { + if (GetClientVersion() >= EQClientRoF) { outapp = new EQApplicationPacket(OP_ReqNewZone, 0); Handle_Connect_OP_ReqNewZone(outapp); safe_delete(outapp); } - if (ClientVersionBit & BIT_UnderfootAndLater) - { + if (ClientVersionBit & BIT_UnderfootAndLater) { outapp = new EQApplicationPacket(OP_XTargetResponse, 8); outapp->WriteUInt32(GetMaxXTargets()); outapp->WriteUInt32(0); @@ -1021,17 +1011,16 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* - Weather Packet - This shouldent be moved, this seems to be what the client - uses to advance to the next state (sending ReqNewZone) + Weather Packet + This shouldent be moved, this seems to be what the client + uses to advance to the next state (sending ReqNewZone) */ outapp = new EQApplicationPacket(OP_Weather, 12); Weather_Struct *ws = (Weather_Struct *)outapp->pBuffer; ws->val1 = 0x000000FF; if (zone->zone_weather == 1) ws->type = 0x31; // Rain - if (zone->zone_weather == 2) - { + if (zone->zone_weather == 2) { outapp->pBuffer[8] = 0x01; ws->type = 0x02; } @@ -2585,7 +2574,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if(i == 0) { - CastSpell(item->Click.Effect, target_id, 10, item->CastTime, 0, 0, slot_id); + CastSpell(item->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, item->CastTime, 0, 0, slot_id); } } else @@ -2612,7 +2601,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if(i == 0) { - CastSpell(augitem->Click.Effect, target_id, 10, augitem->CastTime, 0, 0, slot_id); + CastSpell(augitem->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, augitem->CastTime, 0, 0, slot_id); } } else @@ -4947,6 +4936,7 @@ void Client::Handle_OP_MemorizeSpell(const EQApplicationPacket *app) void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app) { + if (app->size != sizeof(SwapSpell_Struct)) { std::cout << "Wrong size on OP_SwapSpell. Got: " << app->size << ", Expected: " << sizeof(SwapSpell_Struct) << std::endl; return; @@ -4958,8 +4948,13 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app) return; swapspelltemp = m_pp.spell_book[swapspell->from_slot]; + if (swapspelltemp < 0){ + return; + } m_pp.spell_book[swapspell->from_slot] = m_pp.spell_book[swapspell->to_slot]; m_pp.spell_book[swapspell->to_slot] = swapspelltemp; + + database.SaveCharacterSpellSwap(this->CharacterID(), swapspelltemp, swapspell->from_slot, swapspell->to_slot); QueuePacket(app); return; @@ -4991,7 +4986,27 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) #endif LogFile->write(EQEMuLog::Debug, "OP CastSpell: slot=%d, spell=%d, target=%d, inv=%lx", castspell->slot, castspell->spell_id, castspell->target_id, (unsigned long)castspell->inventoryslot); - if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // ITEM or POTION cast + std::cout << "OP_CastSpell " << castspell->slot << " spell " << castspell->spell_id << " inventory slot " << castspell->inventoryslot << "\n" << std::endl; + + /* Memorized Spell */ + if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id){ + uint16 spell_to_cast = 0; + if (castspell->slot < MAX_PP_MEMSPELL) { + spell_to_cast = m_pp.mem_spells[castspell->slot]; + if (spell_to_cast != castspell->spell_id) { + InterruptSpell(castspell->spell_id); //CHEATER!!! + return; + } + } + else if (castspell->slot >= MAX_PP_MEMSPELL) { + InterruptSpell(); + return; + } + + CastSpell(spell_to_cast, castspell->target_id, castspell->slot); + } + /* Spell Slot or Potion Belt Slot */ + else if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)) // ITEM or POTION cast { //discipline, using the item spell slot if (castspell->inventoryslot == 0xFFFFFFFF) { @@ -5070,14 +5085,16 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) InterruptSpell(castspell->spell_id); } } - else if (castspell->slot == DISCIPLINE_SPELL_SLOT) { // DISCIPLINE cast + /* Discipline */ + else if (castspell->slot == DISCIPLINE_SPELL_SLOT) { if (!UseDiscipline(castspell->spell_id, castspell->target_id)) { printf("Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id); InterruptSpell(castspell->spell_id); return; } } - else if (castspell->slot == ABILITY_SPELL_SLOT) { // ABILITY cast (LoH and Harm Touch) + /* ABILITY cast (LoH and Harm Touch) */ + else if (castspell->slot == ABILITY_SPELL_SLOT) { uint16 spell_to_cast = 0; if (castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == PALADIN) { @@ -5109,26 +5126,6 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) if (spell_to_cast > 0) // if we've matched LoH or HT, cast now CastSpell(spell_to_cast, castspell->target_id, castspell->slot); } - else // MEMORIZED SPELL (first confirm that it's a valid memmed spell slot, then validate that the spell is currently memorized) - { - uint16 spell_to_cast = 0; - - if(castspell->slot < MAX_PP_MEMSPELL) - { - spell_to_cast = m_pp.mem_spells[castspell->slot]; - if(spell_to_cast != castspell->spell_id) - { - InterruptSpell(castspell->spell_id); //CHEATER!!! - return; - } - } - else if (castspell->slot >= MAX_PP_MEMSPELL) { - InterruptSpell(); - return; - } - - CastSpell(spell_to_cast, castspell->target_id, castspell->slot); - } return; } @@ -9224,8 +9221,7 @@ void Client::CompleteConnect() { SendAppearancePacket(AT_GuildID, GuildID(), false); SendAppearancePacket(AT_GuildRank, GuildRank(), false); } - for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++) - { + for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++) { if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000) m_pp.spell_book[spellInt] = 0xFFFFFFFF; } diff --git a/zone/command.cpp b/zone/command.cpp index 011cb0f09..b1d195bf4 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2491,14 +2491,14 @@ void command_castspell(Client *c, const Seperator *sep) else if (c->GetTarget() == 0) if(c->Admin() >= commandInstacast) - c->SpellFinished(spellid, 0, 10, 0, -1, spells[spellid].ResistDiff); + c->SpellFinished(spellid, 0, USE_ITEM_SPELL_SLOT, 0, -1, spells[spellid].ResistDiff); else - c->CastSpell(spellid, 0, 10, 0); + c->CastSpell(spellid, 0, USE_ITEM_SPELL_SLOT, 0); else if(c->Admin() >= commandInstacast) c->SpellFinished(spellid, c->GetTarget(), 10, 0, -1, spells[spellid].ResistDiff); else - c->CastSpell(spellid, c->GetTarget()->GetID(), 10, 0); + c->CastSpell(spellid, c->GetTarget()->GetID(), USE_ITEM_SPELL_SLOT, 0); } } diff --git a/zone/common.h b/zone/common.h index 1401af860..0dbb68e0b 100644 --- a/zone/common.h +++ b/zone/common.h @@ -17,6 +17,10 @@ #define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC()) #define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC()) +#define USE_ITEM_SPELL_SLOT 10 +#define POTION_BELT_SPELL_SLOT 11 +#define DISCIPLINE_SPELL_SLOT 10 +#define ABILITY_SPELL_SLOT 9 //LOS Parameters: #define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from diff --git a/zone/mob.h b/zone/mob.h index 55a57892b..51439cfee 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -205,7 +205,7 @@ public: void SendSpellBarEnable(uint16 spellid); void ZeroCastingVars(); virtual void SpellProcess(); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, + virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr); virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, diff --git a/zone/spells.cpp b/zone/spells.cpp index 357fafbd4..94921c685 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4843,6 +4843,8 @@ void Client::MemSpell(uint16 spell_id, int slot, bool update_client) m_pp.mem_spells[slot] = spell_id; mlog(CLIENT__SPELLS, "Spell %d memorized into slot %d", spell_id, slot); + database.SaveCharacterMemorizedSpell(this->CharacterID(), m_pp.mem_spells[slot], slot); + if(update_client) { MemorizeSpell(slot, spell_id, memSpellMemorize); @@ -4857,6 +4859,8 @@ void Client::UnmemSpell(int slot, bool update_client) mlog(CLIENT__SPELLS, "Spell %d forgotten from slot %d", m_pp.mem_spells[slot], slot); m_pp.mem_spells[slot] = 0xFFFFFFFF; + database.DeleteCharacterMemorizedSpell(this->CharacterID(), m_pp.mem_spells[slot], slot); + if(update_client) { MemorizeSpell(slot, m_pp.mem_spells[slot], memSpellForget); @@ -4884,6 +4888,7 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client) } m_pp.spell_book[slot] = spell_id; + database.SaveCharacterSpell(this->CharacterID(), spell_id, slot); mlog(CLIENT__SPELLS, "Spell %d scribed into spell book slot %d", spell_id, slot); if(update_client) @@ -4899,7 +4904,8 @@ void Client::UnscribeSpell(int slot, bool update_client) mlog(CLIENT__SPELLS, "Spell %d erased from spell book slot %d", m_pp.spell_book[slot], slot); m_pp.spell_book[slot] = 0xFFFFFFFF; - + + database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[slot], slot); if(update_client) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct)); diff --git a/zone/zone.cpp b/zone/zone.cpp index 8f4b211d8..a9c63b22f 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -401,40 +401,33 @@ uint32 Zone::GetTempMerchantQuantity(uint32 NPCID, uint32 Slot) { void Zone::LoadTempMerchantData(){ LogFile->write(EQEMuLog::Status, "Loading Temporary Merchant Lists..."); - - char* query = 0; - uint32_breakdown workpt; - workpt.b4() = DBA_b4_Zone; - workpt.w2_3() = 0; - workpt.b1() = DBA_b1_Zone_MerchantListsTemp; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read); - dbaw->AddQuery(1, &query, MakeAnyLenString(&query, - "select ml.npcid,ml.slot,ml.itemid,ml.charges " - "from " - " merchantlist_temp ml, " - " spawnentry se, " - " spawn2 s2 " - "where " - " ml.npcid=se.npcid " - " and se.spawngroupid=s2.spawngroupid " - " and s2.zone='%s' and s2.version=%u", GetShortName(), GetInstanceVersion())); - if (!(pQueuedMerchantsWorkID = dbasync->AddWork(&dbaw))) { - safe_delete(dbaw); - LogFile->write(EQEMuLog::Error, "dbasync->AddWork() failed adding merchant list query"); + std::string query = StringFormat( + "SELECT " + "ml.npcid, " + "ml.slot, " + "ml.charges, " + "ml.itemid " + "FROM " + "merchantlist_temp ml, " + "spawnentry se, " + "spawn2 s2 " + "WHERE " + "ml.npcid = se.npcid " + "AND se.spawngroupid = s2.spawngroupid " + "AND s2.zone = '%s' AND s2.version = %i", GetShortName(), GetInstanceVersion()); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogFile->write(EQEMuLog::Error, "Error in LoadTempMerchantData query '%s' %s", query.c_str(), results.ErrorMessage().c_str()); return; } -} - -void Zone::LoadTempMerchantData_result(MYSQL_RES* result) { - MYSQL_ROW row; - std::map >::iterator cur; + std::map >::iterator cur; uint32 npcid = 0; - while((row = mysql_fetch_row(result))) { + for (auto row = results.begin(); row != results.end(); ++row) { TempMerchantList ml; ml.npcid = atoul(row[0]); - if(npcid != ml.npcid){ + if (npcid != ml.npcid){ cur = tmpmerchanttable.find(ml.npcid); - if(cur == tmpmerchanttable.end()) { + if (cur == tmpmerchanttable.end()) { std::list empty; tmpmerchanttable[ml.npcid] = empty; cur = tmpmerchanttable.find(ml.npcid); @@ -447,9 +440,9 @@ void Zone::LoadTempMerchantData_result(MYSQL_RES* result) { ml.origslot = ml.slot; cur->second.push_back(ml); } + pQueuedMerchantsWorkID = 0; } -//there should prolly be a temp counterpart of this... void Zone::LoadNewMerchantData(uint32 merchantid){ std::list merlist; @@ -476,16 +469,35 @@ void Zone::LoadNewMerchantData(uint32 merchantid){ merchanttable[merchantid] = merlist; } -void Zone::LoadMerchantData_result(MYSQL_RES* result) { - MYSQL_ROW row; - std::map >::iterator cur; +void Zone::GetMerchantDataForZoneLoad(){ + LogFile->write(EQEMuLog::Status, "Loading Merchant Lists..."); + std::string query = StringFormat( + "SELECT " + "ml.merchantid, " + "ml.slot, " + "ml.item, " + "ml.faction_required, " + "ml.level_required, " + "ml.alt_currency_cost, " + "ml.classes_required, " + "ml.probability " + "FROM " + "merchantlist AS ml, " + "npc_types AS nt, " + "spawnentry AS se, " + "spawn2 AS s2 " + "WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid " + "AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i ", GetShortName(), GetInstanceVersion()); + auto results = database.QueryDatabase(query); + std::map >::iterator cur; uint32 npcid = 0; - while((row = mysql_fetch_row(result))) { + if (results.RowCount() == 0){ LogFile->write(EQEMuLog::Error, "Error in loading Merchant Data for zone"); return; } + for (auto row = results.begin(); row != results.end(); ++row) { MerchantList ml; ml.id = atoul(row[0]); - if(npcid != ml.id){ + if (npcid != ml.id){ cur = merchanttable.find(ml.id); - if(cur == merchanttable.end()) { + if (cur == merchanttable.end()) { std::list empty; merchanttable[ml.id] = empty; cur = merchanttable.find(ml.id); @@ -495,15 +507,15 @@ void Zone::LoadMerchantData_result(MYSQL_RES* result) { std::list::iterator iter = cur->second.begin(); bool found = false; - while(iter != cur->second.end()) { - if((*iter).item == ml.id) { + while (iter != cur->second.end()) { + if ((*iter).item == ml.id) { found = true; break; } ++iter; } - if(found) { + if (found) { continue; } @@ -516,28 +528,7 @@ void Zone::LoadMerchantData_result(MYSQL_RES* result) { ml.probability = atoul(row[7]); cur->second.push_back(ml); } -} -void Zone::GetMerchantDataForZoneLoad(){ - LogFile->write(EQEMuLog::Status, "Loading Merchant Lists..."); - char* query = 0; - uint32_breakdown workpt; - workpt.b4() = DBA_b4_Zone; - workpt.w2_3() = 0; - workpt.b1() = DBA_b1_Zone_MerchantLists; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Read); - dbaw->AddQuery(1, &query, MakeAnyLenString(&query, - "select ml.merchantid,ml.slot,ml.item,ml.faction_required,ml.level_required,ml.alt_currency_cost,ml.classes_required,ml.probability " - "from merchantlist ml, npc_types nt, spawnentry se, spawn2 s2 " - "where nt.merchant_id=ml.merchantid and nt.id=se.npcid " - "and se.spawngroupid=s2.spawngroupid and s2.zone='%s' and s2.version=%u " - //"group by ml.merchantid,slot order by merchantid,slot asc" //this made the query use a temp table/filesort (very slow)... so we handle unsorted data on our end. - , GetShortName(), GetInstanceVersion())); - if (!(pQueuedMerchantsWorkID = dbasync->AddWork(&dbaw))) { - safe_delete(dbaw); - LogFile->write(EQEMuLog::Error,"dbasync->AddWork() failed adding merchant list query"); - return; - } } void Zone::LoadMercTemplates(){ @@ -663,61 +654,6 @@ void Zone::LoadMercSpells(){ } -void Zone::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { -// LogFile->write(EQEMuLog::Debug, "Zone work complete..."); - switch (workpt_b1) { - case DBA_b1_Zone_MerchantLists: { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* result = 0; - DBAsyncQuery* dbaq = dbaw->PopAnswer(); - if(dbaq == nullptr) { - LogFile->write(EQEMuLog::Error, "nullptr answer provided for async merchant list load."); - break; - } - if(!dbaq->GetAnswer(errbuf, &result)) { - LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unable to get results for merchant lists"); - break; - } - if(dbaq->QPT() != 1) { - LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Invalid query part for merchant lists"); - break; - } - - LoadMerchantData_result(result); - - pQueuedMerchantsWorkID = 0; - break; - } - case DBA_b1_Zone_MerchantListsTemp: { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* result = 0; - DBAsyncQuery* dbaq = dbaw->PopAnswer(); - if(dbaq == nullptr) { - LogFile->write(EQEMuLog::Error, "nullptr answer provided for async temp merchant list load."); - break; - } - if(!dbaq->GetAnswer(errbuf, &result)) { - LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unable to get results for temp merchant lists"); - break; - } - if(dbaq->QPT() != 1) { - LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Invalid query part for temp merchant lists"); - break; - } - - LoadTempMerchantData_result(result); - - pQueuedMerchantsWorkID = 0; - break; - } - - default: { - LogFile->write(EQEMuLog::Error, "Zone::DBAWComplete(): Unknown workpt_b1"); - break; - } - } -} - bool Zone::IsLoaded() { return ZoneLoaded; } diff --git a/zone/zone.h b/zone/zone.h index 77132124e..9ad692fa0 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -166,7 +166,6 @@ public: void SetStaticZone(bool sz) { staticzone = sz; } inline bool IsStaticZone() { return staticzone; } inline void GotCurTime(bool time) { gottime = time; } - void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw); void SpawnConditionChanged(const SpawnCondition &c, int16 old_value); @@ -174,8 +173,6 @@ public: void LoadNewMerchantData(uint32 merchantid); void LoadTempMerchantData(); uint32 GetTempMerchantQuantity(uint32 NPCID, uint32 Slot); - void LoadTempMerchantData_result(MYSQL_RES* result); - void LoadMerchantData_result(MYSQL_RES* result); int SaveTempItem(uint32 merchantid, uint32 npcid, uint32 item, int32 charges, bool sold=false); void LoadMercTemplates(); void LoadMercSpells(); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 4eb0e64ab..09aa26bc8 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1022,6 +1022,45 @@ bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & return true; } +bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "slot_id, " + "`spell_id` " + "FROM " + "`character_memmed_spells` " + "WHERE `id` = %u ORDER BY `slot_id`", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->mem_spells[i] = atoi(row[1]); } + return true; +} + +bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "slot_id, " + "`spell_id` " + "FROM " + "`character_spells` " + "WHERE `id` = %u ORDER BY `slot_id`", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->spell_book[i] = atoi(row[1]); } + return true; +} + +bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "SELECT " + "lang_id, " + "`value` " + "FROM " + "`character_languages` " + "WHERE `id` = %u ORDER BY `language_id`", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->languages[i] = atoi(row[1]); } + return true; +} + bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat( "SELECT " @@ -1092,8 +1131,23 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru return true; } +bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT id, zone_id, instance_id, x, y, z, heading FROM character_bind_home WHERE `id` = %u", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + pp->binds[4].zoneId = atoi(row[i]); i++; + i++; /* Instance ID can go here eventually */ + pp->binds[4].x = atoi(row[i]); i++; + pp->binds[4].y = atoi(row[i]); i++; + pp->binds[4].z = atoi(row[i]); i++; + pp->binds[4].heading = atoi(row[i]); i++; + } + 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; } std::string query = StringFormat( "REPLACE INTO `character_data` (" " id, " @@ -1187,96 +1241,96 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla " guild_auto_consent, " " RestTimer) " "VALUES (" - "%i," // id " id, " - "%i," // account_id " account_id, " + "%u," // id " id, " + "%u," // account_id " account_id, " "'%s'," // `name` pp->name, " `name`, " "'%s'," // last_name pp->last_name, " last_name, " - "%i," // gender pp->gender, " gender, " - "%i," // race pp->race, " race, " - "%i," // class pp->class_, " class, " - "%i," // `level` pp->level, " `level`, " - "%i," // deity pp->deity, " deity, " - "%i," // birthday pp->birthday, " birthday, " - "%i," // last_login pp->lastlogin, " last_login, " - "%i," // time_played pp->timePlayedMin, " time_played, " - "%i," // pvp_status pp->pvp, " pvp_status, " - "%i," // level2 pp->level2, " level2, " - "%i," // anon pp->anon, " anon, " - "%i," // gm pp->gm, " gm, " - "%i," // intoxication pp->intoxication, " intoxication, " - "%i," // hair_color pp->haircolor, " hair_color, " - "%i," // beard_color pp->beardcolor, " beard_color, " - "%i," // eye_color_1 pp->eyecolor1, " eye_color_1, " - "%i," // eye_color_2 pp->eyecolor2, " eye_color_2, " - "%i," // hair_style pp->hairstyle, " hair_style, " - "%i," // beard pp->beard, " beard, " - "%i," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " - "%i," // ability_number pp->ability_number, " ability_number, " - "%i," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " - "%i," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " + "%u," // gender pp->gender, " gender, " + "%u," // race pp->race, " race, " + "%u," // class pp->class_, " class, " + "%u," // `level` pp->level, " `level`, " + "%u," // deity pp->deity, " deity, " + "%u," // birthday pp->birthday, " birthday, " + "%u," // last_login pp->lastlogin, " last_login, " + "%u," // time_played pp->timePlayedMin, " time_played, " + "%u," // pvp_status pp->pvp, " pvp_status, " + "%u," // level2 pp->level2, " level2, " + "%u," // anon pp->anon, " anon, " + "%u," // gm pp->gm, " gm, " + "%u," // intoxication pp->intoxication, " intoxication, " + "%u," // hair_color pp->haircolor, " hair_color, " + "%u," // beard_color pp->beardcolor, " beard_color, " + "%u," // eye_color_1 pp->eyecolor1, " eye_color_1, " + "%u," // eye_color_2 pp->eyecolor2, " eye_color_2, " + "%u," // hair_style pp->hairstyle, " hair_style, " + "%u," // beard pp->beard, " beard, " + "%u," // ability_time_seconds pp->ability_time_seconds, " ability_time_seconds, " + "%u," // ability_number pp->ability_number, " ability_number, " + "%u," // ability_time_minutes pp->ability_time_minutes, " ability_time_minutes, " + "%u," // ability_time_hours pp->ability_time_hours, " ability_time_hours, " "'%s'," // title pp->title, " title, " " "'%s'," // suffix pp->suffix, " suffix, " - "%i," // exp pp->exp, " exp, " - "%i," // points pp->points, " points, " - "%i," // mana pp->mana, " mana, " - "%i," // cur_hp pp->cur_hp, " cur_hp, " - "%i," // str pp->STR, " str, " - "%i," // sta pp->STA, " sta, " - "%i," // cha pp->CHA, " cha, " - "%i," // dex pp->DEX, " dex, " - "%i," // `int` pp->INT, " `int`, " - "%i," // agi pp->AGI, " agi, " - "%i," // wis pp->WIS, " wis, " - "%i," // face pp->face, " face, " + "%u," // exp pp->exp, " exp, " + "%u," // points pp->points, " points, " + "%u," // mana pp->mana, " mana, " + "%u," // cur_hp pp->cur_hp, " cur_hp, " + "%u," // str pp->STR, " str, " + "%u," // sta pp->STA, " sta, " + "%u," // cha pp->CHA, " cha, " + "%u," // dex pp->DEX, " dex, " + "%u," // `int` pp->INT, " `int`, " + "%u," // agi pp->AGI, " agi, " + "%u," // wis pp->WIS, " wis, " + "%u," // face pp->face, " face, " "%f," // y pp->y, " y, " "%f," // x pp->x, " x, " "%f," // z pp->z, " z, " "%f," // heading pp->heading, " heading, " - "%i," // pvp2 pp->pvp2, " pvp2, " - "%i," // pvp_type pp->pvptype, " pvp_type, " - "%i," // autosplit_enabled pp->autosplit, " autosplit_enabled, " - "%i," // zone_change_count pp->zone_change_count, " zone_change_count, " - "%i," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " - "%i," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " - "%i," // drakkin_details pp->drakkin_details, " drakkin_details, " + "%u," // pvp2 pp->pvp2, " pvp2, " + "%u," // pvp_type pp->pvptype, " pvp_type, " + "%u," // autosplit_enabled pp->autosplit, " autosplit_enabled, " + "%u," // zone_change_count pp->zone_change_count, " zone_change_count, " + "%u," // drakkin_heritage pp->drakkin_heritage, " drakkin_heritage, " + "%u," // drakkin_tattoo pp->drakkin_tattoo, " drakkin_tattoo, " + "%u," // drakkin_details pp->drakkin_details, " drakkin_details, " "%i," // toxicity pp->toxicity, " toxicity, " "%i," // hunger_level pp->hunger_level, " hunger_level, " "%i," // thirst_level pp->thirst_level, " thirst_level, " - "%i," // ability_up pp->ability_up, " ability_up, " - "%i," // zone_id pp->zone_id, " zone_id, " - "%i," // zone_instance pp->zoneInstance, " zone_instance, " - "%i," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " - "%i," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " - "%i," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " - "%i," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " - "%i," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " - "%i," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " - "%i," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " - "%i," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " - "%i," // show_helm pp->showhelm, " show_helm, " - "%i," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " - "%i," // tribute_points pp->tribute_points, " tribute_points, " - "%i," // tribute_active pp->tribute_active, " tribute_active, " - "%i," // endurance pp->endurance, " endurance, " - "%i," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " - "%i," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " - "%i," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " - "%i," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " - "%i," // air_remaining pp->air_remaining, " air_remaining, " - "%i," // pvp_kills pp->PVPKills, " pvp_kills, " - "%i," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " - "%i," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " - "%i," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " - "%i," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " - "%i," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " - "%i," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " - "%i," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " - "%i," // aa_exp pp->expAA, " aa_exp, " - "%i," // aa_points pp->aapoints, " aa_points, " - "%i," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " - "%i," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " - "%i," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " - "%i" // RestTimer pp->RestTimer, " RestTimer) " + "%u," // ability_up pp->ability_up, " ability_up, " + "%u," // zone_id pp->zone_id, " zone_id, " + "%u," // zone_instance pp->zoneInstance, " zone_instance, " + "%u," // leadership_exp_on pp->leadAAActive, " leadership_exp_on, " + "%u," // ldon_points_guk pp->ldon_points_guk, " ldon_points_guk, " + "%u," // ldon_points_mir pp->ldon_points_mir, " ldon_points_mir, " + "%u," // ldon_points_mmc pp->ldon_points_mmc, " ldon_points_mmc, " + "%u," // ldon_points_ruj pp->ldon_points_ruj, " ldon_points_ruj, " + "%u," // ldon_points_tak pp->ldon_points_tak, " ldon_points_tak, " + "%u," // ldon_points_available pp->ldon_points_available, " ldon_points_available, " + "%u," // tribute_time_remaining pp->tribute_time_remaining, " tribute_time_remaining, " + "%u," // show_helm pp->showhelm, " show_helm, " + "%u," // career_tribute_points pp->career_tribute_points, " career_tribute_points, " + "%u," // tribute_points pp->tribute_points, " tribute_points, " + "%u," // tribute_active pp->tribute_active, " tribute_active, " + "%u," // endurance pp->endurance, " endurance, " + "%u," // group_leadership_exp pp->group_leadership_exp, " group_leadership_exp, " + "%u," // raid_leadership_exp pp->raid_leadership_exp, " raid_leadership_exp, " + "%u," // group_leadership_points pp->group_leadership_points, " group_leadership_points, " + "%u," // raid_leadership_points pp->raid_leadership_points, " raid_leadership_points, " + "%u," // air_remaining pp->air_remaining, " air_remaining, " + "%u," // pvp_kills pp->PVPKills, " pvp_kills, " + "%u," // pvp_deaths pp->PVPDeaths, " pvp_deaths, " + "%u," // pvp_current_points pp->PVPCurrentPoints, " pvp_current_points, " + "%u," // pvp_career_points pp->PVPCareerPoints, " pvp_career_points, " + "%u," // pvp_best_kill_streak pp->PVPBestKillStreak, " pvp_best_kill_streak, " + "%u," // pvp_worst_death_streak pp->PVPWorstDeathStreak, " pvp_worst_death_streak, " + "%u," // pvp_current_kill_streak pp->PVPCurrentKillStreak, " pvp_current_kill_streak, " + "%u," // aa_points_spent pp->aapoints_spent, " aa_points_spent, " + "%u," // aa_exp pp->expAA, " aa_exp, " + "%u," // aa_points pp->aapoints, " aa_points, " + "%u," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " + "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " + "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " + "%u" // RestTimer pp->RestTimer, " RestTimer) " ")", character_id, account_id, @@ -1370,7 +1424,12 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla pp->RestTimer ); auto results = database.QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + //if (results.RowsAffected() != 2) { + // LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::SaveCharacterData Error! Query: %s \n", query); return false; + //} + //else{ + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + //} return true; } @@ -1407,7 +1466,7 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru pp->currentEbonCrystals, pp->careerEbonCrystals); auto results = database.QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id); + LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id); return true; } @@ -1416,10 +1475,35 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur " VALUES (%u, %u, %u)", character_id, aa_id, current_level); auto results = QueryDatabase(rquery); - LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %i, aa_id: %u current_level: %i", character_id, aa_id, current_level); + LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %u, aa_id: %u current_level: %u", character_id, aa_id, current_level); return true; } +bool ZoneDatabase::SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot){ + std::string rquery = StringFormat("UPDATE `character_spells` SET `slot_id` = %u WHERE `slot_id` = %u AND `id` = %u", + to_slot, from_slot, character_id); + clock_t t = std::clock(); /* Function timer start */ + auto results = QueryDatabase(rquery); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSpellSwap for character ID: %u, from_slot: %u to_slot: %u spell: %u time: %f seconds", character_id, from_slot, to_slot, spell_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + return true; +} + +bool ZoneDatabase::SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ + std::string query = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; +} + +bool ZoneDatabase::DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ + std::string query = StringFormat("DELETE FROM `character_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; +} + +bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ + std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; +} + +bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ + std::string query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; +} + bool ZoneDatabase::NoRentExpired(const char* name){ char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; @@ -1429,7 +1513,7 @@ bool ZoneDatabase::NoRentExpired(const char* name){ safe_delete_array(query); if (mysql_num_rows(result) == 1) { row = mysql_fetch_row(result); - uint32 seconds = atoi(row[0]); + uint32 seconds = atoi(row[0]); mysql_free_result(result); return (seconds>1800); } diff --git a/zone/zonedb.h b/zone/zonedb.h index ce32e919f..87aefd4cf 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -256,18 +256,28 @@ public: void SavePetInfo(Client *c); void RemoveTempFactions(Client *c); - /* Player Profile Loaders */ + /* Character Data Loaders */ bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list); + bool LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp); - /* Player Profile Saves */ - + /* Character Data Saves */ bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); + 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); + + /* Character Data Deletes */ + bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); /* * Character Inventory diff --git a/zone/zonedbasync.cpp b/zone/zonedbasync.cpp index 579517d55..454252ab6 100644 --- a/zone/zonedbasync.cpp +++ b/zone/zonedbasync.cpp @@ -12,30 +12,6 @@ void DispatchFinishedDBAsync(DBAsyncWork* dbaw) { uint32_breakdown workpt; workpt = dbaw->WPT(); switch (workpt.b4()) { -/* case DBA_b4_Main: { - switch (workpt.i24_1()) { - case DBA_i24_1_Main_LoadVariables: { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* result; - DBAsyncQuery* dbaq = dbaw->PopAnswer(); - if (dbaq->GetAnswer(errbuf, result)) - database.LoadVariables_result(result); - else - std::cout << "Async DB.LoadVariables() failed: '" << errbuf << "'" << std::endl; - break; - } - default: { - std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4" << std::endl; - break; - } - } - }*/ - case DBA_b4_Zone: { - if(zone == nullptr) - break; - zone->DBAWComplete(workpt.b1(), dbaw); - break; - } case DBA_b4_Entity: { Entity* entity = entity_list.GetID(workpt.w2_3()); if (!entity) From 6497bdf45a9ff991b9bb916af063526bc0309637 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 31 Aug 2014 21:31:44 -0500 Subject: [PATCH 07/56] More stuff --- common/database.cpp | 39 ++++- world/worlddb.cpp | 348 +++++++++++++++++++++-------------------- zone/client.cpp | 3 + zone/client_packet.cpp | 1 + zone/inventory.cpp | 6 +- zone/zonedb.cpp | 22 +++ zone/zonedb.h | 2 + 7 files changed, 243 insertions(+), 178 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index fcfab3c52..1058cc5e1 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -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 */ diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 02dfa4290..b07480031 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -35,12 +35,10 @@ extern std::vector 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], ""); @@ -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 ="<name[char_num]); + } + safe_delete(inv); + if (++char_num > 10) + break; } return; diff --git a/zone/client.cpp b/zone/client.cpp index 975e61dc1..6d2a784a4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -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) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 9921298fe..bdd08b002 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -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... */ diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 197841c76..50b48fff9 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -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) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 09aa26bc8..b998733c3 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -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; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 87aefd4cf..d98749f5e 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -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); From e0a99730e5ac1fafe3b4aee13c186ef83662bcdb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 31 Aug 2014 21:58:04 -0500 Subject: [PATCH 08/56] pp revert --- common/database.cpp | 2 +- common/eq_packet_structs.h | 4 +-- world/worlddb.cpp | 64 ++------------------------------------ zone/client_packet.cpp | 2 +- zone/inventory.cpp | 4 +-- zone/zonedb.cpp | 4 +-- zone/zonedb.h | 2 +- 7 files changed, 11 insertions(+), 71 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 1058cc5e1..cd5693e89 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1130,7 +1130,7 @@ bool Database::CheckDatabaseConversions() { /* Verify PP Integrity */ lengths = mysql_fetch_lengths(result2); - if (lengths[1] > 0) { + if (lengths[1] == sizeof(PlayerProfile_Struct)) { memcpy(pp, row2[1], sizeof(PlayerProfile_Struct)); // printf("FINE: Player profile '%s' %i length Expected: %i, Got: %i \n", row2[2], atoi(row2[3]), sizeof(PlayerProfile_Struct), lengths[1]); } diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index d6ffd119b..c561e3a22 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -801,8 +801,8 @@ struct SuspendedMinion_Struct ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 720; // Increased to 480 to support SoF -static const uint32 MAX_PP_MEMSPELL = 12; +static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF +static const uint32 MAX_PP_MEMSPELL = 9; static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size static const uint32 MAX_PP_AA_ARRAY = 240; static const uint32 MAX_GROUP_MEMBERS = 6; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b07480031..81c99d022 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -124,61 +124,6 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* 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); - // } - // } - /* Character's equipped items @merth: Haven't done bracer01/bracer02 yet. @@ -194,10 +139,6 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* 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]); } /* Load Inventory */ @@ -212,9 +153,8 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs->equip[char_num][material] = item->GetItem()->Material; - 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; } + if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; } + else{ color = item->GetItem()->Color; } cs->cs_colors[char_num][material].color = color; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index bdd08b002..88425fade 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -597,7 +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.LoadCharacterMaterialColor(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... */ diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 50b48fff9..02cf6e568 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1878,8 +1878,8 @@ void Client::DyeArmor(DyeStruct* dye){ ItemInst* inst = this->m_inv.GetItem(slot2); if(inst){ 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); + inst->SetColor(armor_color); + database.SaveCharacterMaterialColor(this->CharacterID(), i, armor_color); database.SaveInventory(CharacterID(),inst,slot2); if(dye->dye[i].rgb.use_tint) m_pp.item_tint[i].rgb.use_tint = 0xFF; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b998733c3..50a74c892 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1151,9 +1151,9 @@ bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_i return true; } -bool ZoneDatabase::LoadCharacterMaterial(uint32 character_id, PlayerProfile_Struct* pp){ +bool ZoneDatabase::LoadCharacterMaterialColor(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; + 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++; diff --git a/zone/zonedb.h b/zone/zonedb.h index d98749f5e..705377a39 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -266,7 +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); + bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); From e0db3c0b60aa049ee8e74e2c08916eca21cd8b2c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 1 Sep 2014 22:17:06 -0500 Subject: [PATCH 09/56] Fixed Character select to be loaded from new character data tables --- common/database.cpp | 250 ++++++++++++++++++++--------------------- common/shareddb.cpp | 40 +++++++ common/shareddb.h | 3 + world/worlddb.cpp | 25 +++-- zone/client.cpp | 52 ++++----- zone/client_packet.cpp | 15 ++- zone/zonedb.cpp | 17 +-- 7 files changed, 218 insertions(+), 184 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cd5693e89..d926cb950 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -798,7 +798,7 @@ bool Database::CheckDatabaseConversions() { int character_id = 0; int account_id = 0; int number_of_characters = 0; - int printppdebug = 0; + int printppdebug = 0; /* Prints Player Profile */ int runconvert = 0; /* Check For Legacy Storage Method */ @@ -842,7 +842,7 @@ bool Database::CheckDatabaseConversions() { " `race` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " " `class` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " " `level` int(11) UNSIGNED NOT NULL DEFAULT 0, " - " `deity` tinyint(11) UNSIGNED NOT NULL, " + " `deity` int(11) UNSIGNED NOT NULL, " " `birthday` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `last_login` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `time_played` int(11) UNSIGNED NOT NULL DEFAULT 0, " @@ -886,9 +886,9 @@ bool Database::CheckDatabaseConversions() { " `drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " - " `toxicity` int(11) NOT NULL DEFAULT 0, " - " `hunger_level` int(11) NOT NULL DEFAULT 0, " - " `thirst_level` int(11) NOT NULL DEFAULT 0, " + " `toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " @@ -1113,9 +1113,9 @@ bool Database::CheckDatabaseConversions() { printf("Starting conversion...\n\n"); } - // querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); + // querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); // WHERE `account_id` = 11001 int char_iter_count = 0; - querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` >= 61238 LIMIT 10"); + querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `account_id` = 11001"); if (RunQuery(query, querylen, errbuf, &result)) { safe_delete_array(query); while (row = mysql_fetch_row(result)) { @@ -1176,96 +1176,96 @@ bool Database::CheckDatabaseConversions() { /* Run Character Data Convert */ rquery = StringFormat( "REPLACE INTO `character_data` (" - " id, " - " account_id, " - " `name`, " - " last_name, " - " gender, " - " race, " - " class, " - " `level`, " - " deity, " - " birthday, " - " last_login, " - " time_played, " - " pvp_status, " - " level2, " - " anon, " - " gm, " - " intoxication, " - " hair_color, " - " beard_color, " - " eye_color_1, " - " eye_color_2, " - " hair_style, " - " beard, " - " ability_time_seconds, " - " ability_number, " - " ability_time_minutes, " - " ability_time_hours, " - " title, " - " suffix, " - " exp, " - " points, " - " mana, " - " cur_hp, " - " str, " - " sta, " - " cha, " - " dex, " - " `int`, " - " agi, " - " wis, " - " face, " - " y, " - " x, " - " z, " - " heading, " - " pvp2, " - " pvp_type, " - " autosplit_enabled, " - " zone_change_count, " - " drakkin_heritage, " - " drakkin_tattoo, " - " drakkin_details, " - " toxicity, " - " hunger_level, " - " thirst_level, " - " ability_up, " - " zone_id, " - " zone_instance, " - " leadership_exp_on, " - " ldon_points_guk, " - " ldon_points_mir, " - " ldon_points_mmc, " - " ldon_points_ruj, " - " ldon_points_tak, " - " ldon_points_available, " - " tribute_time_remaining, " - " show_helm, " - " career_tribute_points, " - " tribute_points, " - " tribute_active, " - " endurance, " - " group_leadership_exp, " - " raid_leadership_exp, " - " group_leadership_points, " - " raid_leadership_points, " - " air_remaining, " - " pvp_kills, " - " pvp_deaths, " - " pvp_current_points, " - " pvp_career_points, " - " pvp_best_kill_streak, " - " pvp_worst_death_streak, " - " pvp_current_kill_streak, " - " aa_points_spent, " - " aa_exp, " - " aa_points, " - " group_auto_consent, " - " raid_auto_consent, " - " guild_auto_consent, " - " RestTimer) " + "id," + "account_id," + "`name`," + "last_name," + "gender," + "race," + "class," + "`level`," + "deity," + "birthday," + "last_login," + "time_played," + "pvp_status," + "level2," + "anon," + "gm," + "intoxication," + "hair_color," + "beard_color," + "eye_color_1," + "eye_color_2," + "hair_style," + "beard," + "ability_time_seconds," + "ability_number," + "ability_time_minutes," + "ability_time_hours," + "title," + "suffix," + "exp," + "points," + "mana," + "cur_hp," + "str," + "sta," + "cha," + "dex," + "`int`," + "agi," + "wis," + "face," + "y," + "x," + "z," + "heading," + "pvp2," + "pvp_type," + "autosplit_enabled," + "zone_change_count," + "drakkin_heritage," + "drakkin_tattoo," + "drakkin_details," + "toxicity," + "hunger_level," + "thirst_level," + "ability_up," + "zone_id," + "zone_instance," + "leadership_exp_on," + "ldon_points_guk," + "ldon_points_mir," + "ldon_points_mmc," + "ldon_points_ruj," + "ldon_points_tak," + "ldon_points_available," + "tribute_time_remaining," + "show_helm," + "career_tribute_points," + "tribute_points," + "tribute_active," + "endurance," + "group_leadership_exp," + "raid_leadership_exp," + "group_leadership_points," + "raid_leadership_points," + "air_remaining," + "pvp_kills," + "pvp_deaths," + "pvp_current_points," + "pvp_career_points," + "pvp_best_kill_streak," + "pvp_worst_death_streak," + "pvp_current_kill_streak," + "aa_points_spent," + "aa_exp," + "aa_points," + "group_auto_consent," + "raid_auto_consent," + "guild_auto_consent," + "RestTimer)" "VALUES (" "%u," // id "%u," // account_id @@ -1450,6 +1450,7 @@ bool Database::CheckDatabaseConversions() { pp->RestTimer ); results = QueryDatabase(rquery); + if (!results.RowsAffected()){ std::cout << "ERROR PP Data Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run AA Convert */ for (i = 0; i < MAX_PP_AA_ARRAY; i++){ @@ -1457,21 +1458,21 @@ bool Database::CheckDatabaseConversions() { rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - QueryDatabase(rquery); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } /* Run Bind Home Convert */ rquery = StringFormat("REPLACE INTO `character_bind_home` (id, zone_id, instance_id, x, y, z, heading)" " VALUES (%u, %u, %u, %f, %f, %f, %f)", - character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - QueryDatabase(rquery); + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Language Convert */ for (i = 0; i < MAX_PP_LANGUAGE; i++){ if (pp->languages[i] > 0){ rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); - QueryDatabase(rquery); + QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } @@ -1479,7 +1480,7 @@ bool Database::CheckDatabaseConversions() { for (i = 0; i < MAX_PP_SKILL; i++){ if (pp->skills[i] > 0){ rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); - QueryDatabase(rquery); + QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } @@ -1487,7 +1488,7 @@ bool Database::CheckDatabaseConversions() { for (i = 0; i < MAX_PP_SPELLBOOK; i++){ if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295){ rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); - QueryDatabase(rquery); + QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } @@ -1495,7 +1496,7 @@ bool Database::CheckDatabaseConversions() { for (i = 0; i < MAX_PP_MEMSPELL; i++){ if (pp->mem_spells[i] > 0){ rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); - QueryDatabase(rquery); + QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } @@ -1503,16 +1504,16 @@ bool Database::CheckDatabaseConversions() { for (i = 0; i < MAX_PP_DISCIPLINES; i++){ if (pp->disciplines.values[i] > 0){ rquery = StringFormat("REPLACE INTO `character_disciplines` (id, disc_id) VALUES (%u, %u)", character_id, pp->disciplines.values[i]); - QueryDatabase(rquery); + QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } /* 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); - } + // printf("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u);\n", 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); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } } } @@ -2568,13 +2569,13 @@ uint8 Database::GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 return base_cap; } -uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZoneID, uint32* oInstanceID, float* oX, float* oY, float* oZ) { - - std::string query = StringFormat("SELECT id, account_id, zonename, instanceid, x, y, z FROM character_ WHERE name='%s'", iName); +uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZoneID, uint32* oInstanceID, float* oX, float* oY, float* oZ) { + std::string query = StringFormat("SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'", iName); auto results = QueryDatabase(query); - if (!results.Success()) - { + printf("Calling Database::GetCharacterInfo: ACCID: %u ZONEID: %u INSTANCEID: %u \n", oAccID, oZoneID, oInstanceID); + + if (!results.Success()) { std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -2582,21 +2583,16 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo if (results.RowCount() != 1) return 0; - auto row = results.begin(); - + auto row = results.begin(); uint32 charid = atoi(row[0]); - if (oAccID) - *oAccID = atoi(row[1]); - if (oZoneID) - *oZoneID = GetZoneID(row[2]); - if(oInstanceID) - *oInstanceID = atoi(row[3]); - if (oX) - *oX = atof(row[4]); - if (oY) - *oY = atof(row[5]); - if (oZ) - *oZ = atof(row[6]); + if (oAccID){ *oAccID = atoi(row[1]); } + if (oZoneID){ *oZoneID = atoi(row[2]); } + if (oInstanceID){ *oInstanceID = atoi(row[3]); } + if (oX){ *oX = atof(row[4]); } + if (oY){ *oY = atof(row[5]); } + if (oZ){ *oZ = atof(row[6]); } + + printf("Calling Database::GetCharacterInfo: ACCID: %u ZONEID: %u INSTANCEID: %u \n", oAccID, oZoneID, oInstanceID); return charid; } diff --git a/common/shareddb.cpp b/common/shareddb.cpp index e4336b02f..9f234b4ae 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -61,6 +61,46 @@ bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) return true; } +bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + uint32 affected_rows = 0; + bool ret = false; + + if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { + ret = (affected_rows != 0); + } + + if (!ret) { + LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); + } + + safe_delete_array(query); + return ret; +} + +// Generate SQL for updating player profile +uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { + *query = new char[396 + sizeof(PlayerProfile_Struct)* 2 + sizeof(ExtendedProfile_Struct)* 2 + 4]; + char* end = *query; + if (!current_zone) + current_zone = pp->zone_id; + + if (!current_instance) + current_instance = pp->zoneInstance; + + if (strlen(pp->name) == 0) // Sanity check in case pp never loaded + return false; + + end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, ", pp->name, "halas", 29, current_instance, pp->x, pp->y, pp->z); + // end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); + end += sprintf(end, " extprofile=\'"); + end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); + end += sprintf(end, "\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); + + return (uint32)(end - (*query)); +} + uint8 SharedDatabase::GetGMSpeed(uint32 account_id) { diff --git a/common/shareddb.h b/common/shareddb.h index 5401bfa0a..c55163465 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -34,6 +34,9 @@ public: SharedDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port); virtual ~SharedDatabase(); + /* Temp */ + uint32 SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); + bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); /* * General Character Related Stuff */ diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 81c99d022..deccc9207 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -35,9 +35,7 @@ extern std::vector 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) { - /* Initialize Player Profile for the small time it is being used for item material */ - PlayerProfile_Struct pp; - memset(&pp, 0, sizeof(PlayerProfile_Struct)); + Inventory *inv; /* Initialize Variables */ for (int i=0; i<10; i++) { @@ -73,10 +71,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* "zone_id " // 19 "FROM " "character_data " - "WHERE `account_id` = %i LIMIT 10 ", account_id); - auto results = database.QueryDatabase(cquery); uint16 char_num = 0; + "WHERE `account_id` = %i ORDER BY `name` LIMIT 10 ", account_id); + auto results = database.QueryDatabase(cquery); int char_num = 0; for (auto row = results.begin(); row != results.end(); ++row) { - printf("id is %i \n", atoi(row[0])); + PlayerProfile_Struct pp; + memset(&pp, 0, sizeof(PlayerProfile_Struct)); + uint32 character_id = atoi(row[0]); strcpy(cs->name[char_num], row[1]); uint8 lvl = atoi(row[5]); @@ -133,16 +133,17 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* */ /* Load Character Material Data for Char Select */ - cquery = StringFormat("SELECT slot, use_tint, color FROM `character_material` WHERE `id` = %u", character_id); + cquery = StringFormat("SELECT slot, red, green, blue, 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]); + pp.item_tint[slot].rgb.red = atoi(row_b[1]); + pp.item_tint[slot].rgb.green = atoi(row_b[2]); + pp.item_tint[slot].rgb.blue = atoi(row_b[3]); + pp.item_tint[slot].rgb.use_tint = atoi(row_b[4]); } /* Load Inventory */ - Inventory *inv; inv = new Inventory; if (GetInventory(account_id, cs->name[char_num], inv)) { for (uint8 material = 0; material <= 8; material++) { @@ -156,9 +157,9 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* if (pp.item_tint[material].rgb.use_tint){ color = pp.item_tint[material].color; } else{ color = item->GetItem()->Color; } - cs->cs_colors[char_num][material].color = color; + cs->cs_colors[char_num][material].color = color; - // the weapons are kept elsewhere + /* Weapons are handled a bit differently */ if ((material == MaterialPrimary) || (material == MaterialSecondary)) { if (strlen(item->GetItem()->IDFile) > 2) { uint32 idfile = atoi(&item->GetItem()->IDFile[2]); diff --git a/zone/client.cpp b/zone/client.cpp index 6d2a784a4..2213c0a26 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -588,35 +588,35 @@ bool Client::Save(uint8 iCommitNow) { /* Save Character Task */ SaveTaskState(); + if (iCommitNow <= 1) { + // char* query = 0; + // uint32_breakdown workpt; + // workpt.b4() = DBA_b4_Entity; + // workpt.w2_3() = GetID(); + // workpt.b1() = DBA_b1_Entity_Client_Save; + // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); + // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); + // if (iCommitNow == 0){ + // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); + // } + // else { + // dbasync->AddWork(&dbaw, 0); + // SaveBackup(); + // } + // safe_delete_array(query); + // return true; + } + else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { + SaveBackup(); + } + else { + std::cerr << "Failed to update player profile" << std::endl; + return false; + } + /* Save Character Data */ database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); - // if (iCommitNow <= 1) { - // char* query = 0; - // uint32_breakdown workpt; - // workpt.b4() = DBA_b4_Entity; - // workpt.w2_3() = GetID(); - // workpt.b1() = DBA_b1_Entity_Client_Save; - // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); - // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); - // if (iCommitNow == 0){ - // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); - // } - // else { - // dbasync->AddWork(&dbaw, 0); - // SaveBackup(); - // } - // safe_delete_array(query); - // return true; - // } - // else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { - // SaveBackup(); - // } - // else { - // std::cerr << "Failed to update player profile" << std::endl; - // return false; - // } - /* Mirror Character Data */ database.StoreCharacterLookup(this->CharacterID()); LogFile->write(EQEMuLog::Status, "Client::Save %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 88425fade..87d884eb7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -553,7 +553,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.item_tint[i].rgb.use_tint = 0xFF; uint32 cid = CharacterID(); - character_id = cid; + character_id = cid; /* Global character_id reference */ /* Flush and reload factions */ database.RemoveTempFactions(this); @@ -588,8 +588,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (RuleB(Character, SharedBankPlat)) m_pp.platinum_shared = database.GetSharedPlatinum(database.GetAccountIDByChar(cid)); - // if (ext) { SetExtendedProfile(ext, row[8], lengths[8]); } - if (level){ level = atoi(row[10]); } if (LFP){ LFP = atoi(row[11]); } if (LFG){ LFG = atoi(row[12]); } if (firstlogon){ firstlogon = atoi(row[15]); } @@ -608,6 +606,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */ database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */ + if (level){ level = m_pp.level; } + /* If GM, not trackable */ if (gmhideme) { trackable = false; } /* Set Con State for Reporting */ @@ -632,9 +632,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.z = zone->safe_z(); } /* If too far below ground, then fix */ - float ground_z = GetGroundZ(m_pp.x, m_pp.y, m_pp.z); - if (m_pp.z < (ground_z - 500)) - m_pp.z = ground_z; + // float ground_z = GetGroundZ(m_pp.x, m_pp.y, m_pp.z); + // if (m_pp.z < (ground_z - 500)) + // m_pp.z = ground_z; /* Set Mob variables for spawn */ class_ = m_pp.class_; @@ -1019,8 +1019,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) outapp = new EQApplicationPacket(OP_Weather, 12); Weather_Struct *ws = (Weather_Struct *)outapp->pBuffer; ws->val1 = 0x000000FF; - if (zone->zone_weather == 1) - ws->type = 0x31; // Rain + if (zone->zone_weather == 1){ ws->type = 0x31; } // Rain if (zone->zone_weather == 2) { outapp->pBuffer[8] = 0x01; ws->type = 0x02; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 50a74c892..794b1240f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1146,7 +1146,7 @@ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Str } 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); + std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", 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; } @@ -1160,9 +1160,8 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile 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); + pp->item_tint[i].rgb.use_tint = atoi(row[r]); + printf("Material Load: %u %u %u %u\n", 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); } return true; } @@ -1445,13 +1444,9 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla pp->guildAutoconsent, pp->RestTimer ); - auto results = database.QueryDatabase(query); - //if (results.RowsAffected() != 2) { - // LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::SaveCharacterData Error! Query: %s \n", query); return false; - //} - //else{ - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); - //} + auto results = database.QueryDatabase(query); + if (!results.RowsAffected()){ std::cout << "ERROR ZoneDatabase:SaveCharacterData: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } From 0a9222e1ee39791f5de1d3b3c5db8b33201cdee5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 1 Sep 2014 23:54:15 -0500 Subject: [PATCH 10/56] - --- common/shareddb.cpp | 2 +- world/zoneserver.cpp | 3 +++ zone/client.cpp | 50 ++++++++++++++++++++++---------------------- zone/mob.cpp | 1 + zone/worldserver.cpp | 2 +- zone/zoning.cpp | 22 +++++++++++++++++++ 6 files changed, 53 insertions(+), 27 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 9f234b4ae..6124d37f1 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -92,7 +92,7 @@ uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint if (strlen(pp->name) == 0) // Sanity check in case pp never loaded return false; - end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, ", pp->name, "halas", 29, current_instance, pp->x, pp->y, pp->z); + end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, ", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); // end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); end += sprintf(end, " extprofile=\'"); end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 7c4f4f963..af0752a95 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -675,6 +675,9 @@ bool ZoneServer::Process() { zlog(WORLD__ZONE,"ZoneToZone request for %s current zone %d req zone %d\n", ztz->name, ztz->current_zone_id, ztz->requested_zone_id); + printf("\n\n ZoneToZone request for %s current zone %d req zone %d\n\n", + ztz->name, ztz->current_zone_id, ztz->requested_zone_id); + if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) // this is a request from the egress zone { zlog(WORLD__ZONE,"Processing ZTZ for egress from zone for client %s\n", ztz->name); diff --git a/zone/client.cpp b/zone/client.cpp index 2213c0a26..c56d47b4d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -588,31 +588,31 @@ bool Client::Save(uint8 iCommitNow) { /* Save Character Task */ SaveTaskState(); - if (iCommitNow <= 1) { - // char* query = 0; - // uint32_breakdown workpt; - // workpt.b4() = DBA_b4_Entity; - // workpt.w2_3() = GetID(); - // workpt.b1() = DBA_b1_Entity_Client_Save; - // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); - // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); - // if (iCommitNow == 0){ - // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); - // } - // else { - // dbasync->AddWork(&dbaw, 0); - // SaveBackup(); - // } - // safe_delete_array(query); - // return true; - } - else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { - SaveBackup(); - } - else { - std::cerr << "Failed to update player profile" << std::endl; - return false; - } + // if (iCommitNow <= 1) { + // // char* query = 0; + // // uint32_breakdown workpt; + // // workpt.b4() = DBA_b4_Entity; + // // workpt.w2_3() = GetID(); + // // workpt.b1() = DBA_b1_Entity_Client_Save; + // // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); + // // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); + // // if (iCommitNow == 0){ + // // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); + // // } + // // else { + // // dbasync->AddWork(&dbaw, 0); + // // SaveBackup(); + // // } + // // safe_delete_array(query); + // // return true; + // } + // else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { + // SaveBackup(); + // } + // else { + // std::cerr << "Failed to update player profile" << std::endl; + // return false; + // } /* Save Character Data */ database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); diff --git a/zone/mob.cpp b/zone/mob.cpp index 0d7002253..9b4e3f53e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1931,6 +1931,7 @@ void Mob::SetZone(uint32 zone_id, uint32 instance_id) { CastToClient()->GetPP().zone_id = zone_id; CastToClient()->GetPP().zoneInstance = instance_id; + CastToClient()->Save(); } Save(); } diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 791a34ee4..152ed4f0d 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -322,7 +322,7 @@ void WorldServer::Process() { entity->CastToMob()->SetZone(ztz->requested_zone_id, ztz->requested_instance_id); - if(ztz->ignorerestrictions == 3) + if(ztz->ignorerestrictions == 3) entity->CastToClient()->GoToSafeCoords(ztz->requested_zone_id, ztz->requested_instance_id); } diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 1b64fef3c..88351ee3e 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -50,6 +50,10 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { #endif ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer; + printf("INCOMING CLIENT\n\n"); + printf("%s\n", zc->char_name); + printf("%u\n", zc->zoneID); + uint16 target_zone_id = 0; uint16 target_instance_id = zc->instanceID; ZonePoint* zone_point = nullptr; @@ -368,6 +372,8 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc outapp->priority = 6; FastQueuePacket(&outapp); + printf("INTERZONE PROCESS\n"); + zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } else { // vesuvias - zoneing to another zone so we need to the let the world server @@ -384,6 +390,17 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc strcpy(ztz->name, GetName()); ztz->guild_id = GuildID(); worldserver.SendPacket(pack); + + printf("ZONING REQUEST TO WORLD\n"); + printf("ztz->response %u \n", ztz->response); + printf("ztz->current_zone_id %u \n", ztz->current_zone_id); + printf("ztz->current_instance_id %u \n", ztz->current_instance_id); + printf("ztz->requested_zone_id %u \n", ztz->requested_zone_id); + printf("ztz->requested_instance_id %u \n", ztz->requested_instance_id); + printf("ztz->admin %u \n", ztz->admin); + printf("ztz->ignorerestrictions %u \n", ztz->ignorerestrictions); + printf("ztz->guild_id %u \n", ztz->guild_id); + safe_delete(pack); } @@ -551,6 +568,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z if(ReadyToZone) { zone_mode = zm; + printf("\n\n ZONE MODE %u \n\n", zm); if(zm == ZoneToBindPoint) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + iZoneNameLength); ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; @@ -584,6 +602,10 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z gmg->instance_id = instance_id; gmg->type = 0x01; //an observed value, not sure of meaning + printf("gmg->zone_id %u \n", gmg->zone_id); + printf("gmg->x %u \n", gmg->x); + printf("gmg->y %u \n", gmg->y); + outapp->priority = 6; FastQueuePacket(&outapp); safe_delete(outapp); From 4432c070815873489923c234cab131b01acd825f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 4 Sep 2014 07:24:17 -0500 Subject: [PATCH 11/56] State of Commit: Testable if you ask me (Akkadius) what you need to do - Need to convert a list of functions and columns and should be ready to start intensive testing phase - All preliminary tests show things working great - All of player profile is saved and loaded from the database - DBAsync has been completely removed from all code - Removed zone/dbasync.cpp/.h - Removed common/dbasync.cpp/.h - Removed dbasync from cmake commmon and zone - Cleaned up a ton of functions - Added several tables to world CheckDatabaseConversions script: - `character_skills` - `character_languages` - `character_bind` - `character_alternate_abilities` - `character_currency` - `character_data` - `character_spells` - `character_memmed_spells` - `character_disciplines` - `character_material` - `character_tribute` - `character_bandolier` - `character_potionbelt` - Character select now loads from `character_data` - Character creation now creates to `character_data` - Updated function Database::UpdateName to use `character_data` - Updated function Database::CheckUsedName to use `character_data` - Updated function Database::MoveCharacterToZone to use `character_data` - Updated function Database::SetLoginFlags to use `character_data` - Updated function Database::SetFirstLogon to use `character_data` - Updated function Database::SetLFG to use `character_data` - Removed CopyCharacter functions and commands, to be recreated later since it never worked to begin with - Removed SharedDatabase::SetPlayerProfile - Trimmed down redundant case switch statements for World sendpackets to QueryServ - Added Character Methods to Database class: Loads: bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); Saves: bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); 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); bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); Deletes: bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); --- common/CMakeLists.txt | 2 - common/database.cpp | 1354 ++++++++++++++++--------------- common/database.h | 15 +- common/dbasync.cpp | 669 --------------- common/dbasync.h | 176 ---- common/eq_packet_structs.h | 15 +- common/mysql_request_result.cpp | 1 + common/mysql_request_result.h | 2 +- common/shareddb.cpp | 107 +-- common/shareddb.h | 3 - world/client.cpp | 161 ++-- world/net.cpp | 3 - world/worlddb.cpp | 17 +- world/zoneserver.cpp | 109 +-- zone/CMakeLists.txt | 2 - zone/client.cpp | 90 +- zone/client.h | 10 +- zone/client_packet.cpp | 61 +- zone/client_process.cpp | 3 +- zone/command.cpp | 32 +- zone/command.h | 1 - zone/effects.cpp | 1 + zone/entity.cpp | 5 +- zone/entity.h | 4 +- zone/exp.cpp | 9 +- zone/inventory.cpp | 24 +- zone/net.cpp | 10 - zone/questmgr.cpp | 12 +- zone/spells.cpp | 3 +- zone/trading.cpp | 11 +- zone/tribute.cpp | 10 +- zone/zone.cpp | 5 - zone/zonedb.cpp | 395 ++++++--- zone/zonedb.h | 148 ++-- zone/zonedbasync.cpp | 103 --- zone/zonedbasync.h | 22 - zone/zoning.cpp | 10 +- 37 files changed, 1235 insertions(+), 2370 deletions(-) delete mode 100644 common/dbasync.cpp delete mode 100644 common/dbasync.h delete mode 100644 zone/zonedbasync.cpp delete mode 100644 zone/zonedbasync.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f02212161..55e8a8a72 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -8,7 +8,6 @@ SET(common_sources crc16.cpp crc32.cpp database.cpp - dbasync.cpp dbcore.cpp debug.cpp emu_opcodes.cpp @@ -103,7 +102,6 @@ SET(common_headers crc16.h crc32.h database.h - dbasync.h dbcore.h debug.h deity.h diff --git a/common/database.cpp b/common/database.cpp index d926cb950..5de92ba08 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -71,55 +71,25 @@ Database::Database(const char* host, const char* user, const char* passwd, const Connect(host, user, passwd, database, port); } -bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) -{ +bool Database::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) { uint32 errnum= 0; char errbuf[MYSQL_ERRMSG_SIZE]; - if (!Open(host, user, passwd, database, port, &errnum, errbuf)) - { + if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf); - HandleMysqlError(errnum); return false; } - else - { + else { LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port); return true; } } -void Database::DBInitVars() { - +void Database::DBInitVars() { varcache_array = 0; varcache_max = 0; varcache_lastupdate = 0; } - -void Database::HandleMysqlError(uint32 errnum) { -/* switch(errnum) { - case 0: - break; - case 1045: // Access Denied - case 2001: { - AddEQEMuError(EQEMuError_Mysql_1405, true); - break; - } - case 2003: { // Unable to connect - AddEQEMuError(EQEMuError_Mysql_2003, true); - break; - } - case 2005: { // Unable to connect - AddEQEMuError(EQEMuError_Mysql_2005, true); - break; - } - case 2007: { // Unable to connect - AddEQEMuError(EQEMuError_Mysql_2007, true); - break; - } - }*/ -} - /* Close the connection to the database @@ -191,24 +161,18 @@ bool Database::CheckBannedIPs(const char* loginIP) return false; } -bool Database::AddBannedIP(char* bannedIP, const char* notes) -{ - std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; +bool Database::AddBannedIP(char* bannedIP, const char* notes) { + std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); + auto results = QueryDatabase(query); + if (!results.Success()) { + std::cerr << "Error in Database::AddBannedIP query '" << query << "' " << results.ErrorMessage() << std::endl; return false; - } - + } return true; } bool Database::CheckGMIPs(const char* ip_address, uint32 account_id) { - std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id); - + std::string query = StringFormat("SELECT * FROM `gm_ips` WHERE `ip_address` = '%s' AND `account_id` = %i", ip_address, account_id); auto results = QueryDatabase(query); if (!results.Success()) @@ -221,32 +185,24 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) } bool Database::AddGMIP(char* ip_address, char* name) { - std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name); - - auto results = QueryDatabase(query); - + std::string query = StringFormat("INSERT into `gm_ips` SET `ip_address` = '%s', `name` = '%s'", ip_address, name); + auto results = QueryDatabase(query); return results.Success(); } -void Database::LoginIP(uint32 AccountID, const char* LoginIP) -{ - std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); - - auto results = QueryDatabase(query); - +void Database::LoginIP(uint32 AccountID, const char* LoginIP) { + std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); + auto results = QueryDatabase(query); if (!results.Success()) std::cerr << "Error in Log IP query '" << query << "' " << results.ErrorMessage() << std::endl; } -int16 Database::CheckStatus(uint32 account_id) -{ +int16 Database::CheckStatus(uint32 account_id) { std::string query = StringFormat("SELECT `status`, UNIX_TIMESTAMP(`suspendeduntil`) as `suspendeduntil`, UNIX_TIMESTAMP() as `current`" " FROM `account` WHERE `id` = %i", account_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - { + auto results = QueryDatabase(query); + if (!results.Success()) { std::cerr << "Error in CheckStatus query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -254,10 +210,8 @@ int16 Database::CheckStatus(uint32 account_id) if (results.RowCount() != 1) return 0; - auto row = results.begin(); - - int16 status = atoi(row[0]); - + auto row = results.begin(); + int16 status = atoi(row[0]); int32 suspendeduntil = 0; // MariaDB initalizes with NULL if unix_timestamp() is out of range @@ -281,12 +235,10 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta else query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); - std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; - + std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -301,8 +253,7 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta } bool Database::DeleteAccount(const char* name) { - std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); - + std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); std::cout << "Account Attempting to be deleted:" << name << std::endl; auto results = QueryDatabase(query); @@ -317,7 +268,7 @@ bool Database::DeleteAccount(const char* name) { } bool Database::SetLocalPassword(uint32 accid, const char* password) { - std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", password, accid); + std::string query = StringFormat("UPDATE `account` SET `password` = MD5('%s') where id=%i;", password, accid); auto results = QueryDatabase(query); @@ -342,275 +293,394 @@ bool Database::SetAccountStatus(const char* name, int16 status) { if (results.RowsAffected() == 0) { std::cout << "Account: " << name << " does not exist, therefore it cannot be flagged\n"; - return false; + return false; } return true; } -bool Database::ReserveName(uint32 account_id, char* name) -{ - std::string query = StringFormat("INSERT into character_ SET account_id=%i, name='%s', profile=NULL", account_id, name); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in ReserveName query '" << query << "' " << results.ErrorMessage() << std::endl; - return false; - } - +/* This initially creates the character during character create */ +bool Database::ReserveName(uint32 account_id, char* name) { + std::string query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); + auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::ReserveName", query); return true; } +bool Database::ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query){ + if (ErrorMessage != ""){ std::cout << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n" << std::endl; return true; } + return false; +} + /* -Delete the character with the name "name" -returns false on failure, true otherwise + Delete the character with the name "name" + returns false on failure, true otherwise */ -bool Database::DeleteCharacter(char *name) -{ - std::string query=StringFormat("SELECT id from character_ WHERE name='%s'", name); - int charid; - - if(!name || !strlen(name)) - { +bool Database::DeleteCharacter(char *name) { + uint32 charid = 0; + printf("Database::DeleteCharacter name : %s \n", name); + if(!name || !strlen(name)) { std::cerr << "DeleteCharacter: request to delete without a name (empty char slot)" << std::endl; return false; } -// get id from character_ before deleting record so we can clean up inventory and qglobal - -#if DEBUG >= 5 - std::cout << "DeleteCharacter: Attempting to delete '" << name << "'" << std::endl; -#endif - + /* Get id from character_data before deleting record so we can clean up the rest of the tables */ + std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); } + if (charid <= 0){ std::cerr << "Database::DeleteCharacter :: Character not found, stopping delete...\n"; return false; } - if(results.RowCount() != 1) - { - std::cerr << "DeleteCharacter error: got " << results.RowCount() << " rows matching '" << name << "'" << std::endl; - return false; - } - - auto row = results.begin(); - charid = atoi(row[0]); - -#if DEBUG >= 5 - std::cout << "DeleteCharacter: found '" << name << "' with char id: " << charid << std::endl; - std::cout << "DeleteCharacter: deleting << '" << name << "' (id " << charid << "): " << std::endl; - std::cout << " quest_globals"; -#endif - - query = StringFormat("DELETE from quest_globals WHERE charid='%d'", charid); + query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); +#ifdef BOTS + query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); +#else + query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid); +#endif QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " character_tasks"; -#endif - - query = StringFormat("DELETE from character_tasks WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " character_activities"; -#endif - - query = StringFormat("DELETE from character_activities WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " character_enabledtasks"; -#endif - - query = StringFormat("DELETE from character_enabledtasks WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " completed_tasks"; -#endif - - query = StringFormat("DELETE from completed_tasks WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " friends"; -#endif - - query = StringFormat("DELETE from friends WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " mail"; -#endif - - query = StringFormat( "DELETE from mail WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " ptimers"; -#endif - - query = StringFormat("DELETE from timers WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " inventory"; -#endif - - query = StringFormat("DELETE from inventory WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " guild_members"; -#endif - -#ifdef BOTS - query = StringFormat("DELETE FROM guild_members WHERE char_id='%d' AND GetMobTypeById(%i) = 'C'", charid); -#else - query = StringFormat("DELETE FROM guild_members WHERE char_id='%d'", charid); -#endif - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " recipes"; -#endif - - query = StringFormat("DELETE FROM char_recipe_list WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " adventure_stats"; -#endif - - query = StringFormat("DELETE FROM adventure_stats WHERE player_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " zone_flags"; -#endif - - query = StringFormat("DELETE FROM zone_flags WHERE charID='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " titles"; -#endif - - query = StringFormat("DELETE FROM titles WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " titlesets"; -#endif - - query = StringFormat("DELETE FROM player_titlesets WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " keyring"; -#endif - - query = StringFormat("DELETE FROM keyring WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " factions"; -#endif - - query = StringFormat("DELETE FROM faction_values WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " instances"; -#endif - - query = StringFormat("DELETE FROM instance_list_player WHERE charid='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << " _character"; -#endif - - query = StringFormat("DELETE from character_ WHERE id='%d'", charid); - results = QueryDatabase(query); - - if(results.RowsAffected() != 1) // here we have to have a match or it's an error - { - LogFile->write(EQEMuLog::Error, "DeleteCharacter: error: delete operation affected %d rows\n", results.RowsAffected()); - return false; - } - -#if DEBUG >= 5 - std::cout << " alternate currency"; -#endif - - query = StringFormat("DELETE FROM character_alt_currency WHERE char_id='%d'", charid); - QueryDatabase(query); - -#if DEBUG >= 5 - std::cout << std::endl; -#endif - std::cout << "DeleteCharacter: successfully deleted '" << name << "' (id " << charid << ")" << std::endl; - + return true; } -/* This only for new Character creation storing */ -bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext) -{ - char query[256+sizeof(PlayerProfile_Struct)*2+sizeof(ExtendedProfile_Struct)*2+5]; - char* end = query; - uint32 charid = 0; - char zone[50]; - float x, y, z; +bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat( + "REPLACE INTO `character_data` (" + "id," + "account_id," + "`name`," + "last_name," + "gender," + "race," + "class," + "`level`," + "deity," + "birthday," + "last_login," + "time_played," + "pvp_status," + "level2," + "anon," + "gm," + "intoxication," + "hair_color," + "beard_color," + "eye_color_1," + "eye_color_2," + "hair_style," + "beard," + "ability_time_seconds," + "ability_number," + "ability_time_minutes," + "ability_time_hours," + "title," + "suffix," + "exp," + "points," + "mana," + "cur_hp," + "str," + "sta," + "cha," + "dex," + "`int`," + "agi," + "wis," + "face," + "y," + "x," + "z," + "heading," + "pvp2," + "pvp_type," + "autosplit_enabled," + "zone_change_count," + "drakkin_heritage," + "drakkin_tattoo," + "drakkin_details," + "toxicity," + "hunger_level," + "thirst_level," + "ability_up," + "zone_id," + "zone_instance," + "leadership_exp_on," + "ldon_points_guk," + "ldon_points_mir," + "ldon_points_mmc," + "ldon_points_ruj," + "ldon_points_tak," + "ldon_points_available," + "tribute_time_remaining," + "show_helm," + "career_tribute_points," + "tribute_points," + "tribute_active," + "endurance," + "group_leadership_exp," + "raid_leadership_exp," + "group_leadership_points," + "raid_leadership_points," + "air_remaining," + "pvp_kills," + "pvp_deaths," + "pvp_current_points," + "pvp_career_points," + "pvp_best_kill_streak," + "pvp_worst_death_streak," + "pvp_current_kill_streak," + "aa_points_spent," + "aa_exp," + "aa_points," + "group_auto_consent," + "raid_auto_consent," + "guild_auto_consent," + "RestTimer) " + "VALUES (" + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%i," // toxicity + "%i," // hunger_level + "%i," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_point + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_strea + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent + "%u" // RestTimer + ")", + character_id, // " id, " + account_id, // " account_id, " + pp->name, // " `name`, " + pp->last_name, // " last_name, " + pp->gender, // " gender, " + pp->race, // " race, " + pp->class_, // " class, " + pp->level, // " `level`, " + pp->deity, // " deity, " + pp->birthday, // " birthday, " + pp->lastlogin, // " last_login, " + pp->timePlayedMin, // " time_played, " + pp->pvp, // " pvp_status, " + pp->level2, // " level2, " + pp->anon, // " anon, " + pp->gm, // " gm, " + pp->intoxication, // " intoxication, " + pp->haircolor, // " hair_color, " + pp->beardcolor, // " beard_color, " + pp->eyecolor1, // " eye_color_1, " + pp->eyecolor2, // " eye_color_2, " + pp->hairstyle, // " hair_style, " + pp->beard, // " beard, " + pp->ability_time_seconds, // " ability_time_seconds, " + pp->ability_number, // " ability_number, " + pp->ability_time_minutes, // " ability_time_minutes, " + pp->ability_time_hours, // " ability_time_hours, " + pp->title, // " title, " + pp->suffix, // " suffix, " + pp->exp, // " exp, " + pp->points, // " points, " + pp->mana, // " mana, " + pp->cur_hp, // " cur_hp, " + pp->STR, // " str, " + pp->STA, // " sta, " + pp->CHA, // " cha, " + pp->DEX, // " dex, " + pp->INT, // " `int`, " + pp->AGI, // " agi, " + pp->WIS, // " wis, " + pp->face, // " face, " + pp->y, // " y, " + pp->x, // " x, " + pp->z, // " z, " + pp->heading, // " heading, " + pp->pvp2, // " pvp2, " + pp->pvptype, // " pvp_type, " + pp->autosplit, // " autosplit_enabled, " + pp->zone_change_count, // " zone_change_count, " + pp->drakkin_heritage, // " drakkin_heritage, " + pp->drakkin_tattoo, // " drakkin_tattoo, " + pp->drakkin_details, // " drakkin_details, " + pp->toxicity, // " toxicity, " + pp->hunger_level, // " hunger_level, " + pp->thirst_level, // " thirst_level, " + pp->ability_up, // " ability_up, " + pp->zone_id, // " zone_id, " + pp->zoneInstance, // " zone_instance, " + pp->leadAAActive, // " leadership_exp_on, " + pp->ldon_points_guk, // " ldon_points_guk, " + pp->ldon_points_mir, // " ldon_points_mir, " + pp->ldon_points_mmc, // " ldon_points_mmc, " + pp->ldon_points_ruj, // " ldon_points_ruj, " + pp->ldon_points_tak, // " ldon_points_tak, " + pp->ldon_points_available, // " ldon_points_available, " + pp->tribute_time_remaining, // " tribute_time_remaining, " + pp->showhelm, // " show_helm, " + pp->career_tribute_points, // " career_tribute_points, " + pp->tribute_points, // " tribute_points, " + pp->tribute_active, // " tribute_active, " + pp->endurance, // " endurance, " + pp->group_leadership_exp, // " group_leadership_exp, " + pp->raid_leadership_exp, // " raid_leadership_exp, " + pp->group_leadership_points, // " group_leadership_points, " + pp->raid_leadership_points, // " raid_leadership_points, " + pp->air_remaining, // " air_remaining, " + pp->PVPKills, // " pvp_kills, " + pp->PVPDeaths, // " pvp_deaths, " + pp->PVPCurrentPoints, // " pvp_current_points, " + pp->PVPCareerPoints, // " pvp_career_points, " + pp->PVPBestKillStreak, // " pvp_best_kill_streak, " + pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, " + pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, " + pp->aapoints_spent, // " aa_points_spent, " + pp->expAA, // " aa_exp, " + pp->aapoints, // " aa_points, " + pp->groupAutoconsent, // " group_auto_consent, " + pp->raidAutoconsent, // " raid_auto_consent, " + pp->guildAutoconsent, // " guild_auto_consent, " + pp->RestTimer // " RestTimer) " + ); + auto results = QueryDatabase(query); + return true; +} + +/* This only for new Character creation storing */ +bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) { + uint32 charid = 0; char zone[50]; float x, y, z; charid = GetCharacterID(pp->name); - if(!charid) - { + if(!charid) { LogFile->write(EQEMuLog::Error, "StoreCharacter: no character id"); return false; } const char *zname = GetZoneName(pp->zone_id); if(zname == nullptr) { - //zone not in the DB, something to prevent crash... + /* Zone not in the DB, something to prevent crash... */ strn0cpy(zone, "qeynos", 49); pp->zone_id = 1; - } else - strn0cpy(zone, zname, 49); - - x=pp->x; - y=pp->y; - z=pp->z; - - // construct the character_ query - end += sprintf(end, - "UPDATE character_ SET timelaston=0, " - "zonename=\'%s\', x=%f, y=%f, z=%f, profile=\'", - zone, x, y, z - ); - end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end, "\', extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end, "\' WHERE account_id=%d AND name='%s'",account_id, pp->name); - - auto results = QueryDatabase(query, (uint32) (end - query)); - // stack assigned query, no need to delete it. - - if(!results.RowsAffected()) - { - LogFile->write(EQEMuLog::Error, "StoreCharacter query '%s' %s", query, results.ErrorMessage().c_str()); - return false; } + else{ strn0cpy(zone, zname, 49); } - // now the inventory + x = pp->x; + y = pp->y; + z = pp->z; + + /* Saves Player Profile Data to `character_data` */ + SaveCharacterCreate(charid, account_id, pp); + + /* Insert starting inventory... */ std::string invquery; - for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;) - { + for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;) { const ItemInst* newinv = inv->GetItem(i); - if (newinv) - { + if (newinv) { invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", charid, i, newinv->GetItem()->ID, newinv->GetCharges(), newinv->GetColor()); @@ -624,69 +694,41 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven #endif } - if (i == MainCursor) { - i = EmuConstants::GENERAL_BAGS_BEGIN; - continue; - } - else if (i == EmuConstants::CURSOR_BAG_END) { - i = EmuConstants::BANK_BEGIN; - continue; - } - else if (i == EmuConstants::BANK_END) { - i = EmuConstants::BANK_BAGS_BEGIN; - continue; - } - + if (i == MainCursor) { i = EmuConstants::GENERAL_BAGS_BEGIN; continue; } + else if (i == EmuConstants::CURSOR_BAG_END) { i = EmuConstants::BANK_BEGIN; continue; } + else if (i == EmuConstants::BANK_END) { i = EmuConstants::BANK_BAGS_BEGIN; continue; } i++; } return true; } -//0=failure, otherwise returns the char ID for the given char name. uint32 Database::GetCharacterID(const char *name) { - uint32 cid = 0; - if(GetAccountIDByChar(name, &cid) == 0) - return(0); - return(cid); + std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); + auto results = QueryDatabase(query); + auto row = results.begin(); + if (row[0]){ return atoi(row[0]); } + return 0; } /* -This function returns the account_id that owns the character with -the name "name" or zero if no character with that name was found -Zero will also be returned if there is a database error. + This function returns the account_id that owns the character with + the name "name" or zero if no character with that name was found + Zero will also be returned if there is a database error. */ -uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", charname); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; - return 0; - } - - if (results.RowCount() != 1) - return 0; - +uint32 Database::GetAccountIDByChar(const char* charname) { + uint32 accountId = 0; + std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE `name` = '%s' LIMIT 1", charname); + auto results = QueryDatabase(query); auto row = results.begin(); - - uint32 accountId = atoi(row[0]); - - if (oCharID) - *oCharID = atoi(row[1]); - + if (row[0]){ accountId = atoi(row[0]); } return accountId; } // Retrieve account_id for a given char_id uint32 Database::GetAccountIDByChar(uint32 char_id) { - std::string query = StringFormat("SELECT account_id FROM character_ WHERE id=%i", char_id); - - auto results = QueryDatabase(query); - - if (!results.Success()) - { + std::string query = StringFormat("SELECT `account_id` FROM `character_` WHERE `id` = %i LIMIT 1", char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return 0; } @@ -694,8 +736,7 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { if (results.RowCount() != 1) return 0; - auto row = results.begin(); - + auto row = results.begin(); return atoi(row[0]); } @@ -703,11 +744,10 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* if (!isAlphaNumeric(accname)) return 0; - std::string query = StringFormat("SELECT id, status, lsaccount_id FROM account WHERE name='%s'", accname); + std::string query = StringFormat("SELECT `id`, `status`, `lsaccount_id` FROM `account` WHERE `name` = '%s' LIMIT 1", accname); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -722,8 +762,7 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* if (status) *status = atoi(row[1]); - if (lsid) - { + if (lsid) { if (row[2]) *lsid = atoi(row[2]); else @@ -734,12 +773,10 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* } void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID) { - std::string query = StringFormat("SELECT name, lsaccount_id FROM account WHERE id='%i'", accountid); - + std::string query = StringFormat("SELECT `name`, `lsaccount_id` FROM `account` WHERE `id` = '%i'", accountid); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in GetAccountName query '" << query << "' " << results.ErrorMessage() << std::endl; return; } @@ -773,11 +810,9 @@ void Database::GetCharName(uint32 char_id, char* name) { } static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { - if ((x != n) && (x % (n / 100 + 1) != 0)) return; - + if ((x != n) && (x % (n / 100 + 1) != 0)) return; float ratio = x / (float)n; - int c = ratio * w; - + int c = ratio * w; std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; for (int x = 0; xcareerRadCrystals, pp->currentEbonCrystals, pp->careerEbonCrystals - ); + ); auto results = QueryDatabase(rquery); if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } @@ -1228,7 +1322,7 @@ bool Database::CheckDatabaseConversions() { "drakkin_heritage," "drakkin_tattoo," "drakkin_details," - "toxicity," + "toxicity," "hunger_level," "thirst_level," "ability_up," @@ -1319,7 +1413,7 @@ bool Database::CheckDatabaseConversions() { "%u," // drakkin_heritage "%u," // drakkin_tattoo "%u," // drakkin_details - "%u," // toxicity + "%i," // toxicity "%u," // hunger_level "%u," // thirst_level "%u," // ability_up @@ -1463,35 +1557,38 @@ bool Database::CheckDatabaseConversions() { } /* Run Bind Home Convert */ - rquery = StringFormat("REPLACE INTO `character_bind_home` (id, zone_id, instance_id, x, y, z, heading)" - " VALUES (%u, %u, %u, %f, %f, %f, %f)", + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + + /* Run Bind Convert */ + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Language Convert */ for (i = 0; i < MAX_PP_LANGUAGE; i++){ if (pp->languages[i] > 0){ rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Skill Convert */ for (i = 0; i < MAX_PP_SKILL; i++){ - if (pp->skills[i] > 0){ + if (pp->skills[i] > 0){ rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Spell Convert */ for (i = 0; i < MAX_PP_SPELLBOOK; i++){ - if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295){ + if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Max Memmed Spell Convert */ for (i = 0; i < MAX_PP_MEMSPELL; i++){ if (pp->mem_spells[i] > 0){ @@ -1499,12 +1596,11 @@ bool Database::CheckDatabaseConversions() { QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } - /* Run Discipline Convert */ for (i = 0; i < MAX_PP_DISCIPLINES; i++){ if (pp->disciplines.values[i] > 0){ - rquery = StringFormat("REPLACE INTO `character_disciplines` (id, disc_id) VALUES (%u, %u)", character_id, pp->disciplines.values[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } /* Run Material Color Convert */ @@ -1512,9 +1608,32 @@ bool Database::CheckDatabaseConversions() { if (pp->item_tint[i].color > 0){ 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); // printf("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u);\n", 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); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } } + /* Run Tribute Convert */ + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0){ + rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + } + /* Run Bandolier Convert */ + for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + if (pp->bandoliers[i].items[si].item_id > 0){ + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + } + } + /* Run Potion Belt Convert */ + for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ + if (pp->potionbelt.items[i].item_id > 0){ + rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + } } /* Print out the entire Player Profile for testing */ @@ -2283,7 +2402,7 @@ bool Database::AddToNameFilter(const char* name) { } uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* oStatus) { - + uint32 account_id = 0; std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID); auto results = QueryDatabase(query); @@ -2296,14 +2415,14 @@ uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* o if (results.RowCount() != 1) return 0; - auto row = results.begin(); + for (auto row = results.begin(); row != results.end(); ++row) { + account_id = atoi(row[0]); - uint32 account_id = atoi(row[0]); - - if (oAccountName) - strcpy(oAccountName, row[1]); - if (oStatus) - *oStatus = atoi(row[2]); + if (oAccountName) + strcpy(oAccountName, row[1]); + if (oStatus) + *oStatus = atoi(row[2]); + } return account_id; } @@ -2339,11 +2458,9 @@ void Database::ClearMerchantTemp(){ std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; } -bool Database::UpdateName(const char* oldname, const char* newname) { - - std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; - - std::string query = StringFormat("UPDATE character_ SET name='%s' WHERE name='%s';", newname, oldname); +bool Database::UpdateName(const char* oldname, const char* newname) { + std::cout << "Renaming " << oldname << " to " << newname << "..." << std::endl; + std::string query = StringFormat("UPDATE `character_data` SET `name` = '%s' WHERE `name` = '%s';", newname, oldname); auto results = QueryDatabase(query); if (!results.Success()) @@ -2356,13 +2473,10 @@ bool Database::UpdateName(const char* oldname, const char* newname) { } // If the name is used or an error occurs, it returns false, otherwise it returns true -bool Database::CheckUsedName(const char* name) -{ - std::string query = StringFormat("SELECT id FROM character_ where name='%s'", name); - auto results = QueryDatabase(query); - - if (!results.Success()) - { +bool Database::CheckUsedName(const char* name) { + std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); + auto results = QueryDatabase(query); + if (!results.Success()) { std::cerr << "Error in CheckUsedName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2373,13 +2487,10 @@ bool Database::CheckUsedName(const char* name) return true; } -uint8 Database::GetServerType() -{ - std::string query("SELECT value FROM variables WHERE varname='ServerType'"); - auto results = QueryDatabase(query); - - if (!results.Success()) - { +uint8 Database::GetServerType() { + std::string query("SELECT `value` FROM `variables` WHERE `varname` = 'ServerType' LIMIT 1"); + auto results = QueryDatabase(query); + if (!results.Success()) { std::cerr << "Error in GetServerType query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -2391,15 +2502,14 @@ uint8 Database::GetServerType() return atoi(row[0]); } -bool Database::MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid) { +bool Database::MoveCharacterToZone(const char* charname, const char* zonename, uint32 zoneid) { if(zonename == nullptr || strlen(zonename) == 0) return false; - std::string query = StringFormat("UPDATE character_ SET zonename = '%s',zoneid=%i,x=-1, y=-1, z=-1 WHERE name='%s'", zonename,zoneid, charname); + std::string query = StringFormat("UPDATE `character_data` SET `zoneid` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `name` = '%s'", zoneid, charname); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2414,13 +2524,11 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) { return MoveCharacterToZone(charname, zonename, GetZoneID(zonename)); } -bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { - - std::string query = StringFormat("UPDATE character_ SET zonename = '%s', zoneid=%i, x=-1, y=-1, z=-1 WHERE id=%i", iZonename, GetZoneID(iZonename), iCharID); +bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { + std::string query = StringFormat("UPDATE `character_data` SET `zoneid` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", iZonename, GetZoneID(iZonename), iCharID); auto results = QueryDatabase(query); - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2428,57 +2536,11 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { return results.RowsAffected() != 0; } -uint8 Database::CopyCharacter(const char* oldname, const char* newname, uint32 acctid) { - - PlayerProfile_Struct* pp; - ExtendedProfile_Struct* ext; - - std::string query = StringFormat("SELECT profile, extprofile FROM character_ WHERE name='%s'", oldname); +bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { + std::string query = StringFormat("INSERT INTO `hackers` (account, name, hacked) values('%s','%s','%s')", accountname, charactername, hacked); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cerr << "Error in CopyCharacter read query '" << query << "' " << results.ErrorMessage() << std::endl; - return 0; - } - - auto row = results.begin(); - - pp = (PlayerProfile_Struct*)row[0]; - strcpy(pp->name, newname); - - ext = (ExtendedProfile_Struct*)row[1]; - - char query2[276 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 1]; - char* end=query2; - - end += sprintf(end, "INSERT INTO character_ SET zonename=\'%s\', x = %f, y = %f, z = %f, profile=\'", GetZoneName(pp->zone_id), pp->x, pp->y, pp->z); - end += DoEscapeString(end, (char*) pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end,"\', extprofile=\'"); - end += DoEscapeString(end, (char*) ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end, "\', account_id=%d, name='%s'", acctid, newname); - - results = QueryDatabase(query2, (uint32) (end - query2)); - - if (!results.Success()) - { - std::cerr << "Error in CopyCharacter query '" << query2 << "' " << results.ErrorMessage() << std::endl; - return 0; - } - - if (results.RowsAffected() == 0) - return 0; - - return 1; -} - -bool Database::SetHackerFlag(const char* accountname, const char* charactername, const char* hacked) { - - std::string query = StringFormat("INSERT INTO hackers(account,name,hacked) values('%s','%s','%s')", accountname, charactername, hacked); - auto results = QueryDatabase(query); - - if (!results.Success()) - { + if (!results.Success()) { std::cerr << "Error in SetHackerFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2486,8 +2548,7 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, return results.RowsAffected() != 0; } -bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { - +bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Utilize the "hacker" table, but also give zone information. std::string query = StringFormat("INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone); auto results = QueryDatabase(query); @@ -2573,8 +2634,6 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo std::string query = StringFormat("SELECT `id`, `account_id`, `zone_id`, `zone_instance`, `x`, `y`, `z` FROM `character_data` WHERE `name` = '%s'", iName); auto results = QueryDatabase(query); - printf("Calling Database::GetCharacterInfo: ACCID: %u ZONEID: %u INSTANCEID: %u \n", oAccID, oZoneID, oInstanceID); - if (!results.Success()) { std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; @@ -2583,7 +2642,7 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo if (results.RowCount() != 1) return 0; - auto row = results.begin(); + auto row = results.begin(); uint32 charid = atoi(row[0]); if (oAccID){ *oAccID = atoi(row[1]); } if (oZoneID){ *oZoneID = atoi(row[2]); } @@ -2592,8 +2651,6 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo if (oY){ *oY = atof(row[5]); } if (oZ){ *oZ = atof(row[6]); } - printf("Calling Database::GetCharacterInfo: ACCID: %u ZONEID: %u INSTANCEID: %u \n", oAccID, oZoneID, oInstanceID); - return charid; } @@ -2631,45 +2688,35 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { return true; } -void Database::SetLFP(uint32 CharID, bool LFP) { - - std::string query = StringFormat("update character_ set lfp=%i where id=%i",LFP, CharID); - auto results = QueryDatabase(query); - +void Database::SetLFP(uint32 CharID, bool LFP) { + std::string query = StringFormat("UPDATE `character_data` SET `lfp` = %i WHERE `id` = %i",LFP, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { - - std::string query = StringFormat("update character_ set lfp=%i, lfg=%i, firstlogon=%i where id=%i",LFP, LFG, firstlogon, CharID); - auto results = QueryDatabase(query); - +void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { + std::string query = StringFormat("update `character_data` SET `lfp` = %i, `lfg` = %i, `firstlogon` = %i WHERE `id` = %i",LFP, LFG, firstlogon, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::SetLFG(uint32 CharID, bool LFG) { - - std::string query = StringFormat("update character_ set lfg=%i where id=%i",LFG, CharID); - auto results = QueryDatabase(query); - +void Database::SetLFG(uint32 CharID, bool LFG) { + std::string query = StringFormat("update `character_data` SET `lfg` = %i WHERE `id` = %i",LFG, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { - - std::string query = StringFormat( "update character_ set firstlogon=%i where id=%i",firstlogon, CharID); - auto results = QueryDatabase(query); - +void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { + std::string query = StringFormat( "UPDATE `character_data` SET `firstlogon` = %i WHERE `id` = %i",firstlogon, CharID); + auto results = QueryDatabase(query); if (!results.Success()) LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, results.ErrorMessage().c_str()); } -void Database::AddReport(std::string who, std::string against, std::string lines) -{ - +void Database::AddReport(std::string who, std::string against, std::string lines) { char *escape_str = new char[lines.size()*2+1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); @@ -2681,11 +2728,9 @@ void Database::AddReport(std::string who, std::string against, std::string lines LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), results.ErrorMessage().c_str()); } -void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc){ - +void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc) { std::string query; - if (id == 0) - { + if (id == 0) { // removing from group query = StringFormat("delete from group_id where charid=%i and name='%s' and ismerc=%i",charid, name, ismerc); auto results = QueryDatabase(query); @@ -2696,8 +2741,8 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism return; } - // adding to group - query = StringFormat("replace into group_id set charid=%i, groupid=%i, name='%s', ismerc='%i'",charid, id, name, ismerc); + /* Add to the Group */ + query = StringFormat("REPLACE INTO `group_id` SET `charid` = %i, `groupid` = %i, `name` = '%s', `ismerc` = '%i'", charid, id, name, ismerc); auto results = QueryDatabase(query); if (!results.Success()) @@ -2755,46 +2800,34 @@ uint32 Database::GetGroupID(const char* name){ return atoi(row[0]); } -char* Database::GetGroupLeaderForLogin(const char* name,char* leaderbuf){ - - PlayerProfile_Struct pp; - - std::string query = StringFormat("SELECT profile from character_ where name='%s'", name); +/* Is this really getting used properly... A half implementation ? Akkadius */ +char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf){ + std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name = '%s'", name); auto results = QueryDatabase(query); + auto row = results.begin(); uint32 group_id = 0; + if (row[0]){ group_id = atoi(row[0]); } - if (!results.Success()) - { - std::cout << "Unable to get leader name: " << results.ErrorMessage() << std::endl; - return leaderbuf; - } - - if (results.LengthOfColumn(0) != sizeof(PlayerProfile_Struct)) - return leaderbuf; - - auto row = results.begin(); - - memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); - strcpy(leaderbuf,pp.groupMembers[0]); + query = StringFormat("SELECT `name` FROM `group_id` WHERE `name` != '%s' AND `groupid` = %u", name, group_id); + results = QueryDatabase(query); + row = results.begin(); + if (row[0]){ strcpy(leaderbuf, row[0]); } return leaderbuf; } -void Database::SetGroupLeaderName(uint32 gid, const char* name) { - - std::string query = StringFormat("Replace into group_leaders set gid=%lu, leadername='%s'",(unsigned long)gid,name); +void Database::SetGroupLeaderName(uint32 gid, const char* name) { + std::string query = StringFormat("REPLACE INTO `group_leaders` SET `gid` = %lu, `leadername` = '%s'",(unsigned long)gid,name); auto results = QueryDatabase(query); if (!results.Success()) std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; } -char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ - - std::string query = StringFormat("SELECT leadername, maintank, assist, puller, marknpc, leadershipaa FROM group_leaders WHERE gid=%lu",(unsigned long)gid); +char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ + std::string query = StringFormat("SELECT `leadername`, `maintank`, `assist`, `puller`, `marknpc`, `leadershipaa` FROM `group_leaders` WHERE `gid` = %lu",(unsigned long)gid); auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) - { + if (!results.Success() || results.RowCount() == 0) { if(leaderbuf) strcpy(leaderbuf, "UNKNOWN"); @@ -2837,8 +2870,7 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta } // Clearing all group leaders -void Database::ClearAllGroupLeaders(void) -{ +void Database::ClearAllGroupLeaders(void) { std::string query("DELETE from group_leaders"); auto results = QueryDatabase(query); @@ -2863,8 +2895,7 @@ void Database::ClearGroupLeader(uint32 gid) { std::cout << "Unable to clear group leader: " << results.ErrorMessage() << std::endl; } -uint8 Database::GetAgreementFlag(uint32 acctid) -{ +uint8 Database::GetAgreementFlag(uint32 acctid) { std::string query = StringFormat("SELECT rulesflag FROM account WHERE id=%i",acctid); auto results = QueryDatabase(query); @@ -2880,14 +2911,12 @@ uint8 Database::GetAgreementFlag(uint32 acctid) return atoi(row[0]); } -void Database::SetAgreementFlag(uint32 acctid) -{ +void Database::SetAgreementFlag(uint32 acctid) { std::string query = StringFormat("UPDATE account SET rulesflag=1 where id=%i", acctid); QueryDatabase(query); } void Database::ClearRaid(uint32 rid) { - if(rid == 0) { //clear all raids @@ -2903,8 +2932,7 @@ void Database::ClearRaid(uint32 rid) { std::cout << "Unable to clear raids: " << results.ErrorMessage() << std::endl; } -void Database::ClearAllRaids(void) -{ +void Database::ClearAllRaids(void) { std::string query("delete from raid_members"); auto results = QueryDatabase(query); diff --git a/common/database.h b/common/database.h index a22e6d406..c70464094 100644 --- a/common/database.h +++ b/common/database.h @@ -105,10 +105,16 @@ public: Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); ~Database(); + bool ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query); + /* * General Character Related Stuff */ + + /* Character Creation */ + bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool MoveCharacterToZone(const char* charname, const char* zonename); bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid); bool MoveCharacterToZone(uint32 iCharID, const char* iZonename); @@ -118,16 +124,15 @@ public: bool AddToNameFilter(const char* name); bool ReserveName(uint32 account_id, char* name); bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face); - bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext); + bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv); bool DeleteCharacter(char* name); - uint8 CopyCharacter(const char* oldname, const char* newname, uint32 acctid); /* * General Information Getting Queries */ bool CheckNameFilter(const char* name, bool surname = false); bool CheckUsedName(const char* name); - uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); + uint32 GetAccountIDByChar(const char* charname); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); uint32 GetGuildIDByCharID(uint32 char_id); @@ -252,10 +257,6 @@ public: void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); void AddReport(std::string who, std::string against, std::string lines); - -protected: - void HandleMysqlError(uint32 errnum); - private: void DBInitVars(); diff --git a/common/dbasync.cpp b/common/dbasync.cpp deleted file mode 100644 index 00714c2a0..000000000 --- a/common/dbasync.cpp +++ /dev/null @@ -1,669 +0,0 @@ -#include "debug.h" -#ifdef _WINDOWS - #include - #include - #include -#endif -#include -#include "dbasync.h" -#include "database.h" -#include -#include -#include -#include "dbcore.h" -#include -//#include "../common/misc_functions.h" -#include "string_util.h" -#define ASYNC_LOOP_GRANULARITY 4 //# of ms between checking our work - -bool DBAsyncCB_LoadVariables(DBAsyncWork* iWork) { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES* result = 0; - DBAsyncQuery* dbaq = iWork->PopAnswer(); - if (dbaq->GetAnswer(errbuf, &result)) - iWork->GetDB()->LoadVariables_result(result); - else - std::cout << "Error: DBAsyncCB_LoadVariables failed: !GetAnswer: '" << errbuf << "'" << std::endl; - return true; -} - -void AsyncLoadVariables(DBAsync *dba, Database *db) { - char* query = 0; - DBAsyncWork* dbaw = new DBAsyncWork(db, &DBAsyncCB_LoadVariables, 0, DBAsync::Read); - dbaw->AddQuery(0, &query, db->LoadVariables_MQ(&query)); - dba->AddWork(&dbaw); -} - - -//we only need to do anything when somebody puts work on the queue -//so instead of checking all the time, we will wait on a condition -//which will get signaled when somebody puts something on the queue -ThreadReturnType DBAsyncLoop(void* tmp) { - DBAsync* dba = (DBAsync*) tmp; - -#ifndef WIN32 - _log(COMMON__THREADS, "Starting DBAsyncLoop with thread ID %d", pthread_self()); -#endif - - dba->MLoopRunning.lock(); - while (dba->RunLoop()) { - //wait before working so we check the loop condition - //as soon as were done working - dba->CInList.Wait(); - //we could check dba->RunLoop() again to see if we - //got turned off while we were waiting - { - dba->Process(); - } - } - dba->MLoopRunning.unlock(); - -#ifndef WIN32 - _log(COMMON__THREADS, "Ending DBAsyncLoop with thread ID %d", pthread_self()); -#endif - - THREAD_RETURN(nullptr); -} - -DBAsync::DBAsync(DBcore* iDBC) -: Timeoutable(10000) -{ - pDBC = iDBC; - pRunLoop = true; - pNextID = 1; -#ifdef _WINDOWS - _beginthread(DBAsyncLoop, 0, this); -#else - pthread_t thread; - pthread_create(&thread, nullptr, DBAsyncLoop, this); -#endif -} - -DBAsync::~DBAsync() { - StopThread(); -} - -bool DBAsync::StopThread() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - pRunLoop = false; - MRunLoop.unlock(); - - //signal the condition so we exit the loop if were waiting - CInList.Signal(); - - //this effectively waits for the processing thread to finish - MLoopRunning.lock(); - MLoopRunning.unlock(); - - return ret; -} - -uint32 DBAsync::AddWork(DBAsyncWork** iWork, uint32 iDelay) { - MInList.lock(); - uint32 ret = GetNextID(); - if (!(*iWork)->SetWorkID(ret)) { - MInList.unlock(); - return 0; - } - InList.Append(*iWork); - (*iWork)->SetStatus(Queued); - if (iDelay) - (*iWork)->pExecuteAfter = Timer::GetCurrentTime() + iDelay; -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "Adding AsyncWork #" << (*iWork)->GetWorkID() << std::endl; - std::cout << "ExecuteAfter = " << (*iWork)->pExecuteAfter << " (" << Timer::GetCurrentTime() << " + " << iDelay << ")" << std::endl; -#endif - *iWork = 0; - MInList.unlock(); - - //wake up the processing thread and tell it to get to work. - CInList.Signal(); - - return ret; -} - -bool DBAsync::CancelWork(uint32 iWorkID) { - if (iWorkID == 0) - return false; -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "DBAsync::CancelWork: " << iWorkID << std::endl; -#endif - MCurrentWork.lock(); - if (CurrentWork && CurrentWork->GetWorkID() == iWorkID) { - CurrentWork->Cancel(); - MCurrentWork.unlock(); - return true; - } - MCurrentWork.unlock(); - MInList.lock(); - LinkedListIterator iterator(InList); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->GetWorkID() == iWorkID) { - iterator.RemoveCurrent(true); - MInList.unlock(); - return true; - } - iterator.Advance(); - } - MInList.unlock(); - return false; -} - -bool DBAsync::RunLoop() { - bool ret; - MRunLoop.lock(); - ret = pRunLoop; - MRunLoop.unlock(); - return ret; -} - -DBAsyncWork* DBAsync::InListPop() { - DBAsyncWork* ret = 0; - MInList.lock(); - LinkedListIterator iterator(InList); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->pExecuteAfter <= Timer::GetCurrentTime()) { - ret = iterator.GetData(); -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "Poping AsyncWork #" << ret->GetWorkID() << std::endl; - std::cout << ret->pExecuteAfter << " <= " << Timer::GetCurrentTime() << std::endl; -#endif - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MInList.unlock(); - return ret; -} - -DBAsyncWork* DBAsync::InListPopWrite() { - MInList.lock(); - LinkedListIterator iterator(InList); - - DBAsyncWork* ret = 0; - DBAsync::Type tmpType; - iterator.Reset(); - while (iterator.MoreElements()) { - tmpType = iterator.GetData()->Type(); - if (tmpType == Write || tmpType == Both) { - ret = iterator.GetData(); - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MInList.unlock(); - return ret; -} - -void DBAsync::AddFQ(DBAsyncFinishedQueue* iDBAFQ) { - MFQList.lock(); - DBAsyncFinishedQueue** tmp = new DBAsyncFinishedQueue*; - *tmp = iDBAFQ; - FQList.Append(tmp); - MFQList.unlock(); -} - -void DBAsync::Process() { - DBAsyncWork* tmpWork; - MCurrentWork.lock(); - while ((CurrentWork = InListPop())) { - MCurrentWork.unlock(); - //move from queued to executing - Status tmpStatus = CurrentWork->SetStatus(Executing); - if (tmpStatus == Queued) { - //execute the work - ProcessWork(CurrentWork); - tmpWork = CurrentWork; - MCurrentWork.lock(); - CurrentWork = 0; - MCurrentWork.unlock(); - //move from executing to finished - tmpStatus = tmpWork->SetStatus(DBAsync::Finished); - if (tmpStatus != Executing) { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #1" << std::endl; - } - MCurrentWork.lock(); - safe_delete(tmpWork); - } - else { - //call callbacks or put results on finished queue - DispatchWork(tmpWork); - Sleep(25); - MCurrentWork.lock(); - } - } - else { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #2" << std::endl; - } - MCurrentWork.lock(); - safe_delete(CurrentWork); - } - } - MCurrentWork.unlock(); -} - -void DBAsync::CheckTimeout() { - try{ - MFQList.lock(); - LinkedListIterator iterator(FQList); - - iterator.Reset(); - while (iterator.MoreElements()) { - (*iterator.GetData())->CheckTimeouts(); - iterator.Advance(); - } - MFQList.unlock(); - } - catch(...){ - - } -} - -void DBAsync::CommitWrites() { -#if DEBUG_MYSQL_QUERIES >= 2 - std::cout << "DBAsync::CommitWrites() called." << std::endl; -#endif - DBAsyncWork* tmpWork; - while ((tmpWork = InListPopWrite())) { - Status tmpStatus = tmpWork->SetStatus(Executing); - if (tmpStatus == Queued) { - ProcessWork(tmpWork); - tmpStatus = tmpWork->SetStatus(DBAsync::Finished); - if (tmpStatus != Executing) { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #1" << std::endl; - } - safe_delete(tmpWork); - } - else { - DispatchWork(tmpWork); - } - } - else { - if (tmpStatus != Canceled) { - std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #2" << std::endl; - } - safe_delete(tmpWork); - } - } -} - -void DBAsync::ProcessWork(DBAsyncWork* iWork, bool iSleep) { - DBAsyncQuery* CurrentQuery; - while ((CurrentQuery = iWork->PopQuery())) { - CurrentQuery->Process(pDBC); - iWork->PushAnswer(CurrentQuery); - if (iSleep) - Sleep(1); - } -} - -void DBAsync::DispatchWork(DBAsyncWork* iWork) { - //if this work has a callback, call it - //otherwise, stick the work on the finish queue - if (iWork->pCB) { - if (iWork->pCB(iWork)) - safe_delete(iWork); - } - else { - if (!iWork->pDBAFQ->Push(iWork)) - safe_delete(iWork); - } -} - - - -DBAsyncFinishedQueue::DBAsyncFinishedQueue(uint32 iTimeout) { - pTimeout = iTimeout; -} - -DBAsyncFinishedQueue::~DBAsyncFinishedQueue() { -} - -void DBAsyncFinishedQueue::CheckTimeouts() { - if (pTimeout == 0xFFFFFFFF) - return; - MLock.lock(); - LinkedListIterator iterator(list); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->CheckTimeout(pTimeout)) - iterator.RemoveCurrent(true); - iterator.Advance(); - } - MLock.unlock(); -} - -DBAsyncWork* DBAsyncFinishedQueue::Pop() { - DBAsyncWork* ret = 0; - MLock.lock(); - ret = list.Pop(); - MLock.unlock(); - return ret; -} - -DBAsyncWork* DBAsyncFinishedQueue::Find(uint32 iWorkID) { - DBAsyncWork* ret = 0; - MLock.lock(); - LinkedListIterator iterator(list); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->GetWorkID() == iWorkID) { - ret = iterator.GetData(); - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MLock.unlock(); - return ret; -} - -DBAsyncWork* DBAsyncFinishedQueue::PopByWPT(uint32 iWPT) { - DBAsyncWork* ret = 0; - MLock.lock(); - LinkedListIterator iterator(list); - - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()->WPT() == iWPT) { - ret = iterator.GetData(); - iterator.RemoveCurrent(false); - break; - } - iterator.Advance(); - } - MLock.unlock(); - return ret; -} - -bool DBAsyncFinishedQueue::Push(DBAsyncWork* iDBAW) { - if (!this) - return false; - MLock.lock(); - list.Append(iDBAW); - MLock.unlock(); - return true; -} - - - -DBAsyncWork::DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout) -: m_db(db) -{ - pstatus = DBAsync::AddingWork; - pType = iType; - pExecuteAfter = 0; - pWorkID = 0; - pDBAFQ = iDBAFQ; - pCB = 0; - pWPT = iWPT; - pQuestionCount = 0; - pAnswerCount = 0; - pTimeout = iTimeout; - pTSFinish = 0; -} - -DBAsyncWork::DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout) -: m_db(db) -{ - pstatus = DBAsync::AddingWork; - pType = iType; - pExecuteAfter = 0; - pWorkID = 0; - pDBAFQ = 0; - pCB = iCB; - pWPT = iWPT; - pQuestionCount = 0; - pAnswerCount = 0; - pTimeout = iTimeout; - pTSFinish = 0; -} - -DBAsyncWork::~DBAsyncWork() { - DBAsyncQuery* dbaq = 0; - while ((dbaq = todo.pop())) - safe_delete(dbaq); - while ((dbaq = done.pop())) - safe_delete(dbaq); - while ((dbaq = todel.pop())) - safe_delete(dbaq); -} - -bool DBAsyncWork::AddQuery(DBAsyncQuery** iDBAQ) { - bool ret; - MLock.lock(); - if (pstatus != DBAsync::AddingWork) - ret = false; - else { - ret = true; - pQuestionCount++; - todo.push(*iDBAQ); - (*iDBAQ)->pstatus = DBAsync::Queued; - *iDBAQ = 0; - } - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) { - DBAsyncQuery* DBAQ = new DBAsyncQuery(iQPT, iQuery, iQueryLen, iGetResultSet, iGetErrbuf); - if (AddQuery(&DBAQ)) - return true; - else { - safe_delete(DBAQ); - return false; - } -} - -bool DBAsyncWork::SetWorkID(uint32 iWorkID) { - bool ret = true; - MLock.lock(); - if (pWorkID) - ret = false; - else - pWorkID = iWorkID; - MLock.unlock(); - return ret; -} - -uint32 DBAsyncWork::GetWorkID() { - uint32 ret; - MLock.lock(); - ret = pWorkID; - MLock.unlock(); - return ret; -} - -uint32 DBAsyncWork::WPT() { - uint32 ret; - MLock.lock(); - ret = pWPT; - MLock.unlock(); - return ret; -} - -DBAsync::Type DBAsyncWork::Type() { - DBAsync::Type ret; - MLock.lock(); - ret = pType; - MLock.unlock(); - return ret; -} - -DBAsyncQuery* DBAsyncWork::PopAnswer() { - DBAsyncQuery* ret; - MLock.lock(); - ret = done.pop(); - if (ret) - pAnswerCount--; - todel.push(ret); - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::CheckTimeout(uint32 iFQTimeout) { - if (pTimeout == 0xFFFFFFFF) - return false; - bool ret = false; - MLock.lock(); - if (pTimeout > iFQTimeout) - iFQTimeout = pTimeout; - if (Timer::GetCurrentTime() > (pTSFinish + iFQTimeout)) - ret = true; - MLock.unlock(); - return ret; -} - -//sets the work's status to the supplied value and returns -//the revious status -DBAsync::Status DBAsyncWork::SetStatus(DBAsync::Status iStatus) { - DBAsync::Status ret; - MLock.lock(); - if (iStatus == DBAsync::Finished) - pTSFinish = Timer::GetCurrentTime(); - ret = pstatus; - pstatus = iStatus; - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::Cancel() { - bool ret; - MLock.lock(); - if (pstatus != DBAsync::Finished) { - pstatus = DBAsync::Canceled; - ret = true; - } - else - ret = false; - MLock.unlock(); - return ret; -} - -bool DBAsyncWork::IsCancled() { - bool ret; - MLock.lock(); - ret = (bool) (pstatus == DBAsync::Canceled); - MLock.unlock(); - return ret; -} - -DBAsyncQuery* DBAsyncWork::PopQuery() { - DBAsyncQuery* ret = 0; - MLock.lock(); - ret = todo.pop(); - if (ret) - pQuestionCount--; - MLock.unlock(); - return ret; -} - -void DBAsyncWork::PushAnswer(DBAsyncQuery* iDBAQ) { - MLock.lock(); - done.push(iDBAQ); - pAnswerCount++; - MLock.unlock(); -} - - -DBAsyncQuery::DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) { - if (iQueryLen == 0xFFFFFFFF) - pQueryLen = strlen(*iQuery); - else - pQueryLen = iQueryLen; - pQuery = *iQuery; - *iQuery = 0; - Init(iQPT, iGetResultSet, iGetErrbuf); -} - -DBAsyncQuery::DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) { - if (iQueryLen == 0xFFFFFFFF) - pQueryLen = strlen(iQuery); - else - pQueryLen = iQueryLen; - pQuery = strn0cpy(new char[pQueryLen+1], iQuery, pQueryLen+1); - Init(iQPT, iGetResultSet, iGetErrbuf); -} - -void DBAsyncQuery::Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf) { - pstatus = DBAsync::AddingWork; - pQPT = iQPT; - pGetResultSet = iGetResultSet; - pGetErrbuf = iGetErrbuf; - - pmysqlsuccess = false; - perrbuf = 0; - perrnum = 0; - presult = 0; - paffected_rows = 0; - plast_insert_id = 0; -} - -DBAsyncQuery::~DBAsyncQuery() { - safe_delete_array(perrbuf); - safe_delete_array(pQuery); - if (presult) - mysql_free_result(presult); -} - -bool DBAsyncQuery::GetAnswer(char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum) { - if (pstatus != DBAsync::Finished) { - if (errbuf) - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error: Query not finished."); - if (errnum) - *errnum = UINT_MAX; - return false; - } - if (errbuf) { - if (pGetErrbuf) { - if (perrbuf) - strn0cpy(errbuf, perrbuf, MYSQL_ERRMSG_SIZE); - else - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message should've been saved, but hasnt. errno: %u", perrnum); - } - else - snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message not saved. errno: %u", perrnum); - } - if (errnum) - *errnum = perrnum; - if (affected_rows) - *affected_rows = paffected_rows; - if (last_insert_id) - *last_insert_id = plast_insert_id; - if (result) - *result = presult; - return pmysqlsuccess; -} - -void DBAsyncQuery::Process(DBcore* iDBC) { - pstatus = DBAsync::Executing; - if (pGetErrbuf) - perrbuf = new char[MYSQL_ERRMSG_SIZE]; - MYSQL_RES** resultPP = 0; - if (pGetResultSet) - resultPP = &presult; - pmysqlsuccess = iDBC->RunQuery(pQuery, pQueryLen, perrbuf, resultPP, &paffected_rows, &plast_insert_id, &perrnum); - pstatus = DBAsync::Finished; -} - - - - - - - - - diff --git a/common/dbasync.h b/common/dbasync.h deleted file mode 100644 index f65f9cb58..000000000 --- a/common/dbasync.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef DBASYNC_H -#define DBASYNC_H -#include "../common/dbcore.h" -#include "../common/timeoutmgr.h" - - -class DBAsyncFinishedQueue; -class DBAsyncWork; -class DBAsyncQuery; -class Database; - -// Big daddy that owns the threads and does the work -class DBAsync : private Timeoutable { -public: - enum Status { AddingWork, Queued, Executing, Finished, Canceled }; - enum Type { Read, Write, Both }; - - DBAsync(DBcore* iDBC); - ~DBAsync(); - bool StopThread(); - - uint32 AddWork(DBAsyncWork** iWork, uint32 iDelay = 0); - bool CancelWork(uint32 iWorkID); - void CommitWrites(); - - void AddFQ(DBAsyncFinishedQueue* iDBAFQ); -protected: - //things related to the processing thread: - friend ThreadReturnType DBAsyncLoop(void* tmp); - Mutex MLoopRunning; - Condition CInList; - bool RunLoop(); - void Process(); - -private: - virtual void CheckTimeout(); - - void ProcessWork(DBAsyncWork* iWork, bool iSleep = true); - void DispatchWork(DBAsyncWork* iWork); - inline uint32 GetNextID() { return pNextID++; } - DBAsyncWork* InListPop(); - DBAsyncWork* InListPopWrite(); // Ignores delay - void OutListPush(DBAsyncWork* iDBAW); - - Mutex MRunLoop; - bool pRunLoop; - - DBcore* pDBC; - uint32 pNextID; - Mutex MInList; - LinkedList InList; - - Mutex MFQList; - LinkedList FQList; - - // Mutex for outside access to current work & when current work is being changed. - // NOT locked when CurrentWork is being accessed by the DBAsync thread. - // Never change pointer from outside DBAsync thread! - // Only here for access to thread-safe DBAsyncWork functions. - Mutex MCurrentWork; - DBAsyncWork* CurrentWork; - -}; - -/* - DB Work Complete Callback: - This will be called under the DBAsync thread! Never access any non-threadsafe - data/functions/classes. (ie: zone, entitylist, client, etc are not threadsafe) - Function prototype: - return value: true if we should delete the data, false if we should keep it -*/ -typedef bool(*DBWorkCompleteCallBack)(DBAsyncWork*); - -class DBAsyncFinishedQueue { -public: - DBAsyncFinishedQueue(uint32 iTimeout = 90000); - ~DBAsyncFinishedQueue(); - - DBAsyncWork* Pop(); - DBAsyncWork* PopByWPT(uint32 iWPT); - DBAsyncWork* Find(uint32 iWPT); - bool Push(DBAsyncWork* iDBAW); - - void CheckTimeouts(); -private: - Mutex MLock; - uint32 pTimeout; - LinkedList list; -}; - -// Container class for multiple queries -class DBAsyncWork { -public: - DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0); - DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0); - ~DBAsyncWork(); - - bool AddQuery(DBAsyncQuery** iDBAQ); - bool AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true); - uint32 WPT(); - DBAsync::Type Type(); - - // Pops finished queries off the work - DBAsyncQuery* PopAnswer(); - uint32 QueryCount(); - - Database *GetDB() const { return(m_db); } - - bool CheckTimeout(uint32 iFQTimeout); - bool SetWorkID(uint32 iWorkID); - uint32 GetWorkID(); -protected: - friend class DBAsync; - DBAsync::Status SetStatus(DBAsync::Status iStatus); - bool Cancel(); - bool IsCancled(); - DBAsyncQuery* PopQuery(); // Get query to be run - void PushAnswer(DBAsyncQuery* iDBAQ); // Push answer back into workset - - // not mutex'd cause only to be accessed from dbasync class - uint32 pExecuteAfter; -private: - Mutex MLock; - uint32 pQuestionCount; - uint32 pAnswerCount; - uint32 pWorkID; - uint32 pWPT; - uint32 pTimeout; - uint32 pTSFinish; // timestamp when finished - DBAsyncFinishedQueue* pDBAFQ; //we do now own this pointer - DBWorkCompleteCallBack pCB; - DBAsync::Status pstatus; - DBAsync::Type pType; - MyQueue todo; - MyQueue done; - MyQueue todel; - Database *const m_db; //we do now own this pointer -}; - -// Container class for the query information -class DBAsyncQuery { -public: - DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true); - DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true); - ~DBAsyncQuery(); - - bool GetAnswer(char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0); - inline uint32 QPT() { return pQPT; } -protected: - friend class DBAsyncWork; - uint32 pQPT; - - friend class DBAsync; - void Process(DBcore* iDBC); - - void Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf); - DBAsync::Status pstatus; - char* pQuery; - uint32 pQueryLen; - bool pGetResultSet; - bool pGetErrbuf; - - bool pmysqlsuccess; - char* perrbuf; - uint32 perrnum; - uint32 paffected_rows; - uint32 plast_insert_id; - MYSQL_RES* presult; -}; - - -void AsyncLoadVariables(DBAsync *dba, Database *db); - - -#endif - diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c561e3a22..061f498d4 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -800,9 +800,12 @@ struct SuspendedMinion_Struct ** Length: 4308 bytes ** OpCode: 0x006a */ -static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF -static const uint32 MAX_PP_MEMSPELL = 9; +static const uint32 MAX_PP_LANGUAGE = 28; +static const uint32 MAX_PP_SPELLBOOK = 720; // Set for all functions +static const uint32 MAX_PP_MEMSPELL = 12; // Set to latest client so functions can work right +static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain +static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain + static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size static const uint32 MAX_PP_AA_ARRAY = 240; static const uint32 MAX_GROUP_MEMBERS = 6; @@ -880,7 +883,7 @@ struct PlayerProfile_Struct /*0245*/ uint8 guildbanker; /*0246*/ uint8 unknown0246[6]; // /*0252*/ uint32 intoxication; -/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms +/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms /*0292*/ uint32 abilitySlotRefresh; /*0296*/ uint8 haircolor; // Player hair color /*0297*/ uint8 beardcolor; // Player beard color @@ -919,9 +922,9 @@ struct PlayerProfile_Struct /*2505*/ uint8 unknown2541[47]; // ? /*2552*/ uint8 languages[MAX_PP_LANGUAGE]; /*2580*/ uint8 unknown2616[4]; -/*2584*/ uint32 spell_book[MAX_PP_SPELLBOOK]; +/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK]; /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff -/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL]; +/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL]; /*4668*/ uint8 unknown4704[32]; // /*4700*/ float y; // Player y position /*4704*/ float x; // Player x position diff --git a/common/mysql_request_result.cpp b/common/mysql_request_result.cpp index ffbc3ef40..df598c8cd 100644 --- a/common/mysql_request_result.cpp +++ b/common/mysql_request_result.cpp @@ -32,6 +32,7 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u void MySQLRequestResult::FreeInternals() { + safe_delete_array(m_ErrorBuffer); if (m_Result != nullptr) diff --git a/common/mysql_request_result.h b/common/mysql_request_result.h index cd561be56..693c4d43a 100644 --- a/common/mysql_request_result.h +++ b/common/mysql_request_result.h @@ -40,7 +40,7 @@ public: MySQLRequestResult& operator=(MySQLRequestResult&& other); bool Success() const { return m_Success;} - std::string ErrorMessage() const {return std::string(m_ErrorBuffer);} + std::string ErrorMessage() const { return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string(""); } uint32 ErrorNumber() const {return m_ErrorNumber;} uint32 RowsAffected() const {return m_RowsAffected;} uint32 RowCount() const {return m_RowCount;} diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 6124d37f1..f6f960cc3 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -61,46 +61,6 @@ bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) return true; } -bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 affected_rows = 0; - bool ret = false; - - if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { - ret = (affected_rows != 0); - } - - if (!ret) { - LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -// Generate SQL for updating player profile -uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - *query = new char[396 + sizeof(PlayerProfile_Struct)* 2 + sizeof(ExtendedProfile_Struct)* 2 + 4]; - char* end = *query; - if (!current_zone) - current_zone = pp->zone_id; - - if (!current_instance) - current_instance = pp->zoneInstance; - - if (strlen(pp->name) == 0) // Sanity check in case pp never loaded - return false; - - end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, ", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); - // end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end, " extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end, "\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); - - return (uint32)(end - (*query)); -} - uint8 SharedDatabase::GetGMSpeed(uint32 account_id) { @@ -386,12 +346,11 @@ int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) return 0; } -bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) -{ +bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `sharedplat` = `sharedplat` + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl; safe_delete_array(query); return false; @@ -401,35 +360,24 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) return true; } -bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; +bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { const Item_Struct* myitem; - - RunQuery - ( - query, - MakeAnyLenString - ( - &query, - "SELECT itemid, item_charges, slot FROM starting_items " - "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " - "(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND " - "gm <= %i ORDER BY id", - si_race, si_class, si_deity, si_current_zone, admin_level - ), - errbuf, - &result - ); - safe_delete_array(query); - - while((row = mysql_fetch_row(result))) { - int itemid = atoi(row[0]); - int charges = atoi(row[1]); - int slot = atoi(row[2]); + uint32 itemid = 0; + uint32 charges = 0; + uint32 slot = 0; + auto query = StringFormat( + "SELECT `itemid`, `item_charges`, `slot` FROM `starting_items`" + " WHERE (`race` = %i OR `race` = 0)" + " AND (`class` = %i OR `class` = 0)" + " AND (`deityid` = %i OR `deityid` = 0)" + " AND (`zoneid` = %i OR `zoneid` = 0)" + " AND gm <= %i ORDER BY id", + si_race, si_class, si_deity, si_current_zone, admin_level); + auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + itemid = atoi(row[0]); + charges = atoi(row[1]); + slot = atoi(row[2]); myitem = GetItem(itemid); if(!myitem) continue; @@ -439,9 +387,6 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, inv->PutItem(slot, *myinst); safe_delete(myinst); } - - if(result) mysql_free_result(result); - return true; } @@ -675,8 +620,13 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) bool ret = false; // Retrieve character inventory - if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," - "instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid", + if (RunQuery(query, MakeAnyLenString(&query, + " SELECT `slotid`, `itemid`, `charges`, `color`, `augslot1`, `augslot2`, `augslot3`, `augslot4`, `augslot5`, `instnodrop`, `custom_data`" + " FROM `inventory`" + " INNER JOIN character_ ch ON ch.id = charid" + " WHERE ch.NAME = '%s'" + " AND ch.account_id = % i" + " ORDER BY `slotid`", name, account_id), errbuf, &result)) { while ((row = mysql_fetch_row(result))) { @@ -736,7 +686,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) } } } - if (slot_id>=8000 && slot_id <= 8999) + if (slot_id >= 8000 && slot_id <= 8999) put_slot_id = inv->PushCursor(*inst); else put_slot_id = inv->PutItem(slot_id, *inst); @@ -2053,8 +2003,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { return nullptr; } -void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { - +void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; MYSQL_RES *result; diff --git a/common/shareddb.h b/common/shareddb.h index c55163465..5401bfa0a 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -34,9 +34,6 @@ public: SharedDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port); virtual ~SharedDatabase(); - /* Temp */ - uint32 SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); - bool SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets); /* * General Character Related Stuff */ diff --git a/world/client.cpp b/world/client.cpp index fc7e525db..c8fea66c9 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -64,8 +64,6 @@ extern ClientList client_list; extern uint32 numclients; extern volatile bool RunLoops; - - Client::Client(EQStreamInterface* ieqs) : autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)), CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)), @@ -128,9 +126,8 @@ void Client::SendLogServer() safe_delete(outapp); } -void Client::SendEnterWorld(std::string name) -{ -char char_name[32]= { 0 }; +void Client::SendEnterWorld(std::string name) { + char char_name[32]= { 0 }; if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) { if(database.GetAccountIDByChar(char_name) != GetAccountID()) { eqs->Close(); @@ -472,7 +469,6 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { } bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { - if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account"); return false; @@ -491,19 +487,10 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { outapp->size = 1; bool valid; - if(!database.CheckNameFilter(char_name)) { - valid = false; - } - else if(char_name[0] < 'A' && char_name[0] > 'Z') { - //name must begin with an upper-case letter. - valid = false; - } - else if (database.ReserveName(GetAccountID(), char_name)) { - valid = true; - } - else { - valid = false; - } + if(!database.CheckNameFilter(char_name)) { valid = false; } + else if (char_name[0] < 'A' && char_name[0] > 'Z') { valid = false; } /* Name must begin with an upper-case letter. */ + else if (database.ReserveName(GetAccountID(), char_name)) { valid = true; } + else { valid = false; } outapp->pBuffer[0] = valid? 1 : 0; QueuePacket(outapp); safe_delete(outapp); @@ -642,13 +629,11 @@ bool Client::HandleCharacterCreateRequestPacket(const EQApplicationPacket *app) } bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { - if (GetAccountID() == 0) - { + if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Account ID not set; unable to create character."); return false; } - else if (app->size != sizeof(CharCreate_Struct)) - { + else if (app->size != sizeof(CharCreate_Struct)) { clog(WORLD__CLIENT_ERR,"Wrong size on OP_CharacterCreate. Got: %d, Expected: %d",app->size,sizeof(CharCreate_Struct)); DumpPacket(app); // the previous behavior was essentially returning true here @@ -657,8 +642,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { } CharCreate_Struct *cc = (CharCreate_Struct*)app->pBuffer; - if(OPCharCreate(char_name, cc) == false) - { + if(OPCharCreate(char_name, cc) == false) { database.DeleteCharacter(char_name); EQApplicationPacket *outapp = new EQApplicationPacket(OP_ApproveName, 1); outapp->pBuffer[0] = 0; @@ -675,8 +659,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { return true; } -bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { - +bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Enter world with no logged in account"); eqs->Close(); @@ -713,8 +696,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { return true; } - if(!pZoning && ew->return_home && !ew->tutorial) - { + if(!pZoning && ew->return_home && !ew->tutorial) { CharacterSelect_Struct* cs = new CharacterSelect_Struct; memset(cs, 0, sizeof(CharacterSelect_Struct)); database.GetCharSelectInfo(GetAccountID(), cs); @@ -733,12 +715,10 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } safe_delete(cs); - if(home_enabled) - { + if(home_enabled) { zoneID = database.MoveCharacterToBind(charid,4); } - else - { + else { clog(WORLD__CLIENT_ERR,"'%s' is trying to go home before they're able...",char_name); database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able."); eqs->Close(); @@ -807,16 +787,16 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { database.SetLoginFlags(charid, false, false, 1); } else{ - uint32 groupid=database.GetGroupID(char_name); - if(groupid>0){ - char* leader=0; - char leaderbuf[64]={0}; - if((leader=database.GetGroupLeaderForLogin(char_name,leaderbuf)) && strlen(leader)>1){ + uint32 groupid = database.GetGroupID(char_name); + if(groupid > 0){ + char* leader = 0; + char leaderbuf[64] = {0}; + if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){ EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer; gj->action=8; - strcpy(gj->yourname,char_name); - strcpy(gj->membername,leader); + strcpy(gj->yourname, char_name); + strcpy(gj->membername, leader); QueuePacket(outapp3); safe_delete(outapp3); } @@ -895,8 +875,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) { uint32 char_acct_id = database.GetAccountIDByChar((char*)app->pBuffer); - if(char_acct_id == GetAccountID()) - { + if(char_acct_id == GetAccountID()) { clog(WORLD__CLIENT,"Delete character: %s",app->pBuffer); database.DeleteCharacter((char *)app->pBuffer); SendCharInfo(); @@ -1347,8 +1326,7 @@ void Client::SendApproveWorld() safe_delete(outapp); } -bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) -{ +bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) { PlayerProfile_Struct pp; ExtendedProfile_Struct ext; Inventory inv; @@ -1356,12 +1334,11 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) 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; + + 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", @@ -1374,38 +1351,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) 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 + /* Validate the char creation struct */ if(ClientVersionBit & BIT_SoFAndLater) { - if(!CheckCharCreateInfoSoF(cc)) - { + if(!CheckCharCreateInfoSoF(cc)) { clog(WORLD__CLIENT_ERR,"CheckCharCreateInfo did not validate the request (bad race/class/stats)"); return false; } } else { - if(!CheckCharCreateInfoTitanium(cc)) - { + if(!CheckCharCreateInfoTitanium(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 + /* Convert incoming cc_s to the new PlayerProfile_Struct */ memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile - InitExtendedProfile(&ext); - strn0cpy(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_; @@ -1432,44 +1394,39 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) 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.cur_hp = 1000; // 1k hp during dev only pp.hunger_level = 6000; pp.thirst_level = 6000; - - // FIXME: FV roleplay, database goodness... - - // Racial Languages - SetRacialLanguages( &pp ); // bUsh - SetRaceStartingSkills( &pp ); // bUsh - SetClassStartingSkills( &pp ); // bUsh + /* Racial Languages */ + SetRacialLanguages( &pp ); + SetRaceStartingSkills( &pp ); + SetClassStartingSkills( &pp ); pp.skills[SkillSenseHeading] = 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++) + for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++) pp.spell_book[i] = 0xFFFFFFFF; - for(i = 0; i < MAX_PP_MEMSPELL; i++) + for(i = 0; i < MAX_PP_REF_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 + */ - //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. + /* If server is PVP by default, make all character set to it. */ pp.pvp = database.GetServerType() == 1 ? 1 : 0; - //If it is an SoF Client and the SoF Start Zone rule is set, send new chars there + /* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */ if((ClientVersionBit & BIT_SoFAndLater) && (RuleI(World, SoFStartZoneID) > 0)) { clog(WORLD__CLIENT,"Found 'SoFStartZoneID' rule setting: %i", (RuleI(World, SoFStartZoneID))); pp.zone_id = (RuleI(World, SoFStartZoneID)); @@ -1478,11 +1435,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) else clog(WORLD__CLIENT_ERR,"Error getting zone id for Zone ID %i", (RuleI(World, SoFStartZoneID))); } - else - { - // if there's a startzone variable put them in there - if(database.GetVariable("startzone", startzone, 50)) - { + else { + /* 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) @@ -1490,8 +1445,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) else clog(WORLD__CLIENT_ERR,"Error getting zone id for '%s'", startzone); } - else // otherwise use normal starting zone logic - { + else{ /* otherwise use normal starting zone logic */ bool ValidStartZone = false; if(ClientVersionBit & BIT_TitaniumAndEarlier) @@ -1504,14 +1458,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) } } - if(!pp.zone_id) - { + if(!pp.zone_id) { pp.zone_id = 1; // qeynos pp.x = pp.y = pp.z = -1; } - if(!pp.binds[0].zoneId) - { + if(!pp.binds[0].zoneId) { pp.binds[0].zoneId = pp.zone_id; pp.binds[0].x = pp.x; pp.binds[0].y = pp.y; @@ -1519,7 +1471,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.binds[0].heading = pp.heading; } - // set starting city location to the initial bind point + /* Set Starting city */ pp.binds[4] = pp.binds[0]; @@ -1528,28 +1480,23 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) 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 + /* 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)) - { + if (!database.StoreCharacter(GetAccountID(), &pp, &inv)) { clog(WORLD__CLIENT_ERR,"Character creation failed: %s", pp.name); return false; } - else - { + else { clog(WORLD__CLIENT,"Character creation successful: %s", pp.name); return true; } } // returns true if the request is ok, false if there's an error -bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) -{ +bool CheckCharCreateInfoSoF(CharCreate_Struct *cc) { if(!cc) return false; _log(WORLD__CLIENT, "Validating char creation info..."); diff --git a/world/net.cpp b/world/net.cpp index 2d186c1af..3c4ab53c3 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -67,7 +67,6 @@ #endif -#include "../common/dbasync.h" #include "../common/emu_tcp_server.h" #include "../common/patches/patches.h" #include "zoneserver.h" @@ -98,7 +97,6 @@ UCSConnection UCSLink; QueryServConnection QSLink; LauncherList launcher_list; AdventureManager adventure_manager; -DBAsync *dbasync = nullptr; volatile bool RunLoops = true; uint32 numclients = 0; uint32 numzones = 0; @@ -175,7 +173,6 @@ int main(int argc, char** argv) { _log(WORLD__INIT_ERR, "Cannot continue without a database connection."); return 1; } - dbasync = new DBAsync(&database); guild_mgr.SetDatabase(&database); if (argc >= 2) { diff --git a/world/worlddb.cpp b/world/worlddb.cpp index deccc9207..fdbcc704d 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -21,7 +21,6 @@ #include "../common/string_util.h" #include "../common/eq_packet_structs.h" #include "../common/item.h" -#include "../common/dbasync.h" #include "../common/rulesys.h" #include #include @@ -390,12 +389,16 @@ bool WorldDatabase::GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Stru in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0; in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = 0; - if(!RunQuery(query, MakeAnyLenString(&query, "SELECT x,y,z,heading,bind_id FROM start_zones WHERE zone_id=%i AND player_class=%i " - "AND player_deity=%i AND player_race=%i", - in_cc->start_zone, - in_cc->class_, - in_cc->deity, - in_cc->race), errbuf, &result)) + if(!RunQuery(query, MakeAnyLenString(&query, "SELECT `x`, `y`, ``z, `heading`, `bind_id` " + " FROM `start_zones` " + " WHERE `zone_id` = %i " + " AND `player_class` = %i " + " AND player_deity=%i" + " AND player_race=%i", + in_cc->start_zone, + in_cc->class_, + in_cc->deity, + in_cc->race), errbuf, &result)) { LogFile->write(EQEMuLog::Status, "SoF Start zone query failed: %s : %s\n", query, errbuf); safe_delete_array(query); diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index af0752a95..6529a1f3d 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -652,17 +652,17 @@ bool ZoneServer::Process() { client->Clearance(wtz->response); } case ServerOP_ZoneToZoneRequest: { - // - // solar: ZoneChange is received by the zone the player is in, then the - // zone sends a ZTZ which ends up here. This code then find the target - // (ingress point) and boots it if needed, then sends the ZTZ to it. - // The ingress server will decide wether the player can enter, then will - // send back the ZTZ to here. This packet is passed back to the egress - // server, which will send a ZoneChange response back to the client - // which can be an error, or a success, in which case the client will - // disconnect, and their zone location will be saved when ~Client is - // called, so it will be available when they ask to zone. - // + // + // solar: ZoneChange is received by the zone the player is in, then the + // zone sends a ZTZ which ends up here. This code then find the target + // (ingress point) and boots it if needed, then sends the ZTZ to it. + // The ingress server will decide wether the player can enter, then will + // send back the ZTZ to here. This packet is passed back to the egress + // server, which will send a ZoneChange response back to the client + // which can be an error, or a success, in which case the client will + // disconnect, and their zone location will be saved when ~Client is + // called, so it will be available when they ask to zone. + // if(pack->size != sizeof(ZoneToZone_Struct)) @@ -675,43 +675,31 @@ bool ZoneServer::Process() { zlog(WORLD__ZONE,"ZoneToZone request for %s current zone %d req zone %d\n", ztz->name, ztz->current_zone_id, ztz->requested_zone_id); - printf("\n\n ZoneToZone request for %s current zone %d req zone %d\n\n", - ztz->name, ztz->current_zone_id, ztz->requested_zone_id); - - if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) // this is a request from the egress zone - { + /* This is a request from the egress zone */ + if(GetZoneID() == ztz->current_zone_id && GetInstanceID() == ztz->current_instance_id) { zlog(WORLD__ZONE,"Processing ZTZ for egress from zone for client %s\n", ztz->name); - if - ( - ztz->admin < 80 && - ztz->ignorerestrictions < 2 && - zoneserver_list.IsZoneLocked(ztz->requested_zone_id) - ) - { + if (ztz->admin < 80 && ztz->ignorerestrictions < 2 && zoneserver_list.IsZoneLocked(ztz->requested_zone_id)) { ztz->response = 0; SendPacket(pack); break; } ZoneServer *ingress_server = nullptr; - if(ztz->requested_instance_id > 0) - { + if(ztz->requested_instance_id > 0) { ingress_server = zoneserver_list.FindByInstanceID(ztz->requested_instance_id); } - else - { - ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id); - + else { + ingress_server = zoneserver_list.FindByZoneID(ztz->requested_zone_id); } - if(ingress_server) // found a zone already running - { + /* Zone was already running*/ + if(ingress_server) { _log(WORLD__ZONE,"Found a zone already booted for %s\n", ztz->name); ztz->response = 1; } - else // need to boot one - { + /* Boot the Zone*/ + else { int server_id; if ((server_id = zoneserver_list.TriggerBootup(ztz->requested_zone_id, ztz->requested_instance_id))){ _log(WORLD__ZONE,"Successfully booted a zone for %s\n", ztz->name); @@ -719,8 +707,7 @@ bool ZoneServer::Process() { ztz->response = 1; ingress_server = zoneserver_list.FindByID(server_id); } - else - { + else { _log(WORLD__ZONE_ERR,"FAILED to boot a zone for %s\n", ztz->name); // bootup failed, send back error code 0 ztz->response = 0; @@ -728,27 +715,24 @@ bool ZoneServer::Process() { } if(ztz->response!=0 && client) client->LSZoneChange(ztz); - SendPacket(pack); // send back to egress server - if(ingress_server) // if we couldn't boot one, this is 0 - { - ingress_server->SendPacket(pack); // inform target server - } + SendPacket(pack); // send back to egress server + if(ingress_server) { + ingress_server->SendPacket(pack); // inform target server + } } - else // this is response from the ingress server, route it back to the egress server - { + /* Response from Ingress server, route back to egress */ + else{ + zlog(WORLD__ZONE,"Processing ZTZ for ingress to zone for client %s\n", ztz->name); ZoneServer *egress_server = nullptr; - if(ztz->current_instance_id > 0) - { + if(ztz->current_instance_id > 0) { egress_server = zoneserver_list.FindByInstanceID(ztz->current_instance_id); } - else - { + else { egress_server = zoneserver_list.FindByZoneID(ztz->current_zone_id); } - if(egress_server) - { + if(egress_server) { egress_server->SendPacket(pack); } } @@ -786,21 +770,18 @@ bool ZoneServer::Process() { delete whom; break; } - case ServerOP_RequestOnlineGuildMembers: - { + case ServerOP_RequestOnlineGuildMembers: { ServerRequestOnlineGuildMembers_Struct *srogms = (ServerRequestOnlineGuildMembers_Struct*) pack->pBuffer; zlog(GUILDS__IN_PACKETS, "ServerOP_RequestOnlineGuildMembers Recieved. FromID=%i GuildID=%i", srogms->FromID, srogms->GuildID); client_list.SendOnlineGuildMembers(srogms->FromID, srogms->GuildID); break; } - case ServerOP_ClientVersionSummary: - { + case ServerOP_ClientVersionSummary: { ServerRequestClientVersionSummary_Struct *srcvss = (ServerRequestClientVersionSummary_Struct*) pack->pBuffer; client_list.SendClientVersionSummary(srcvss->Name); break; } - case ServerOP_ReloadRules: - { + case ServerOP_ReloadRules: { zoneserver_list.SendPacket(pack); RuleManager::Instance()->LoadRules(&database, "default"); break; @@ -1275,30 +1256,10 @@ bool ZoneServer::Process() { case ServerOP_QueryServGeneric: case ServerOP_Speech: case ServerOP_QSPlayerLogTrades: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogHandins: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogNPCKills: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogDeletes: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogMoves: - { - QSLink.SendPacket(pack); - break; - } case ServerOP_QSPlayerLogMerchantTransactions: { QSLink.SendPacket(pack); diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 0b6ebc10a..8cd086405 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -119,7 +119,6 @@ SET(zone_sources zone_logsys.cpp zone_config.cpp zonedb.cpp - zonedbasync.cpp zoning.cpp ) @@ -207,7 +206,6 @@ SET(zone_headers zone.h zone_config.h zonedb.h - zonedbasync.h zonedump.h ) diff --git a/zone/client.cpp b/zone/client.cpp index c56d47b4d..962715b86 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -73,8 +73,6 @@ extern uint32 numclients; extern PetitionList petition_list; bool commandlogged; char entirecommand[255]; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; Client::Client(EQStreamInterface* ieqs) : Mob("No name", // name @@ -544,8 +542,9 @@ bool Client::Save(uint8 iCommitNow) { /* Save Character Currency */ database.SaveCharacterCurrency(this->CharacterID(), &m_pp); - /* Save Character AA */ - // SaveAA(); + /* Save Current Bind Points : Sets Instance to 0 because it is currently not implemented */ + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0); /* Regular bind */ + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[4].zoneId, 0, m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0, 1); /* Home Bind */ /* Save Character Buffs */ database.SaveBuffs(this); @@ -557,15 +556,11 @@ bool Client::Save(uint8 iCommitNow) { /* Save Mercs */ if (GetMercInfo().MercTimerRemaining > RuleI(Mercs, UpkeepIntervalMS)){ GetMercInfo().MercTimerRemaining = RuleI(Mercs, UpkeepIntervalMS); } - if(GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); } + if (GetMercTimer()->Enabled()) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); } if (GetMerc() && !dead) { } else { memset(&m_mercinfo, 0, sizeof(struct MercInfo)); } m_pp.lastlogin = time(nullptr); - if (pQueuedSaveWorkID) { - dbasync->CancelWork(pQueuedSaveWorkID); - pQueuedSaveWorkID = 0; - } if (GetPet() && !GetPet()->IsFamiliar() && GetPet()->CastToNPC()->GetPetSpellID() && !dead) { NPC *pet = GetPet()->CastToNPC(); @@ -585,34 +580,10 @@ bool Client::Save(uint8 iCommitNow) { p_timers.Store(&database); - /* Save Character Task */ - SaveTaskState(); + database.SaveCharacterTribute(this->CharacterID(), &m_pp); - // if (iCommitNow <= 1) { - // // char* query = 0; - // // uint32_breakdown workpt; - // // workpt.b4() = DBA_b4_Entity; - // // workpt.w2_3() = GetID(); - // // workpt.b1() = DBA_b1_Entity_Client_Save; - // // DBAsyncWork* dbaw = new DBAsyncWork(&database, &MTdbafq, workpt, DBAsync::Write, 0xFFFFFFFF); - // // dbaw->AddQuery(iCommitNow == 0 ? true : false, &query, database.SetPlayerProfile_MQ(&query, account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets), false); - // // if (iCommitNow == 0){ - // // pQueuedSaveWorkID = dbasync->AddWork(&dbaw, 2500); - // // } - // // else { - // // dbasync->AddWork(&dbaw, 0); - // // SaveBackup(); - // // } - // // safe_delete_array(query); - // // return true; - // } - // else if (database.SetPlayerProfile(account_id, character_id, &m_pp, &m_inv, &m_epp, 0, 0, MaxXTargets)) { - // SaveBackup(); - // } - // else { - // std::cerr << "Failed to update player profile" << std::endl; - // return false; - // } + /* Save Character Task */ + SaveTaskState(); /* Save Character Data */ database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); @@ -624,12 +595,6 @@ bool Client::Save(uint8 iCommitNow) { } void Client::SaveBackup() { - if (!RunLoops) - return; - char* query = 0; - DBAsyncWork* dbaw = new DBAsyncWork(&database, &DBAsyncCB_CharacterBackup, this->CharacterID(), DBAsync::Read); - dbaw->AddQuery(0, &query, MakeAnyLenString(&query, "Select id, UNIX_TIMESTAMP()-UNIX_TIMESTAMP(ts) as age from character_backup where charid=%u and backupreason=0 order by ts asc", this->CharacterID()), true); - dbasync->AddWork(&dbaw, 0); } CLIENTPACKET::CLIENTPACKET() @@ -1393,12 +1358,14 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme) void Client::SetSkill(SkillUseTypes skillid, uint16 value) { if (skillid > HIGHEST_SKILL) - return; - m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills + return; + m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills + + database.SaveCharacterSkill(this->CharacterID(), skillid, value); EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; - skill->skillId=skillid; + skill->skillId=skillid; skill->value=value; QueuePacket(outapp); safe_delete(outapp); @@ -1414,10 +1381,12 @@ void Client::IncreaseLanguageSkill(int skill_id, int value) { if (m_pp.languages[skill_id] > 100) //Lang skill above max m_pp.languages[skill_id] = 100; + database.SaveCharacterLanguage(this->CharacterID(), skill_id, m_pp.languages[skill_id]); + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; skill->skillId = 100 + skill_id; - skill->value = m_pp.languages[skill_id]; + skill->value = m_pp.languages[skill_id]; QueuePacket(outapp); safe_delete(outapp); @@ -2165,32 +2134,27 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){ uint64 tmp2; tmp = copper; - // Add Amount of Platinum + /* Add Amount of Platinum */ tmp2 = tmp/1000; int32 new_val = m_pp.platinum + tmp2; - if(new_val < 0) { - m_pp.platinum = 0; - } else { - m_pp.platinum = m_pp.platinum + tmp2; - } + if(new_val < 0) { m_pp.platinum = 0; } + else { m_pp.platinum = m_pp.platinum + tmp2; } tmp-=tmp2*1000; //if (updateclient) // SendClientMoneyUpdate(3,tmp2); - // Add Amount of Gold + /* Add Amount of Gold */ tmp2 = tmp/100; new_val = m_pp.gold + tmp2; - if(new_val < 0) { - m_pp.gold = 0; - } else { - m_pp.gold = m_pp.gold + tmp2; - } + if(new_val < 0) { m_pp.gold = 0; } + else { m_pp.gold = m_pp.gold + tmp2; } + tmp-=tmp2*100; //if (updateclient) // SendClientMoneyUpdate(2,tmp2); - // Add Amount of Silver + /* Add Amount of Silver */ tmp2 = tmp/10; new_val = m_pp.silver + tmp2; if(new_val < 0) { @@ -2226,8 +2190,7 @@ void Client::AddMoneyToPP(uint64 copper, bool updateclient){ LogFile->write(EQEMuLog::Debug, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); } -void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){ - +void Client::EVENT_ITEM_ScriptStopReturn(){ /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items This will stopgap players from items being returned if global_npc.pl has a catch all return_items */ @@ -2236,6 +2199,10 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat gettimeofday(&read_time, 0); sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); this->SetEntityVariable("Stop_Return", buffer); +} + +void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){ + this->EVENT_ITEM_ScriptStopReturn(); int32 new_value = m_pp.platinum + platinum; if(new_value >= 0 && new_value > m_pp.platinum) @@ -3184,6 +3151,7 @@ void Client::SetLanguageSkill(int langid, int value) value = 100; //Max lang value m_pp.languages[langid] = value; + database.SaveCharacterLanguage(this->CharacterID(), langid, value); EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; diff --git a/zone/client.h b/zone/client.h index bab48e8ea..e33dcd755 100644 --- a/zone/client.h +++ b/zone/client.h @@ -234,7 +234,6 @@ public: bool KeyRingCheck(uint32 item_id); void KeyRingList(); virtual bool IsClient() const { return true; } - virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw); void CompleteConnect(); bool TryStacking(ItemInst* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); @@ -654,14 +653,14 @@ public: void OnDisconnect(bool hard_disconnect); - uint16 GetSkillPoints() {return m_pp.points;} - void SetSkillPoints(int inp) {m_pp.points = inp;} + uint16 GetSkillPoints() { return m_pp.points;} + void SetSkillPoints(int inp) { m_pp.points = inp;} void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } } void IncreaseLanguageSkill(int skill_id, int value = 1); - virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0)? m_pp.skills[skill_id]*(100 + itembonuses.skillmod[skill_id])/100 : m_pp.skills[skill_id]); } return 0; } + virtual uint16 GetSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return((itembonuses.skillmod[skill_id] > 0) ? m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100 : m_pp.skills[skill_id]); } return 0; } uint32 GetRawSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; } - bool HasSkill(SkillUseTypes skill_id) const; + bool HasSkill(SkillUseTypes skill_id) const; bool CanHaveSkill(SkillUseTypes skill_id) const; void SetSkill(SkillUseTypes skill_num, uint16 value); void AddSkill(SkillUseTypes skillid, uint16 value); @@ -782,6 +781,7 @@ public: int16 acmod(); // Item methods + void EVENT_ITEM_ScriptStopReturn(); uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); void SetTint(int16 slot_id, uint32 color); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 87d884eb7..3b34878d5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -77,9 +77,6 @@ extern volatile bool ZoneLoaded; extern WorldServer worldserver; extern PetitionList petition_list; extern EntityList entity_list; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; - typedef void (Client::*ClientPacketProc)(const EQApplicationPacket *app); //Use a map for connecting opcodes since it dosent get used a lot and is sparse @@ -525,7 +522,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) client_state = CLIENT_KICKED; return; } - strcpy(name, cze->char_name); /* Check for Client Spoofing */ @@ -592,19 +588,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (LFG){ LFG = atoi(row[12]); } if (firstlogon){ firstlogon = atoi(row[15]); } } - + loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ + database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */ database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */ + database.LoadCharacterPotions(cid, &m_pp); /* Load Character Potion Belt */ 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... */ - database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency */ database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */ - database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ + database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */ database.LoadCharacterSpellBook(cid, &m_pp); /* Load Character Spell Book */ database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */ database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */ + database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ if (level){ level = m_pp.level; } @@ -612,9 +609,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (gmhideme) { trackable = false; } /* Set Con State for Reporting */ conn_state = PlayerProfileLoaded; - - // m_pp.zone_id = zone->GetZoneID(); - // m_pp.zoneInstance = zone->GetInstanceID(); /* Set Total Seconds Played */ TotalSecondsPlayed = m_pp.timePlayedMin * 60; @@ -9168,38 +9162,6 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) return; } -void Client::DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { - Entity::DBAWComplete(workpt_b1, dbaw); - switch (workpt_b1) { - case DBA_b1_Entity_Client_Save: { - clock_t t = std::clock(); /* Function timer start */ - - char errbuf[MYSQL_ERRMSG_SIZE]; - uint32 affected_rows = 0; - DBAsyncQuery* dbaq = dbaw->PopAnswer(); - if (dbaq->GetAnswer(errbuf, 0, &affected_rows) && affected_rows == 1) { - if (dbaq->QPT()) { - SaveBackup(); - } - } - else { - std::cout << "Async client save failed. '" << errbuf << "'" << std::endl; - Message(13, "Error: Asyncronous save of your character failed."); - if (Admin() >= 200) - Message(13, "errbuf: %s", errbuf); - } - pQueuedSaveWorkID = 0; - - LogFile->write(EQEMuLog::Status, "Client::DBAWComplete Save Character Async done... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC); - break; - } - default: { - std::cout << "Error: Client::DBAWComplete(): Unknown workpt_b1" << std::endl; - break; - } - } -} - /* Finish client connecting state */ void Client::CompleteConnect() { UpdateWho(); @@ -9221,7 +9183,7 @@ void Client::CompleteConnect() { SendAppearancePacket(AT_GuildID, GuildID(), false); SendAppearancePacket(AT_GuildRank, GuildRank(), false); } - for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++) { + for (uint32 spellInt = 0; spellInt < MAX_PP_REF_SPELLBOOK; spellInt++) { if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000) m_pp.spell_book[spellInt] = 0xFFFFFFFF; } @@ -9417,7 +9379,7 @@ void Client::CompleteConnect() { SendWearChange(x); Mob *pet = GetPet(); if (pet != nullptr) { - for (x = 0; x < 8; x++) + for (x = 0; x < 8; x++) pet->SendWearChange(x); } @@ -9497,6 +9459,8 @@ void Client::CompleteConnect() { alternate_currency_loaded = true; ProcessAlternateCurrencyQueue(); + + CalcItemScale(); DoItemEnterZone(); @@ -10504,8 +10468,7 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app) { } } -void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { - +void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { if(app->size != sizeof(MovePotionToBelt_Struct)) { LogFile->write(EQEMuLog::Debug, "Size mismatch in OP_PotionBelt expected %i got %i", sizeof(MovePotionToBelt_Struct), app->size); @@ -10519,6 +10482,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { m_pp.potionbelt.items[mptbs->SlotNumber].item_id = BaseItem->ID; m_pp.potionbelt.items[mptbs->SlotNumber].icon = BaseItem->Icon; strn0cpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, BaseItem->Name, sizeof(BaseItem->Name)); + database.SaveCharacterPotionBelt(this->CharacterID(), mptbs->SlotNumber, m_pp.potionbelt.items[mptbs->SlotNumber].item_id, m_pp.potionbelt.items[mptbs->SlotNumber].icon); } } else { @@ -10526,9 +10490,6 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) { m_pp.potionbelt.items[mptbs->SlotNumber].icon = 0; strncpy(m_pp.potionbelt.items[mptbs->SlotNumber].item_name, "\0", 1); } - - Save(); - } void Client::Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app) { diff --git a/zone/client_process.cpp b/zone/client_process.cpp index fd8cb3740..4c9c8ca2d 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1717,6 +1717,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) } uint16 skilllevel = GetRawSkill(skill); + if(skilllevel == 0) { //this is a new skill.. uint16 t_level = SkillTrainLevel(skill, GetClass()); @@ -1726,7 +1727,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) } SetSkill(skill, t_level); - } else { + } else { switch(skill) { case SkillBrewing: case SkillMakePoison: diff --git a/zone/command.cpp b/zone/command.cpp index b1d195bf4..ea85fb9af 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -225,7 +225,6 @@ int command_init(void) { command_add("worldshutdown","- Shut down world and all zones",200,command_worldshutdown) || command_add("sendzonespawns","- Refresh spawn list for all clients in zone",150,command_sendzonespawns) || command_add("dbspawn2","[spawngroup] [respawn] [variance] - Spawn an NPC from a predefined row in the spawn2 table",100,command_dbspawn2) || - command_add("copychar","[character name] [new character] [new account id] - Create a copy of a character",100,command_copychar) || command_add("shutdown","- Shut this zone process down",150,command_shutdown) || command_add("delacct","[accountname] - Delete an account",150,command_delacct) || command_add("setpass","[accountname] [password] - Set local password for accountname",150,command_setpass) || @@ -2227,28 +2226,6 @@ void command_dbspawn2(Client *c, const Seperator *sep) } } -void command_copychar(Client *c, const Seperator *sep) -{ - if(sep->arg[1][0]==0 || sep->arg[2][0] == 0 || sep->arg[3][0] == 0) - c->Message(0, "Usage: #copychar [character name] [new character] [new account id]"); - //CheckUsedName.... TRUE=No Char, FALSE=Char/Error - //If there is no source... - else if (database.CheckUsedName((char*)sep->arg[1])) { - c->Message(0, "Source character not found!"); - } - else { - //If there is a name is not used.... - if (database.CheckUsedName((char*) sep->arg[2])) { - if (!database.CopyCharacter((char*) sep->arg[1], (char*) sep->arg[2], atoi(sep->arg[3]))) - c->Message(0, "Character copy operation failed!"); - else - c->Message(0, "Character copy complete."); - } - else - c->Message(0, "Target character already exists!"); - } -} - void command_shutdown(Client *c, const Seperator *sep) { CatchSignal(2); @@ -2423,8 +2400,8 @@ void command_showskills(Client *c, const Seperator *sep) c->Message(0, "Skills for %s", t->GetName()); for (SkillUseTypes i=Skill1HBlunt; i <= HIGHEST_SKILL; i=(SkillUseTypes)(i+1)) - c->Message(0, "Skill [%d] is at [%d]", i, t->GetSkill(i)); -} + c->Message(0, "Skill [%d] is at [%d] - %u", i, t->GetSkill(i), t->GetRawSkill(i)); +} void command_findspell(Client *c, const Seperator *sep) { @@ -2801,7 +2778,7 @@ void command_charbackup(Client *c, const Seperator *sep) if (sep->IsNumber(2)) charid = atoi(sep->arg[2]); else - database.GetAccountIDByChar(sep->arg[2], &charid); + database.GetAccountIDByChar(sep->arg[2]); if (charid) { if (database.RunQuery(query, MakeAnyLenString(&query, "Select id, backupreason, charid, account_id, zoneid, DATE_FORMAT(ts, '%%m/%%d/%%Y %%H:%%i:%%s') " @@ -2828,7 +2805,7 @@ void command_charbackup(Client *c, const Seperator *sep) if (sep->IsNumber(2)) charid = atoi(sep->arg[2]); else - database.GetAccountIDByChar(sep->arg[2], &charid); + database.GetAccountIDByChar(sep->arg[2]); if (charid && sep->IsNumber(3)) { uint32 cbid = atoi(sep->arg[3]); @@ -8725,6 +8702,7 @@ void command_traindisc(Client *c, const Seperator *sep) break; //continue the 1st loop } else if(t->GetPP().disciplines.values[r] == 0) { t->GetPP().disciplines.values[r] = curspell; + database.SaveCharacterDisc(c->CharacterID(), r, curspell); t->SendDisciplineUpdate(); t->Message(0, "You have learned a new discipline!"); count++; //success counter diff --git a/zone/command.h b/zone/command.h index 6a880625e..ef7302c51 100644 --- a/zone/command.h +++ b/zone/command.h @@ -125,7 +125,6 @@ void command_worldshutdown(Client *c, const Seperator *sep); void command_sendzonespawns(Client *c, const Seperator *sep); void command_zsave(Client *c, const Seperator *sep); void command_dbspawn2(Client *c, const Seperator *sep); -void command_copychar(Client *c, const Seperator *sep); void command_shutdown(Client *c, const Seperator *sep); void command_delacct(Client *c, const Seperator *sep); void command_setpass(Client *c, const Seperator *sep); diff --git a/zone/effects.cpp b/zone/effects.cpp index 5e07d5f9a..10748c0e1 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -606,6 +606,7 @@ bool Client::TrainDiscipline(uint32 itemid) { return(false); } else if(m_pp.disciplines.values[r] == 0) { m_pp.disciplines.values[r] = spell_id; + database.SaveCharacterDisc(this->CharacterID(), r, spell_id); SendDisciplineUpdate(); Message(0, "You have learned a new discipline!"); return(true); diff --git a/zone/entity.cpp b/zone/entity.cpp index 2ca3f640d..b59822d73 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -40,7 +40,6 @@ #include "../common/spdat.h" #include "../common/features.h" #include "string_ids.h" -#include "../common/dbasync.h" #include "guild_mgr.h" #include "raids.h" #include "quest_parser_collection.h" @@ -57,7 +56,6 @@ extern WorldServer worldserver; extern NetConnection net; extern uint32 numclients; extern PetitionList petition_list; -extern DBAsync *dbasync; extern char errorname[32]; extern uint16 adverrornum; @@ -65,12 +63,11 @@ extern uint16 adverrornum; Entity::Entity() { id = 0; - pDBAsyncWorkID = 0; } Entity::~Entity() { - dbasync->CancelWork(pDBAsyncWorkID); + } Client *Entity::CastToClient() diff --git a/zone/entity.h b/zone/entity.h index cc302fe75..9599aa7fc 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -28,7 +28,6 @@ #include "zonedb.h" #include "zonedump.h" -#include "zonedbasync.h" #include "qglobals.h" class EQApplicationPacket; @@ -53,7 +52,7 @@ class Bot; class BotRaids; #endif -extern EntityList entity_list; +extern EntityList entity_list; class Entity { @@ -100,7 +99,6 @@ public: inline const uint16& GetID() const { return id; } virtual const char* GetName() { return ""; } - virtual void DBAWComplete(uint8 workpt_b1, DBAsyncWork* dbaw) { pDBAsyncWorkID = 0; } bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1); #ifdef BOTS diff --git a/zone/exp.cpp b/zone/exp.cpp index 9415022ca..a82aa25d9 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -51,14 +51,7 @@ static uint32 MaxBankedRaidLeadershipPoints(int Level) void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Stop_Return", buffer); + this->EVENT_ITEM_ScriptStopReturn(); uint32 add_exp = in_add_exp; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 02cf6e568..69570faf2 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -200,14 +200,7 @@ bool Client::CheckLoreConflict(const Item_Struct* item) { } bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, bool attuned, uint16 to_slot) { - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Recieved_Item", buffer); + this->EVENT_ITEM_ScriptStopReturn(); // TODO: update calling methods and script apis to handle a failure return @@ -2320,10 +2313,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { _log(INVENTORY__BANDOLIER, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->number, bs->name); strcpy(m_pp.bandoliers[bs->number].name, bs->name); - const ItemInst* InvItem; - - const Item_Struct *BaseItem; - + const ItemInst* InvItem; + const Item_Struct *BaseItem; int16 WeaponSlot; for(int BandolierSlot = bandolierMainHand; BandolierSlot <= bandolierAmmo; BandolierSlot++) { @@ -2334,6 +2325,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { _log(INVENTORY__BANDOLIER, "Char: %s adding item %s to slot %i", GetName(),BaseItem->Name, WeaponSlot); m_pp.bandoliers[bs->number].items[BandolierSlot].item_id = BaseItem->ID; m_pp.bandoliers[bs->number].items[BandolierSlot].icon = BaseItem->Icon; + database.SaveCharacterBandolier(this->CharacterID(), bs->number, BandolierSlot, m_pp.bandoliers[bs->number].items[BandolierSlot].item_id, m_pp.bandoliers[bs->number].items[BandolierSlot].icon, bs->name); } else { _log(INVENTORY__BANDOLIER, "Char: %s no item in slot %i", GetName(), WeaponSlot); @@ -2341,21 +2333,17 @@ void Client::CreateBandolier(const EQApplicationPacket *app) { m_pp.bandoliers[bs->number].items[BandolierSlot].icon = 0; } } - Save(); } void Client::RemoveBandolier(const EQApplicationPacket *app) { - - // Delete bandolier with the specified number - BandolierDelete_Struct *bds = (BandolierDelete_Struct*)app->pBuffer; _log(INVENTORY__BANDOLIER, "Char: %s removing set", GetName(), bds->number); memset(m_pp.bandoliers[bds->number].name, 0, 32); for(int i = bandolierMainHand; i <= bandolierAmmo; i++) { m_pp.bandoliers[bds->number].items[i].item_id = 0; - m_pp.bandoliers[bds->number].items[i].icon = 0; + m_pp.bandoliers[bds->number].items[i].icon = 0; } - Save(); + database.DeleteCharacterBandolier(this->CharacterID(), bds->number); } void Client::SetBandolier(const EQApplicationPacket *app) { diff --git a/zone/net.cpp b/zone/net.cpp index 8a8421786..498ed5102 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -97,8 +97,6 @@ extern Zone* zone; EQStreamFactory eqsf(ZoneStream); npcDecayTimes_Struct npcCorpseDecayTimes[100]; TitleManager title_manager; -DBAsyncFinishedQueue MTdbafq; -DBAsync *dbasync = nullptr; QueryServ *QServ = 0; TaskManager *taskmanager = 0; QuestParserCollection *parse = 0; @@ -168,8 +166,6 @@ int main(int argc, char** argv) { _log(ZONE__INIT_ERR, "Cannot continue without a database connection."); return 1; } - dbasync = new DBAsync(&database); - dbasync->AddFQ(&MTdbafq); guild_mgr.SetDatabase(&database); GuildBanks = nullptr; @@ -444,10 +440,6 @@ int main(int argc, char** argv) { } } - DBAsyncWork* dbaw = 0; - while ((dbaw = MTdbafq.Pop())) { - DispatchFinishedDBAsync(dbaw); - } if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); @@ -507,8 +499,6 @@ int main(int argc, char** argv) { //Fix for Linux world server problem. eqsf.Close(); worldserver.Disconnect(); - dbasync->CommitWrites(); - dbasync->StopThread(); safe_delete(taskmanager); command_deinit(); safe_delete(parse); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fc31178ae..776376bdf 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -974,6 +974,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID); if (SpellGlobalCheckResult) { initiator->GetPP().disciplines.values[r] = curspell; + database.SaveCharacterDisc(Char_ID, r, curspell); initiator->SendDisciplineUpdate(); initiator->Message(0, "You have learned a new discipline!"); count++; //success counter @@ -981,11 +982,12 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { break; //continue the 1st loop } else { - initiator->GetPP().disciplines.values[r] = curspell; - initiator->SendDisciplineUpdate(); - initiator->Message(0, "You have learned a new discipline!"); - count++; //success counter - break; //continue the 1st loop + initiator->GetPP().disciplines.values[r] = curspell; + database.SaveCharacterDisc(Char_ID, r, curspell); + initiator->SendDisciplineUpdate(); + initiator->Message(0, "You have learned a new discipline!"); + count++; //success counter + break; //continue the 1st loop } } //if we get to this point, there's already a discipline in this slot, so we skip it } diff --git a/zone/spells.cpp b/zone/spells.cpp index 94921c685..1f37a21e4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4933,8 +4933,9 @@ void Client::UntrainDisc(int slot, bool update_client) if(slot >= MAX_PP_DISCIPLINES || slot < 0) return; - mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot); + mlog(CLIENT__SPELLS, "Discipline %d untrained from slot %d", m_pp.disciplines.values[slot], slot); m_pp.disciplines.values[slot] = 0; + database.DeleteCharacterDisc(this->CharacterID(), slot); if(update_client) { diff --git a/zone/trading.cpp b/zone/trading.cpp index 23d8d77af..414b397fc 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -913,14 +913,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(!tradingWith->IsMoving()) tradingWith->FaceTarget(this); - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Stop_Return", buffer); + this->EVENT_ITEM_ScriptStopReturn(); } } @@ -938,7 +931,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st parse->AddVar(temp1, temp2); snprintf(temp1, 100, "platinum.%d", tradingWith->GetNPCTypeID()); snprintf(temp2, 100, "%u", trade->pp); - parse->AddVar(temp1, temp2); + parse->AddVar(temp1, temp2); if(tradingWith->GetAppearance() != eaDead) { tradingWith->FaceTarget(this); diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 95da9b5a3..08bbf4662 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -254,8 +254,10 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { return(0); } - //make sure they have enough of them - //and remove it from inventory + /* + Make sure they have enough of them + and remove it from inventory + */ if(inst->IsStackable()) { if(inst->GetCharges() < (int32)quantity) //dont have enough.... return(0); @@ -267,7 +269,7 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { pts *= quantity; - //add the tribute value in points + /* Add the tribute value in points */ AddTributePoints(pts); return(pts); } @@ -279,7 +281,7 @@ int32 Client::TributeMoney(uint32 platinum) { return(0); } - //add the tribute value in points + /* Add the tribute value in points */ AddTributePoints(platinum); return(platinum); } diff --git a/zone/zone.cpp b/zone/zone.cpp index a9c63b22f..9ae17381d 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -77,8 +77,6 @@ extern bool staticzone; Zone* zone = 0; volatile bool ZoneLoaded = false; extern QuestParserCollection* parse; -extern DBAsyncFinishedQueue MTdbafq; -extern DBAsync *dbasync; bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { const char* zonename = database.GetZoneName(iZoneID); @@ -705,7 +703,6 @@ void Zone::Shutdown(bool quite) zone->ResetAuth(); safe_delete(zone); - dbasync->CommitWrites(); entity_list.ClearAreas(); parse->ReloadQuests(true); UpdateWindowTitle(); @@ -844,8 +841,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) } Zone::~Zone() { - if(pQueuedMerchantsWorkID != 0) - dbasync->CancelWork(pQueuedMerchantsWorkID); spawn2_list.Clear(); safe_delete(zonemap); safe_delete(watermap); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 794b1240f..77e5739ee 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -626,8 +626,7 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id){ return loadti; } -ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { - +ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; MYSQL_RES *result; @@ -687,8 +686,7 @@ void ZoneDatabase::SaveTraderItem(uint32 CharID, uint32 ItemID, uint32 SerialNum safe_delete_array(query); } -void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) { - +void ZoneDatabase::UpdateTraderItemCharges(int CharID, uint32 SerialNumber, int32 Charges) { _log(TRADING__CLIENT, "ZoneDatabase::UpdateTraderItemCharges(%i, %i, %i)", CharID, SerialNumber, Charges); char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; @@ -784,8 +782,7 @@ void ZoneDatabase::DeleteBuyLines(uint32 CharID){ safe_delete_array(query); } -void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) { - +void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char* ItemName, uint32 Quantity, uint32 Price) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; if (!(RunQuery(query,MakeAnyLenString(&query, "replace INTO buyer VALUES(%i,%i, %i,\"%s\",%i,%i)", @@ -795,8 +792,7 @@ void ZoneDatabase::AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, cons safe_delete_array(query); } -void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { - +void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { char errbuf[MYSQL_ERRMSG_SIZE]; char* query = 0; @@ -806,8 +802,7 @@ void ZoneDatabase::RemoveBuyLine(uint32 CharID, uint32 BuySlot) { safe_delete_array(query); } -void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) { - +void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) { if(Quantity <= 0) { RemoveBuyLine(CharID, BuySlot); return; @@ -1016,7 +1011,7 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* } bool ZoneDatabase::LoadCharacterFactionValues(uint32 character_id, faction_map & val_list) { - std::string query = StringFormat("SELECT faction_id,current_value FROM faction_values WHERE char_id = %i", character_id); + std::string query = StringFormat("SELECT `faction_id`, `current_value` FROM `faction_values` WHERE `char_id` = %i", character_id); auto results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { val_list[atoi(row[0])] = atoi(row[1]); } return true; @@ -1055,8 +1050,12 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str "`value` " "FROM " "`character_languages` " - "WHERE `id` = %u ORDER BY `language_id`", character_id); + "WHERE `id` = %u ORDER BY `lang_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; + /* Initialize Languages */ + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + pp->languages[i] = 0; + } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->languages[i] = atoi(row[1]); } return true; } @@ -1069,8 +1068,8 @@ bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_S "`character_disciplines`" "WHERE `id` = %u ORDER BY `disc_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; } - return true; + for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; } + return true; } bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp){ @@ -1081,7 +1080,11 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct "FROM " "`character_skills` " "WHERE `id` = %u ORDER BY `skill_id`", character_id); - auto results = database.QueryDatabase(query); int i = 0; + auto results = database.QueryDatabase(query); int i = 0; + /* Initialize Skill */ + for (i = 0; i < MAX_PP_SKILL; i++){ + pp->skills[i] = 0; + } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->skills[i] = atoi(row[1]); } return true; } @@ -1131,44 +1134,162 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru return true; } +bool ZoneDatabase::LoadCharacterMaterialColor(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++; + pp->item_tint[i].rgb.use_tint = atoi(row[r]); + } + return true; +} + +bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT 16", character_id); + auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0; + for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + pp->bandoliers[i].items[si].icon = 0; + } + } + + for (auto row = results.begin(); row != results.end(); ++row) { + r = 0; + i = atoi(row[r]); /* Bandolier ID */ r++; + si = atoi(row[r]); /* Bandolier Slot */ r++; + pp->bandoliers[i].items[si].item_id = atoi(row[r]); r++; + pp->bandoliers[i].items[si].icon = atoi(row[r]); r++; + strcpy(pp->bandoliers[i].name, row[r]); r++; + si++; + } + return true; +} + +bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT `tier`, `tribute` FROM `character_tribute` WHERE `id` = %u", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + pp->tributes[i].tribute = 0; + pp->tributes[i].tier = 0; + } + for (auto row = results.begin(); row != results.end(); ++row) { + pp->tributes[i].tier = atoi(row[0]); + pp->tributes[i].tribute = atoi(row[1]); + } + return true; +} + +bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT `potion_id`, `item_id`, `icon` FROM `character_potionbelt` WHERE `id` = %u LIMIT 4", character_id); + auto results = database.QueryDatabase(query); int i = 0; + for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ + pp->potionbelt.items[i].icon = 0; + pp->potionbelt.items[i].item_id = 0; + strncpy(pp->potionbelt.items[i].item_name, "\0", 1); + } + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); /* Potion belt slot number */ + pp->potionbelt.items[i].item_id = atoi(row[1]); + pp->potionbelt.items[i].icon = atoi(row[2]); + } + return true; +} + bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ - std::string query = StringFormat("SELECT id, zone_id, instance_id, x, y, z, heading FROM character_bind_home WHERE `id` = %u", character_id); + std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z, heading, is_home FROM character_bind WHERE `id` = %u LIMIT 2", character_id); auto results = database.QueryDatabase(query); int i = 0; for (auto row = results.begin(); row != results.end(); ++row) { - pp->binds[4].zoneId = atoi(row[i]); i++; - i++; /* Instance ID can go here eventually */ - pp->binds[4].x = atoi(row[i]); i++; - pp->binds[4].y = atoi(row[i]); i++; - pp->binds[4].z = atoi(row[i]); i++; - pp->binds[4].heading = atoi(row[i]); i++; + i = 0; + /* Is home bind */ + if (atoi(row[6]) == 1){ + pp->binds[4].zoneId = atoi(row[i]); i++; + i++; /* Instance ID can go here eventually */ + pp->binds[4].x = atoi(row[i]); i++; + pp->binds[4].y = atoi(row[i]); i++; + pp->binds[4].z = atoi(row[i]); i++; + pp->binds[4].heading = atoi(row[i]); i++; + } + /* Is regular bind point */ + else{ + pp->binds[0].zoneId = atoi(row[i]); i++; + i++; /* Instance ID can go here eventually */ + pp->binds[0].x = atoi(row[i]); i++; + pp->binds[0].y = atoi(row[i]); i++; + pp->binds[0].z = atoi(row[i]); i++; + pp->binds[0].heading = atoi(row[i]); i++; + } } return true; } +bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value){ + std::string query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, lang_id, value); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterLanguage for character ID: %i, lang_id:%u value:%u done", character_id, lang_id, value); + return true; +} + +bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home){ + /* Save Home Bind Point */ + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, x, y, z, heading, is_home); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u x: %f y: %f z: %f heading: %f ishome: %u", character_id, zone_id, instance_id, x, y, z, heading, is_home); + auto results = QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + return true; +} + bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){ std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", 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::LoadCharacterMaterialColor(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++; - pp->item_tint[i].rgb.use_tint = atoi(row[r]); - printf("Material Load: %u %u %u %u\n", 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); +bool ZoneDatabase::SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value){ + std::string query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, skill_id, value); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSkill for character ID: %i, skill_id:%u value:%u done", character_id, skill_id, value); + return true; +} + +bool ZoneDatabase::SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id){ + std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u value:%u done", character_id, slot_id, disc_id); + return true; +} + +bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); + /* Save Tributes only if we have values... */ + for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != UINT32_MAX){ + std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + } } return true; } +bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name){ + char bandolier_name_esc[64]; + DoEscapeString(bandolier_name_esc, bandolier_name, strlen(bandolier_name)); + std::string query = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%u, %u, %u, %u, %u,'%s')", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name_esc); + auto results = QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBandolier for character ID: %i, bandolier_id: %u, bandolier_slot: %u item_id: %u, icon:%u band_name:%s done", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name); + if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + return true; +} + +bool ZoneDatabase::SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon) { + std::string query = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%u, %u, %u, %u)", character_id, potion_id, item_id, icon); + auto results = QueryDatabase(query); + if (!results.RowsAffected()){ std::cout << "ERROR Potionbelt Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + 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; } std::string query = StringFormat( "REPLACE INTO `character_data` (" " id, " @@ -1352,97 +1473,97 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " "%u" // RestTimer pp->RestTimer, " RestTimer) " - ")", - character_id, - account_id, - pp->name, - pp->last_name, - pp->gender, - pp->race, - pp->class_, - pp->level, - pp->deity, - pp->birthday, - pp->lastlogin, - pp->timePlayedMin, - pp->pvp, - pp->level2, - pp->anon, - pp->gm, - pp->intoxication, - pp->haircolor, - pp->beardcolor, - pp->eyecolor1, - pp->eyecolor2, - pp->hairstyle, - pp->beard, - pp->ability_time_seconds, - pp->ability_number, - pp->ability_time_minutes, - pp->ability_time_hours, - pp->title, - pp->suffix, - pp->exp, - pp->points, - pp->mana, - pp->cur_hp, - pp->STR, - pp->STA, - pp->CHA, - pp->DEX, - pp->INT, - pp->AGI, - pp->WIS, - pp->face, - pp->y, - pp->x, - pp->z, - pp->heading, - pp->pvp2, - pp->pvptype, - pp->autosplit, - pp->zone_change_count, - pp->drakkin_heritage, - pp->drakkin_tattoo, - pp->drakkin_details, - pp->toxicity, - pp->hunger_level, - pp->thirst_level, - pp->ability_up, - pp->zone_id, - pp->zoneInstance, - pp->leadAAActive, - pp->ldon_points_guk, - pp->ldon_points_mir, - pp->ldon_points_mmc, - pp->ldon_points_ruj, - pp->ldon_points_tak, - pp->ldon_points_available, - pp->tribute_time_remaining, - pp->showhelm, - pp->career_tribute_points, - pp->tribute_points, - pp->tribute_active, - pp->endurance, - pp->group_leadership_exp, - pp->raid_leadership_exp, - pp->group_leadership_points, - pp->raid_leadership_points, - pp->air_remaining, - pp->PVPKills, - pp->PVPDeaths, - pp->PVPCurrentPoints, - pp->PVPCareerPoints, - pp->PVPBestKillStreak, - pp->PVPWorstDeathStreak, - pp->PVPCurrentKillStreak, - pp->aapoints_spent, - pp->expAA, - pp->aapoints, - pp->groupAutoconsent, - pp->raidAutoconsent, - pp->guildAutoconsent, - pp->RestTimer + ")", + character_id, // " id, " + account_id, // " account_id, " + pp->name, // " `name`, " + pp->last_name, // " last_name, " + pp->gender, // " gender, " + pp->race, // " race, " + pp->class_, // " class, " + pp->level, // " `level`, " + pp->deity, // " deity, " + pp->birthday, // " birthday, " + pp->lastlogin, // " last_login, " + pp->timePlayedMin, // " time_played, " + pp->pvp, // " pvp_status, " + pp->level2, // " level2, " + pp->anon, // " anon, " + pp->gm, // " gm, " + pp->intoxication, // " intoxication, " + pp->haircolor, // " hair_color, " + pp->beardcolor, // " beard_color, " + pp->eyecolor1, // " eye_color_1, " + pp->eyecolor2, // " eye_color_2, " + pp->hairstyle, // " hair_style, " + pp->beard, // " beard, " + pp->ability_time_seconds, // " ability_time_seconds, " + pp->ability_number, // " ability_number, " + pp->ability_time_minutes, // " ability_time_minutes, " + pp->ability_time_hours, // " ability_time_hours, " + pp->title, // " title, " + pp->suffix, // " suffix, " + pp->exp, // " exp, " + pp->points, // " points, " + pp->mana, // " mana, " + pp->cur_hp, // " cur_hp, " + pp->STR, // " str, " + pp->STA, // " sta, " + pp->CHA, // " cha, " + pp->DEX, // " dex, " + pp->INT, // " `int`, " + pp->AGI, // " agi, " + pp->WIS, // " wis, " + pp->face, // " face, " + pp->y, // " y, " + pp->x, // " x, " + pp->z, // " z, " + pp->heading, // " heading, " + pp->pvp2, // " pvp2, " + pp->pvptype, // " pvp_type, " + pp->autosplit, // " autosplit_enabled, " + pp->zone_change_count, // " zone_change_count, " + pp->drakkin_heritage, // " drakkin_heritage, " + pp->drakkin_tattoo, // " drakkin_tattoo, " + pp->drakkin_details, // " drakkin_details, " + pp->toxicity, // " toxicity, " + pp->hunger_level, // " hunger_level, " + pp->thirst_level, // " thirst_level, " + pp->ability_up, // " ability_up, " + pp->zone_id, // " zone_id, " + pp->zoneInstance, // " zone_instance, " + pp->leadAAActive, // " leadership_exp_on, " + pp->ldon_points_guk, // " ldon_points_guk, " + pp->ldon_points_mir, // " ldon_points_mir, " + pp->ldon_points_mmc, // " ldon_points_mmc, " + pp->ldon_points_ruj, // " ldon_points_ruj, " + pp->ldon_points_tak, // " ldon_points_tak, " + pp->ldon_points_available, // " ldon_points_available, " + pp->tribute_time_remaining, // " tribute_time_remaining, " + pp->showhelm, // " show_helm, " + pp->career_tribute_points, // " career_tribute_points, " + pp->tribute_points, // " tribute_points, " + pp->tribute_active, // " tribute_active, " + pp->endurance, // " endurance, " + pp->group_leadership_exp, // " group_leadership_exp, " + pp->raid_leadership_exp, // " raid_leadership_exp, " + pp->group_leadership_points, // " group_leadership_points, " + pp->raid_leadership_points, // " raid_leadership_points, " + pp->air_remaining, // " air_remaining, " + pp->PVPKills, // " pvp_kills, " + pp->PVPDeaths, // " pvp_deaths, " + pp->PVPCurrentPoints, // " pvp_current_points, " + pp->PVPCareerPoints, // " pvp_career_points, " + pp->PVPBestKillStreak, // " pvp_best_kill_streak, " + pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, " + pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, " + pp->aapoints_spent, // " aa_points_spent, " + pp->expAA, // " aa_exp, " + pp->aapoints, // " aa_points, " + pp->groupAutoconsent, // " group_auto_consent, " + pp->raidAutoconsent, // " raid_auto_consent, " + pp->guildAutoconsent, // " guild_auto_consent, " + pp->RestTimer // " RestTimer) " ); auto results = database.QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR ZoneDatabase:SaveCharacterData: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } @@ -1459,6 +1580,10 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru if (pp->silver_bank < 0) { pp->silver_bank = 0; } if (pp->gold_bank < 0) { pp->gold_bank = 0; } if (pp->platinum_bank < 0) { pp->platinum_bank = 0; } + if (pp->platinum_cursor < 0) { pp->platinum_cursor = 0; } + if (pp->gold_cursor < 0) { pp->gold_cursor = 0; } + if (pp->silver_cursor < 0) { pp->silver_cursor = 0; } + if (pp->copper_cursor < 0) { pp->copper_cursor = 0; } std::string query = StringFormat( "REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," "platinum_bank, gold_bank, silver_bank, copper_bank," @@ -1499,12 +1624,16 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur bool ZoneDatabase::SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot){ std::string rquery = StringFormat("UPDATE `character_spells` SET `slot_id` = %u WHERE `slot_id` = %u AND `id` = %u", to_slot, from_slot, character_id); - clock_t t = std::clock(); /* Function timer start */ + clock_t t = std::clock(); /* Function timer start */ auto results = QueryDatabase(rquery); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSpellSwap for character ID: %u, from_slot: %u to_slot: %u spell: %u time: %f seconds", character_id, from_slot, to_slot, spell_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } +bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ + std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; +} + bool ZoneDatabase::SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ std::string query = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; } @@ -1513,8 +1642,12 @@ bool ZoneDatabase::DeleteCharacterSpell(uint32 character_id, uint32 spell_id, ui std::string query = StringFormat("DELETE FROM `character_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; } -bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ - std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; +bool ZoneDatabase::DeleteCharacterDisc(uint32 character_id, uint32 slot_id){ + std::string query = StringFormat("DELETE FROM `character_disciplines` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; +} + +bool ZoneDatabase::DeleteCharacterBandolier(uint32 character_id, uint32 band_id){ + std::string query = StringFormat("DELETE FROM `character_bandolier` WHERE `bandolier_id` = %u AND `id` = %u", band_id, character_id); QueryDatabase(query); return true; } bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ @@ -1715,7 +1848,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->aggroradius = (int32)atoi(row[r++]); // set defaultvalue for aggroradius if (tmpNPCType->aggroradius <= 0) - tmpNPCType->aggroradius = 70; + tmpNPCType->aggroradius = 70; tmpNPCType->assistradius = (int32)atoi(row[r++]); if (tmpNPCType->assistradius <= 0) tmpNPCType->assistradius = tmpNPCType->aggroradius; @@ -3715,4 +3848,6 @@ void ZoneDatabase::StoreCharacterLookup(uint32 char_id) { " FROM `character_` " " WHERE `id` = %i ", char_id); QueryDatabase(c_lookup); -} \ No newline at end of file +} + + diff --git a/zone/zonedb.h b/zone/zonedb.h index 705377a39..659dad673 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -6,6 +6,7 @@ #include "../common/loottable.h" #include "zonedump.h" #include "../common/faction.h" +#include //#include "doors.h" struct wplist { @@ -212,9 +213,7 @@ public: ZoneDatabase(const char* host, const char* user, const char* passwd, const char* database,uint32 port); virtual ~ZoneDatabase(); - /* - * Objects and World Containers - */ + /* Objects and World Containers */ void LoadWorldContainer(uint32 parentid, ItemInst* container); void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container); void DeleteWorldContainer(uint32 parent_id,uint32 zone_id); @@ -223,10 +222,7 @@ public: void DeleteObject(uint32 id); Ground_Spawns* LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs); - /* - * Traders - */ - + /* Traders */ void SaveTraderItem(uint32 char_id,uint32 itemid,uint32 uniqueid, int32 charges,uint32 itemcost,uint8 slot); void UpdateTraderItemCharges(int char_id, uint32 ItemInstID, int32 charges); void UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charges, uint32 NewPrice); @@ -236,16 +232,13 @@ public: Trader_Struct* LoadTraderItem(uint32 char_id); TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id); - // Buyer/Barter - // + /* Buyer/Barter */ void AddBuyLine(uint32 CharID, uint32 BuySlot, uint32 ItemID, const char *ItemName, uint32 Quantity, uint32 Price); void RemoveBuyLine(uint32 CharID, uint32 BuySlot); void DeleteBuyLines(uint32 CharID); void UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity); - /* - * General Character Related Stuff - */ + /* General Character Related Stuff */ void StoreCharacterLookup(uint32 char_id); bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs); uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs); @@ -267,28 +260,36 @@ public: bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ - bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); - bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); - bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); - 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); + bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); + bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); + 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); + bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); + bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); + bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); + bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); + bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); /* Character Data Deletes */ - bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); - bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); + bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); - /* - * Character Inventory - */ + /* Character Inventory */ bool NoRentExpired(const char* name); - /* - * Corpses - */ + /* Corpses */ bool GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes); uint32 CreatePlayerCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading); bool CreatePlayerCorpseBackup(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, uchar* data, uint32 datasize, float x, float y, float z, float heading); @@ -314,9 +315,7 @@ public: uint32 GetPlayerCorpseItemAt(uint32 corpse_id, uint16 slotid); uint32 GetPlayerCorpseTimeLeft(uint8 corpse, uint8 type); - /* - * Faction - */ + /* Faction */ bool GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, int32* value, uint8* temp, int32* primary_faction = 0); bool GetFactionData(FactionMods* fd, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id); //rembrant, needed for factions Dec, 16 2001 bool GetFactionName(int32 faction_id, char* name, uint32 buflen); // rembrant, needed for factions Dec, 16 2001 @@ -324,9 +323,7 @@ public: bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // rembrant, needed for factions Dec, 16 2001 bool LoadFactionData(); - /* - * AAs - */ + /* AAs */ bool LoadAAEffects(); bool LoadAAEffects2(); bool LoadSwarmSpells(); @@ -338,9 +335,7 @@ public: uint32 CountAAEffects(); void FillAAEffects(SendAA_Struct* aa_struct); - /* - * Zone related - */ + /* Zone related */ bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename); bool SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct* zd); bool LoadStaticZonePoints(LinkedList* zone_point_list,const char* zonename, uint32 version); @@ -348,9 +343,7 @@ public: uint8 GetUseCFGSafeCoords(); int getZoneShutDownDelay(uint32 zoneID, uint32 version); - /* - * Spawns and Spawn Points - */ + /* Spawns and Spawn Points */ bool LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list); bool LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list); bool PopulateZoneSpawnList(uint32 zoneid, LinkedList &spawn2_list, int16 version, uint32 repopdelay = 0); @@ -360,9 +353,7 @@ public: uint32 GetSpawnTimeLeft(uint32 id, uint16 instance_id); void UpdateSpawn2Status(uint32 id, uint8 new_status); - /* - * Grids/Paths - */ + /* Grids/Paths */ uint32 GetFreeGrid(uint16 zoneid); void DeleteGrid(Client *c, uint32 sg2, uint32 grid_num, bool grid_too,uint16 zoneid); void DeleteWaypoint(Client *c, uint32 grid_num, uint32 wp_num,uint16 zoneid); @@ -378,9 +369,7 @@ public: int GetHighestGrid(uint32 zoneid); int GetHighestWaypoint(uint32 zoneid, uint32 gridid); - /* - * NPCs - */ + /* NPCs */ const NPCType* GetNPCType(uint32 id); uint32 NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn = 0, uint32 extra = 0); // 0 = Create 1 = Add; 2 = Update; 3 = Remove; 4 = Delete bool SetSpecialAttkFlag(uint8 id, const char* flag); @@ -394,9 +383,7 @@ public: DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID); DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID); - /* - * Mercs - */ + /* Mercs */ const NPCType* GetMercType(uint32 id, uint16 raceid, uint32 clientlevel); void LoadMercEquipment(Merc *merc); void SaveMercBuffs(Merc *merc); @@ -408,9 +395,7 @@ public: //void LoadMercTypesForMercMerchant(NPC *merchant); //void LoadMercsForMercMerchant(NPC *merchant); - /* - * Petitions - */ + /* Petitions */ void UpdateBug(BugStruct* bug); void UpdateBug(PetitionBug_Struct* bug); void DeletePetitionFromDB(Petition* wpet); @@ -418,16 +403,11 @@ public: void InsertPetitionToDB(Petition* wpet); void RefreshPetitionsFromDB(); - - /* - * Merchants - */ + /* Merchants */ void SaveMerchantTemp(uint32 npcid, uint32 slot, uint32 item, uint32 charges); void DeleteMerchantTemp(uint32 npcid, uint32 slot); - /* - * Tradeskills - */ + /* Tradeskills */ bool GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */ @@ -436,14 +416,10 @@ public: bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); - /* - * Tribute - */ + /* Tribute */ bool LoadTributes(); - /* - * Doors - */ + /* Doors */ bool DoorIsOpen(uint8 door_id,const char* zone_name); void SetDoorPlace(uint8 value,uint8 door_id,const char* zone_name); bool LoadDoors(int32 iDoorCount, Door *into, const char *zone_name, int16 version); @@ -456,64 +432,46 @@ public: int32 GetDoorsDBCountPlusOne(const char *zone_name, int16 version); void InsertDoor(uint32 did, uint16 ddoorid, const char* ddoor_name, float dxpos, float dypos, float dzpos, float dheading, uint8 dopentype, uint16 dguildid, uint32 dlockpick, uint32 dkeyitem, uint8 ddoor_param, uint8 dinvert, int dincline, uint16 dsize); - /* - * Blocked Spells - */ - + /* Blocked Spells */ int32 GetBlockedSpellsCount(uint32 zoneid); bool LoadBlockedSpells(int32 blockedSpellsCount, ZoneSpellsBlocked* into, uint32 zoneid); - /* - * Traps - */ + /* Traps */ bool LoadTraps(const char* zonename, int16 version); char* GetTrapMessage(uint32 trap_id); - /* - * Time - */ + /* Time */ uint32 GetZoneTZ(uint32 zoneid, uint32 version); bool SetZoneTZ(uint32 zoneid, uint32 version, uint32 tz); - /* - * Group - */ + /* Group */ void RefreshGroupFromDB(Client *c); uint8 GroupCount(uint32 groupid); - /* - * Raid - */ + + /* Raid */ uint8 RaidGroupCount(uint32 raidid, uint32 groupid); - /* - * Instancing - */ + /* Instancing */ void ListAllInstances(Client* c, uint32 charid); - /* - * QGlobals - */ + /* QGlobals */ void QGlobalPurge(); - /* - * Alternate Currency - */ + /* Alternate Currency */ void LoadAltCurrencyValues(uint32 char_id, std::map ¤cy); void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value); /* - * Misc stuff. - * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD - * REALLY HAS NO BETTER SECTION + * Misc stuff. + * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD + * REALLY HAS NO BETTER SECTION */ bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid); void GetEventLogs(const char* name,char* target,uint32 account_id=0,uint8 eventid=0,char* detail=0,char* timestamp=0, CharacterEventLog_Struct* cel=0); uint32 GetKarma(uint32 acct_id); void UpdateKarma(uint32 acct_id, uint32 amount); - /* - * Things which really dont belong here... - */ + /* Things which really dont belong here... */ int16 CommandRequirement(const char* commandname); protected: diff --git a/zone/zonedbasync.cpp b/zone/zonedbasync.cpp deleted file mode 100644 index 454252ab6..000000000 --- a/zone/zonedbasync.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "../common/debug.h" -#include -#include "entity.h" -#include "masterentity.h" -#include "../common/string_util.h" -#include "../common/breakdowns.h" -#include - -extern EntityList entity_list; - -void DispatchFinishedDBAsync(DBAsyncWork* dbaw) { - uint32_breakdown workpt; - workpt = dbaw->WPT(); - switch (workpt.b4()) { - case DBA_b4_Entity: { - Entity* entity = entity_list.GetID(workpt.w2_3()); - if (!entity) - break; - entity->DBAWComplete(workpt.b1(), dbaw); - break; - } - default: { - std::cout << "Error: DispatchFinishedDBAsync(): Unknown workpt.b4: " << (int) workpt.b4() << ", workpt=" << workpt << std::endl; - break; - } - } - safe_delete(dbaw); -} - -#define MAX_TO_DELETE 10 -#define MAX_BACKUPS 5 -bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork) { // return true means delete data - char errbuf[MYSQL_ERRMSG_SIZE] = "dbaq == 0"; - MYSQL_RES* result = 0; - MYSQL_ROW row; - char* query = 0; - uint32 i; - uint8 ToDeleteIndex = 0; - uint32 ToDelete[MAX_TO_DELETE]; - memset(ToDelete, 0, sizeof(ToDelete)); - - uint32 BackupAges[MAX_BACKUPS]; // must be sorted, highest value in lowest index - memset(BackupAges, 0, sizeof(BackupAges)); - - bool FoundBackup[MAX_BACKUPS]; - memset(FoundBackup, 0, sizeof(FoundBackup)); - - BackupAges[0] = 86400; - BackupAges[1] = 3600; - - DBAsyncQuery* dbaq = iWork->PopAnswer(); - if (dbaq && dbaq->GetAnswer(errbuf, &result)) { - while ((row = mysql_fetch_row(result))) { - for (i=0; i BackupAges[i]) - i = MAX_BACKUPS; - else if (!FoundBackup[i]) { - FoundBackup[i] = true; - break; - } - } - if (i >= MAX_BACKUPS) - ToDelete[ToDeleteIndex++] = atoi(row[0]); - if (ToDeleteIndex >= MAX_TO_DELETE) - break; - } - if (ToDelete[0]) { - uint32 len = 0, size = 0; - AppendAnyLenString(&query, &size, &len, "Delete from character_backup where id=%u", ToDelete[0]); - for (uint8 i=1; iwrite(EQEMuLog::Error, "Error in DBAsyncCB_CharacterBackup query2 '%s' %s", query, errbuf); - safe_delete_array(query); - return true; - } - safe_delete_array(query); - } - bool needtoinsert = false; - for (i=0; iWPT()), errbuf)) { - std::cout << "Error in DBAsyncCB_CharacterBackup query3 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return true; - } - safe_delete_array(query); - } - } - else { -// std::cout << "Error in DBAsyncCB_CharacterBackup query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return true; - } - return true; -} diff --git a/zone/zonedbasync.h b/zone/zonedbasync.h deleted file mode 100644 index b91389322..000000000 --- a/zone/zonedbasync.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef ZONEDBASYNC_H -#define ZONEDBASYNC_H - -#include "../common/dbasync.h" -void DispatchFinishedDBAsync(DBAsyncWork* iDBAW); -bool DBAsyncCB_CharacterBackup(DBAsyncWork* iWork); - -#define DBA_b4_Main 1 -#define DBA_b4_Worldserver 2 -#define DBA_b4_Zone 3 -#define DBA_b4_Entity 4 - -#define DBA_b1_Entity_SeeQPT 0 -#define DBA_b1_Entity_Client_InfoForLogin 1 -#define DBA_b1_Entity_Client_Save 2 -#define DBA_b1_Entity_Client_Backup 3 -#define DBA_b1_Entity_Corpse_Backup 4 -#define DBA_b1_Zone_MerchantLists 5 -#define DBA_b1_Zone_MerchantListsTemp 6 - -#endif - diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 88351ee3e..0eb204d1f 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -50,10 +50,6 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { #endif ZoneChange_Struct* zc=(ZoneChange_Struct*)app->pBuffer; - printf("INCOMING CLIENT\n\n"); - printf("%s\n", zc->char_name); - printf("%u\n", zc->zoneID); - uint16 target_zone_id = 0; uint16 target_instance_id = zc->instanceID; ZonePoint* zone_point = nullptr; @@ -568,7 +564,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z if(ReadyToZone) { zone_mode = zm; - printf("\n\n ZONE MODE %u \n\n", zm); if(zm == ZoneToBindPoint) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + iZoneNameLength); ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; @@ -602,10 +597,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z gmg->instance_id = instance_id; gmg->type = 0x01; //an observed value, not sure of meaning - printf("gmg->zone_id %u \n", gmg->zone_id); - printf("gmg->x %u \n", gmg->x); - printf("gmg->y %u \n", gmg->y); - outapp->priority = 6; FastQueuePacket(&outapp); safe_delete(outapp); @@ -726,6 +717,7 @@ void Client::SetBindPoint(int to_zone, float new_x, float new_y, float new_z) { m_pp.binds[0].y = new_y; m_pp.binds[0].z = new_z; } + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, 0, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0, 0); } void Client::GoToBind(uint8 bindnum) { From ca7dd7d741334b0e47f94f73e74404c585c1febf Mon Sep 17 00:00:00 2001 From: akkadius Date: Sat, 6 Sep 2014 13:53:54 -0500 Subject: [PATCH 12/56] - Improved speed of character database conversion x1000 by changing query style - Adjusted AA MySQL saves for 100x speed increase - Removed StoreCharacter lookup methods as they will no longer be necessary - Some other cleanup --- common/database.cpp | 128 +++++++++++++++++++++++++++++++------------- zone/aa.cpp | 11 ++-- zone/client.cpp | 28 ++++------ zone/zonedb.cpp | 10 ---- zone/zonedb.h | 1 - 5 files changed, 108 insertions(+), 70 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 5de92ba08..ca51636ce 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -793,8 +793,7 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID } -void Database::GetCharName(uint32 char_id, char* name) { - +void Database::GetCharName(uint32 char_id, char* name) { std::string query = StringFormat("SELECT `name` FROM `character_data` WHERE id='%i'", char_id); auto results = QueryDatabase(query); @@ -1209,7 +1208,7 @@ bool Database::CheckDatabaseConversions() { // querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); // WHERE `account_id` = 11001 int char_iter_count = 0; - querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); + querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `account_id` = 11001"); if (RunQuery(query, querylen, errbuf, &result)) { safe_delete_array(query); while (row = mysql_fetch_row(result)) { @@ -1454,8 +1453,8 @@ bool Database::CheckDatabaseConversions() { ")", character_id, account_id, - pp->name, - pp->last_name, + EscapeString(pp->name).c_str(), + EscapeString(pp->last_name).c_str(), pp->gender, pp->race, pp->class_, @@ -1479,8 +1478,8 @@ bool Database::CheckDatabaseConversions() { pp->ability_number, pp->ability_time_minutes, pp->ability_time_hours, - pp->title, - pp->suffix, + EscapeString(pp->title).c_str(), + EscapeString(pp->suffix).c_str(), pp->exp, pp->points, pp->mana, @@ -1546,15 +1545,26 @@ bool Database::CheckDatabaseConversions() { results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR PP Data Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + // str.append(str2); + /* Run AA Convert */ - for (i = 0; i < MAX_PP_AA_ARRAY; i++){ + /* + We set a first entry variable because we need the first initial piece of the query to be declared + This is to speed up the INSERTS and trim down the amount of individual sends during the process. + The speed difference is dramatic + */ + int first_entry = 0; + for (i = 1; i < MAX_PP_AA_ARRAY; i++){ if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ - rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" - " VALUES (%u, %u, %u, %u)", - character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - } - } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + } + } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Bind Home Convert */ rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" @@ -1569,71 +1579,117 @@ bool Database::CheckDatabaseConversions() { results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Language Convert */ + first_entry = 0; for (i = 0; i < MAX_PP_LANGUAGE; i++){ if (pp->languages[i] > 0){ - rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Skill Convert */ + first_entry = 0; for (i = 0; i < MAX_PP_SKILL; i++){ - if (pp->skills[i] > 0){ - rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (pp->skills[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Spell Convert */ + first_entry = 0; for (i = 0; i < MAX_PP_SPELLBOOK; i++){ if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ - rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]); } } - /* Run Max Memmed Spell Convert */ + // std::cout << rquery << "\n"; + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Max Memmed Spell Convert */ + first_entry = 0; for (i = 0; i < MAX_PP_MEMSPELL; i++){ - if (pp->mem_spells[i] > 0){ - rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); - QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Discipline Convert */ + first_entry = 0; for (i = 0; i < MAX_PP_DISCIPLINES; i++){ if (pp->disciplines.values[i] > 0){ - rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Material Color Convert */ + first_entry = 0; for (i = 0; i < _MaterialCount; i++){ if (pp->item_tint[i].color > 0){ - 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); - // printf("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u);\n", 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); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 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); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%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); } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Tribute Convert */ + first_entry = 0; for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0){ - rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Bandolier Convert */ + first_entry = 0; for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ if (pp->bandoliers[i].items[si].item_id > 0){ - rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); } } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } /* Run Potion Belt Convert */ + first_entry = 0; for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ if (pp->potionbelt.items[i].item_id > 0){ - rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + } } + results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } /* Print out the entire Player Profile for testing */ diff --git a/zone/aa.cpp b/zone/aa.cpp index 2af81a619..f546e59f0 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1035,8 +1035,7 @@ void Client::BuyAA(AA_Action* action) uint32 real_cost; std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - if(RequiredLevel != AARequiredLevelAndCost.end()) - { + if(RequiredLevel != AARequiredLevelAndCost.end()) { real_cost = RequiredLevel->second.Cost; } else @@ -1064,8 +1063,10 @@ void Client::BuyAA(AA_Action* action) SendAATable(); - //we are building these messages ourself instead of using the stringID to work around patch discrepencies - //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 + /* + We are building these messages ourself instead of using the stringID to work around patch discrepencies + these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 + */ /* Initial purchase of an AA ability */ if (cur_level < 1){ @@ -1088,8 +1089,6 @@ void Client::BuyAA(AA_Action* action) } } - - SendAAStats(); CalcBonuses(); diff --git a/zone/client.cpp b/zone/client.cpp index 962715b86..2a85bfab7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -477,13 +477,10 @@ void Client::ReportConnectingState() { }; } -inline double clock_diff_to_sec(long clock_diff) -{ - return double(clock_diff) / CLOCKS_PER_SEC; -} - bool Client::SaveAA(){ clock_t t = std::clock(); /* Function timer start */ + int first_entry = 0; + std::string rquery; /* Save Player AA */ int spentpoints = 0; for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { @@ -509,12 +506,15 @@ bool Client::SaveAA(){ m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { if (aa[a]->AA > 0 && aa[a]->value){ - std::string rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" - " VALUES (%u, %u, %u, %u)", - character_id, a, aa[a]->AA, aa[a]->value); - auto results = database.QueryDatabase(rquery); + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value); } } + auto results = database.QueryDatabase(rquery); LogFile->write(EQEMuLog::Status, "Issuing Client AA Save... CID: %i Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } @@ -581,15 +581,9 @@ bool Client::Save(uint8 iCommitNow) { p_timers.Store(&database); database.SaveCharacterTribute(this->CharacterID(), &m_pp); + SaveTaskState(); /* Save Character Task */ + database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); /* Save Character Data */ - /* Save Character Task */ - SaveTaskState(); - - /* Save Character Data */ - database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); - - /* Mirror Character Data */ - database.StoreCharacterLookup(this->CharacterID()); LogFile->write(EQEMuLog::Status, "Client::Save %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 77e5739ee..ebf3957b6 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3841,13 +3841,3 @@ bool ZoneDatabase::GetFactionIdsForNPC(uint32 nfl_id, std::list Date: Sat, 6 Sep 2014 21:50:29 -0500 Subject: [PATCH 13/56] - Ported inspect_messages to character_inspect_messages - Ported character leadership abilities to character_leadership_abilities - Removed player profile debug printing - Refactored total time entitled on account to load from the sum of time_played from all characters in character_data --- common/database.cpp | 1648 +++++++++++++++++----------------------- common/extprofile.h | 35 +- common/shareddb.cpp | 66 +- common/shareddb.h | 4 +- zone/aa.cpp | 13 +- zone/client.cpp | 25 +- zone/client_packet.cpp | 43 +- zone/zone.cpp | 2 +- zone/zonedb.cpp | 236 +++--- zone/zonedb.h | 7 +- 10 files changed, 935 insertions(+), 1144 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index ca51636ce..7c8c988cf 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -329,37 +329,39 @@ bool Database::DeleteCharacter(char *name) { for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); } if (charid <= 0){ std::cerr << "Database::DeleteCharacter :: Character not found, stopping delete...\n"; return false; } - query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); #ifdef BOTS query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); #else @@ -819,14 +821,11 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) } bool Database::CheckDatabaseConversions() { - /* Set all of this ugliness */ - char errbuf[MYSQL_ERRMSG_SIZE]; char errbuf2[MYSQL_ERRMSG_SIZE]; char errbuf3[MYSQL_ERRMSG_SIZE]; - char *query = 0; char *query2 = 0; char *query3 = 0; - uint32 querylen; uint32 querylen2; uint32 querylen3; - MYSQL_RES *result; MYSQL_RES *result2; MYSQL_RES *result3; - MYSQL_ROW row; MYSQL_ROW row2; MYSQL_ROW row3; - unsigned long* lengths; + unsigned int lengths; + unsigned int lengths_e; + std::string squery; PlayerProfile_Struct* pp; + ExtendedProfile_Struct* e_pp; uint32 pplen = 0; uint32 i; int character_id = 0; @@ -870,101 +869,109 @@ bool Database::CheckDatabaseConversions() { if (results.RowCount() == 0){ printf("Table: `character_data` doesn't exist... creating..."); rquery = StringFormat( - "CREATE TABLE `character_data` ( " - "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " - "`account_id` int(11) NOT NULL DEFAULT '0', " - "`name` varchar(64) NOT NULL DEFAULT '', " - "`last_name` varchar(64) NOT NULL DEFAULT '', " - "`gender` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`race` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`class` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`level` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`deity` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`birthday` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`last_login` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`time_played` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_status` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`intoxication` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`hair_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`beard_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`eye_color_1` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`eye_color_2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`hair_style` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`beard` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ability_time_seconds` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ability_number` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ability_time_minutes` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ability_time_hours` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`title` varchar(32) NOT NULL DEFAULT '', " - "`suffix` varchar(32) NOT NULL DEFAULT '', " - "`exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`mana` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`cur_hp` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`str` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`sta` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`cha` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`dex` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`int` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`agi` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`wis` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`face` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`y` float NOT NULL DEFAULT '0', " - "`x` float NOT NULL DEFAULT '0', " - "`z` float NOT NULL DEFAULT '0', " - "`heading` float NOT NULL DEFAULT '0', " - "`pvp2` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_type` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`autosplit_enabled` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`zone_change_count` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`leadership_exp_on` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ldon_points_guk` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ldon_points_mir` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ldon_points_mmc` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ldon_points_ruj` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ldon_points_tak` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`ldon_points_available` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`tribute_time_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`show_helm` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`career_tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`tribute_active` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`endurance` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`group_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`raid_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`group_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`raid_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`air_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_kills` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_deaths` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_current_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_career_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_best_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_worst_death_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`pvp_current_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`aa_points_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`aa_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`aa_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "`group_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`raid_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`guild_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " - "`RestTimer` int(11) UNSIGNED NOT NULL DEFAULT 0, " - "PRIMARY KEY(`id`), " - "UNIQUE KEY `name` (`name`), " - "KEY `account_id` (`account_id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + "CREATE TABLE `character_data` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`account_id` int(11) NOT NULL DEFAULT '0', " + "`name` varchar(64) NOT NULL DEFAULT '', " + "`last_name` varchar(64) NOT NULL DEFAULT '', " + "`title` varchar(32) NOT NULL DEFAULT '', " + "`suffix` varchar(32) NOT NULL DEFAULT '', " + "`zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`y` float NOT NULL DEFAULT '0', " + "`x` float NOT NULL DEFAULT '0', " + "`z` float NOT NULL DEFAULT '0', " + "`heading` float NOT NULL DEFAULT '0', " + "`gender` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`race` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`class` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`deity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`birthday` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`last_login` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`time_played` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`face` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hair_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hair_style` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`beard` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`beard_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`eye_color_1` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`eye_color_2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_seconds` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_number` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_minutes` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_hours` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_points_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`cur_hp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`mana` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`endurance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`intoxication` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`str` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`sta` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`cha` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`dex` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`int` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`agi` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`wis` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`zone_change_count` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_guk` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_mir` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_mmc` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_ruj` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_tak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_available` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_time_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`career_tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_active` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_status` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_kills` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_deaths` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_current_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_career_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_best_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_worst_death_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_current_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp2` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_type` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`show_helm` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`guild_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`leadership_exp_on` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`RestTimer` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`air_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`autosplit_enabled` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`lfp` tinyint(1) unsigned NOT NULL DEFAULT '0', " + "`lfg` tinyint(1) unsigned NOT NULL DEFAULT '0', " + "`mailkey` char(16) NOT NULL DEFAULT '', " + "`xtargets` tinyint(3) unsigned NOT NULL DEFAULT '5', " + "`firstlogon` tinyint(3) NOT NULL DEFAULT '0', " + "`e_aa_effects` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`e_percent_to_aa` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`e_expended_aa_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "PRIMARY KEY(`id`), " + "UNIQUE KEY `name` (`name`), " + "KEY `account_id` (`account_id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " ); QueryDatabase(rquery); printf(" done...\n"); @@ -1200,813 +1207,594 @@ bool Database::CheckDatabaseConversions() { QueryDatabase(rquery); printf(" done...\n"); } - + /* Check for table `character_potionbelt` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_inspect_messages'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_inspect_messages` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_inspect_messages` ( " + "`id` int(11) unsigned NOT NULL AUTO_INCREMENT, " + "`inspect_message` varchar(255) NOT NULL DEFAULT '', " + "PRIMARY KEY(`id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_leadership_abilities` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_leadership_abilities'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_leadership_abilities` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_leadership_abilities` (" + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`rank` smallint(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"); } - // querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `id` = 61238"); // WHERE `account_id` = 11001 + // Testing account = 11001 int char_iter_count = 0; - querylen = MakeAnyLenString(&query, "SELECT `id` FROM `character_` WHERE `account_id` = 11001"); - if (RunQuery(query, querylen, errbuf, &result)) { - safe_delete_array(query); - while (row = mysql_fetch_row(result)) { - char_iter_count++; - querylen2 = MakeAnyLenString(&query2, "SELECT `id`, `profile`, `name`, `level`, `account_id` FROM `character_` WHERE `id` = %i", atoi(row[0])); - if (RunQuery(query2, querylen2, errbuf2, &result2)){ - safe_delete_array(query2); - row2 = mysql_fetch_row(result2); - 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)) { - memcpy(pp, row2[1], sizeof(PlayerProfile_Struct)); - // 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 { - // 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; - } + rquery = StringFormat("SELECT `id` FROM `character_` WHERE `account_id` = 11001"); + results = QueryDatabase(rquery); - /* Loading Status on conversion */ - if (runconvert == 1){ - std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; - loadbar(char_iter_count, number_of_characters, 50); + uint8 firstlogon = 0; + uint8 lfg = 0; + uint8 lfp = 0; + std::string mailkey; + uint8 xtargets = 0; + std::string inspectmessage; - /* Run Currency Convert */ - std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," - "platinum_bank, gold_bank, silver_bank, copper_bank," - "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " - "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" - "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", - character_id, - pp->platinum, - pp->gold, - pp->silver, - pp->copper, - pp->platinum_bank, - pp->gold_bank, - pp->silver_bank, - pp->copper_bank, - pp->platinum_cursor, - pp->gold_cursor, - pp->silver_cursor, - pp->copper_cursor, - pp->currentRadCrystals, - pp->careerRadCrystals, - pp->currentEbonCrystals, - pp->careerEbonCrystals - ); - auto results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + char_iter_count++; + squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", atoi(row[0])); + auto results2 = QueryDatabase(squery); + auto row2 = results2.begin(); + pp = (PlayerProfile_Struct*)row2[1]; + e_pp = (ExtendedProfile_Struct*)row2[11]; + character_id = atoi(row[0]); + account_id = atoi(row2[4]); + /* Convert some data from the character_ table that is still relevant */ + firstlogon = atoi(row2[5]); + lfg = atoi(row2[6]); + lfp = atoi(row2[7]); + mailkey = row2[8]; + xtargets = atoi(row2[9]); + inspectmessage = row2[10]; - if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } - - /* Run Character Data Convert */ - rquery = StringFormat( - "REPLACE INTO `character_data` (" - "id," - "account_id," - "`name`," - "last_name," - "gender," - "race," - "class," - "`level`," - "deity," - "birthday," - "last_login," - "time_played," - "pvp_status," - "level2," - "anon," - "gm," - "intoxication," - "hair_color," - "beard_color," - "eye_color_1," - "eye_color_2," - "hair_style," - "beard," - "ability_time_seconds," - "ability_number," - "ability_time_minutes," - "ability_time_hours," - "title," - "suffix," - "exp," - "points," - "mana," - "cur_hp," - "str," - "sta," - "cha," - "dex," - "`int`," - "agi," - "wis," - "face," - "y," - "x," - "z," - "heading," - "pvp2," - "pvp_type," - "autosplit_enabled," - "zone_change_count," - "drakkin_heritage," - "drakkin_tattoo," - "drakkin_details," - "toxicity," - "hunger_level," - "thirst_level," - "ability_up," - "zone_id," - "zone_instance," - "leadership_exp_on," - "ldon_points_guk," - "ldon_points_mir," - "ldon_points_mmc," - "ldon_points_ruj," - "ldon_points_tak," - "ldon_points_available," - "tribute_time_remaining," - "show_helm," - "career_tribute_points," - "tribute_points," - "tribute_active," - "endurance," - "group_leadership_exp," - "raid_leadership_exp," - "group_leadership_points," - "raid_leadership_points," - "air_remaining," - "pvp_kills," - "pvp_deaths," - "pvp_current_points," - "pvp_career_points," - "pvp_best_kill_streak," - "pvp_worst_death_streak," - "pvp_current_kill_streak," - "aa_points_spent," - "aa_exp," - "aa_points," - "group_auto_consent," - "raid_auto_consent," - "guild_auto_consent," - "RestTimer)" - "VALUES (" - "%u," // id - "%u," // account_id - "'%s'," // `name` - "'%s'," // last_name - "%u," // gender - "%u," // race - "%u," // class - "%u," // `level` - "%u," // deity - "%u," // birthday - "%u," // last_login - "%u," // time_played - "%u," // pvp_status - "%u," // level2 - "%u," // anon - "%u," // gm - "%u," // intoxication - "%u," // hair_color - "%u," // beard_color - "%u," // eye_color_1 - "%u," // eye_color_2 - "%u," // hair_style - "%u," // beard - "%u," // ability_time_seconds - "%u," // ability_number - "%u," // ability_time_minutes - "%u," // ability_time_hours - "'%s'," // title - "'%s'," // suffix - "%u," // exp - "%u," // points - "%u," // mana - "%u," // cur_hp - "%u," // str - "%u," // sta - "%u," // cha - "%u," // dex - "%u," // `int` - "%u," // agi - "%u," // wis - "%u," // face - "%f," // y - "%f," // x - "%f," // z - "%f," // heading - "%u," // pvp2 - "%u," // pvp_type - "%u," // autosplit_enabled - "%u," // zone_change_count - "%u," // drakkin_heritage - "%u," // drakkin_tattoo - "%u," // drakkin_details - "%i," // toxicity - "%u," // hunger_level - "%u," // thirst_level - "%u," // ability_up - "%u," // zone_id - "%u," // zone_instance - "%u," // leadership_exp_on - "%u," // ldon_points_guk - "%u," // ldon_points_mir - "%u," // ldon_points_mmc - "%u," // ldon_points_ruj - "%u," // ldon_points_tak - "%u," // ldon_points_available - "%u," // tribute_time_remaining - "%u," // show_helm - "%u," // career_tribute_points - "%u," // tribute_points - "%u," // tribute_active - "%u," // endurance - "%u," // group_leadership_exp - "%u," // raid_leadership_exp - "%u," // group_leadership_points - "%u," // raid_leadership_points - "%u," // air_remaining - "%u," // pvp_kills - "%u," // pvp_deaths - "%u," // pvp_current_points - "%u," // pvp_career_points - "%u," // pvp_best_kill_streak - "%u," // pvp_worst_death_streak - "%u," // pvp_current_kill_streak - "%u," // aa_points_spent - "%u," // aa_exp - "%u," // aa_points - "%u," // group_auto_consent - "%u," // raid_auto_consent - "%u," // guild_auto_consent - "%u" // RestTimer - ")", - character_id, - account_id, - EscapeString(pp->name).c_str(), - EscapeString(pp->last_name).c_str(), - pp->gender, - pp->race, - pp->class_, - pp->level, - pp->deity, - pp->birthday, - pp->lastlogin, - pp->timePlayedMin, - pp->pvp, - pp->level2, - pp->anon, - pp->gm, - pp->intoxication, - pp->haircolor, - pp->beardcolor, - pp->eyecolor1, - pp->eyecolor2, - pp->hairstyle, - pp->beard, - pp->ability_time_seconds, - pp->ability_number, - pp->ability_time_minutes, - pp->ability_time_hours, - EscapeString(pp->title).c_str(), - EscapeString(pp->suffix).c_str(), - pp->exp, - pp->points, - pp->mana, - pp->cur_hp, - pp->STR, - pp->STA, - pp->CHA, - pp->DEX, - pp->INT, - pp->AGI, - pp->WIS, - pp->face, - pp->y, - pp->x, - pp->z, - pp->heading, - pp->pvp2, - pp->pvptype, - pp->autosplit, - pp->zone_change_count, - pp->drakkin_heritage, - pp->drakkin_tattoo, - pp->drakkin_details, - pp->toxicity, - pp->hunger_level, - pp->thirst_level, - pp->ability_up, - pp->zone_id, - pp->zoneInstance, - pp->leadAAActive, - pp->ldon_points_guk, - pp->ldon_points_mir, - pp->ldon_points_mmc, - pp->ldon_points_ruj, - pp->ldon_points_tak, - pp->ldon_points_available, - pp->tribute_time_remaining, - pp->showhelm, - pp->career_tribute_points, - pp->tribute_points, - pp->tribute_active, - pp->endurance, - pp->group_leadership_exp, - pp->raid_leadership_exp, - pp->group_leadership_points, - pp->raid_leadership_points, - pp->air_remaining, - pp->PVPKills, - pp->PVPDeaths, - pp->PVPCurrentPoints, - pp->PVPCareerPoints, - pp->PVPBestKillStreak, - pp->PVPWorstDeathStreak, - pp->PVPCurrentKillStreak, - pp->aapoints_spent, - pp->expAA, - pp->aapoints, - pp->groupAutoconsent, - pp->raidAutoconsent, - pp->guildAutoconsent, - pp->RestTimer - ); - results = QueryDatabase(rquery); - if (!results.RowsAffected()){ std::cout << "ERROR PP Data Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - - // str.append(str2); - - /* Run AA Convert */ - /* - We set a first entry variable because we need the first initial piece of the query to be declared - This is to speed up the INSERTS and trim down the amount of individual sends during the process. - The speed difference is dramatic - */ - int first_entry = 0; - for (i = 1; i < MAX_PP_AA_ARRAY; i++){ - if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" - " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - - /* Run Bind Home Convert */ - rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", - character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - - /* Run Bind Convert */ - rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", - character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - - /* Run Language Convert */ - first_entry = 0; - for (i = 0; i < MAX_PP_LANGUAGE; i++){ - if (pp->languages[i] > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Skill Convert */ - first_entry = 0; - for (i = 0; i < MAX_PP_SKILL; i++){ - if (pp->skills[i] > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Spell Convert */ - first_entry = 0; - for (i = 0; i < MAX_PP_SPELLBOOK; i++){ - if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]); - } - } - // std::cout << rquery << "\n"; - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Max Memmed Spell Convert */ - first_entry = 0; - for (i = 0; i < MAX_PP_MEMSPELL; i++){ - if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Discipline Convert */ - first_entry = 0; - for (i = 0; i < MAX_PP_DISCIPLINES; i++){ - if (pp->disciplines.values[i] > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Material Color Convert */ - first_entry = 0; - for (i = 0; i < _MaterialCount; i++){ - if (pp->item_tint[i].color > 0){ - if (first_entry != 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); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%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); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Tribute Convert */ - first_entry = 0; - for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ - if (pp->tributes[i].tribute > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Bandolier Convert */ - first_entry = 0; - for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ - for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ - if (pp->bandoliers[i].items[si].item_id > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); - } - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - /* Run Potion Belt Convert */ - first_entry = 0; - for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ - if (pp->potionbelt.items[i].item_id > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); - - } - } - results = QueryDatabase(rquery); if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - } - - /* Print out the entire Player Profile for testing */ - if (printppdebug == 1) { - printf("ID: %i \n", atoi(row[0])); - printf("checksum: %i \n", pp->checksum); - printf("name: %s \n", pp->name); - printf("last_name: %s \n", pp->last_name); - printf("gender: %i \n", pp->gender); - printf("race: %i \n", pp->race); - printf("class_: %i \n", pp->class_); - printf("unknown0112: %i \n", pp->unknown0112); - printf("level: %i \n", pp->level); - - printf("\n=== BIND DATA (Array Size 5) ===\n"); - for (i = 0; i < 5; i++){ - printf("Bind Num: %i ZoneID: %u x: %f y: %f z: %f heading: %f \n", i, pp->binds[i].zoneId, pp->binds[i].x, pp->binds[i].y, pp->binds[i].z, pp->binds[i].heading); - } - printf("\n"); - - printf("deity: %u \n", pp->deity); - printf("guild_id: %u \n", pp->guild_id); - printf("birthday: %u \n", pp->birthday); - printf("lastlogin: %u \n", pp->lastlogin); - printf("timePlayedMin: %u \n", pp->timePlayedMin); - printf("pvp: %u \n", pp->pvp); - printf("level2: %u \n", pp->level2); - printf("anon: %u \n", pp->anon); - printf("gm: %u \n", pp->gm); - printf("guildrank: %u \n", pp->guildrank); - printf("guildbanker: %u \n", pp->guildbanker); - printf("unknown0246[6]: %u \n", pp->unknown0246[6]); - printf("intoxication: %u \n", pp->intoxication); - - printf("\n=== Spell Slot Refresh spellSlotRefresh[MAX_PP_MEMSPELL] ===\n"); - for (i = 0; i < MAX_PP_MEMSPELL; i++){ - printf("Slot: %i Value: %u \n", i, pp->spellSlotRefresh[i]); - } - printf("\n\n"); - - printf("abilitySlotRefresh: %u \n", pp->abilitySlotRefresh); - printf("haircolor: %u \n", pp->haircolor); - printf("beardcolor: %u \n", pp->beardcolor); - printf("eyecolor1: %u \n", pp->eyecolor1); - printf("eyecolor2: %u \n", pp->eyecolor2); - printf("hairstyle: %u \n", pp->hairstyle); - printf("beard: %u \n", pp->beard); - printf("ability_time_seconds: %u \n", pp->ability_time_seconds); - printf("ability_number: %u \n", pp->ability_number); - printf("ability_time_minutes: %u \n", pp->ability_time_minutes); - printf("ability_time_hours: %u \n", pp->ability_time_hours); - - printf("\n=== Color Material Data ===\n"); - for (i = 0; i < 10; i++){ - printf("Slot: %i Blue: %u Green: %u Red: %i Use_Tint: %u Color: %u \n", 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); - } - printf("\n\n"); - - printf("\n=== AA Data ===\n"); - for (i = 0; i < MAX_PP_AA_ARRAY; i++){ - printf("ID: %u Value %u\n", pp->aa_array[i].AA, pp->aa_array[i].value); - } - printf("\n\n"); - - printf("%i unknown2384\n", pp->unknown2384); - printf("servername: %s \n", pp->servername); - printf("title: %s \n", pp->title); - printf("suffix: %s \n", pp->suffix); - printf("guildid2: %u \n", pp->guildid2); - printf("exp: %u \n", pp->exp); - printf("unknown2492: %u \n", pp->unknown2492); - printf("points: %u \n", pp->points); - printf("mana: %u \n", pp->mana); - printf("cur_hp: %u \n", pp->cur_hp); - printf("unknown2508: %u \n", pp->unknown2508); - printf("STR: %u \n", pp->STR); - printf("STA: %u \n", pp->STA); - printf("CHA: %u \n", pp->CHA); - printf("DEX: %u \n", pp->DEX); - printf("INT: %u \n", pp->INT); - printf("AGI: %u \n", pp->AGI); - printf("WIS: %u \n", pp->WIS); - printf("face: %u \n", pp->face); - printf("unknown2541[47]: %u \n", pp->unknown2541[47]); - printf("languages[MAX_PP_LANGUAGE]: %u \n", pp->languages[MAX_PP_LANGUAGE]); - - printf("\n=== languages[MAX_PP_LANGUAGE] ===\n"); - for (i = 0; i < MAX_PP_LANGUAGE; i++){ - printf("ID: %u Value: %u \n", i, pp->languages[i]); - } - printf("\n\n"); - - printf("unknown2616[4]: %u \n", pp->unknown2616[4]); - - printf("\n=== Spell Book ===\n"); - for (i = 0; i < MAX_PP_SPELLBOOK; i++){ - printf("Spell Book Slot: %i Spell: %u \n", i, pp->spell_book[i]); - } - printf("\n\n"); - - printf("unknown4540[128]: %u \n", pp->unknown4540[128]); - - printf("\n=== mem_spells[MAX_PP_MEMSPELL] ===\n"); - for (i = 0; i < MAX_PP_MEMSPELL; i++){ - printf("ID: %u Value: %u \n", i, pp->mem_spells[i]); - } - printf("\n\n"); - - printf("unknown4704[32]: %u \n", pp->unknown4704[32]); - printf("y: %4.2f \n", pp->y); - printf("x: %4.2f \n", pp->x); - printf("z: %4.2f \n", pp->z); - printf("heading: %4.2f \n", pp->heading); - printf("unknown4752[4]: %u \n", pp->unknown4752[4]); - - printf("platinum: %u \n", pp->platinum); - printf("gold: %u \n", pp->gold); - printf("silver: %u \n", pp->silver); - printf("copper: %u \n", pp->copper); - printf("platinum_bank: %u \n", pp->platinum_bank); - printf("gold_bank: %u \n", pp->gold_bank); - printf("silver_bank: %u \n", pp->silver_bank); - printf("copper_bank: %u \n", pp->copper_bank); - printf("platinum_cursor: %u \n", pp->platinum_cursor); - printf("gold_cursor: %u \n", pp->gold_cursor); - printf("silver_cursor: %u \n", pp->silver_cursor); - printf("copper_cursor: %u \n", pp->copper_cursor); - printf("platinum_shared: %u \n", pp->platinum_shared); - printf("unknown4808[24]: %u \n", pp->unknown4808[24]); - - - - printf("\n=== skills[MAX_PP_SKILL] ===\n"); - for (i = 0; i < MAX_PP_SKILL; i++){ - printf("ID: %u Value: %u \n", i, pp->skills[i]); - } - printf("\n\n"); - - printf("unknown5132[184]: %u \n", pp->unknown5132[184]); - printf("pvp2: %u \n", pp->pvp2); - printf("unknown5420: %u \n", pp->unknown5420); - printf("pvptype: %u \n", pp->pvptype); - printf("unknown5428: %u \n", pp->unknown5428); - printf("ability_down: %u \n", pp->ability_down); - printf("unknown5436[8]: %u \n", pp->unknown5436[8]); - printf("autosplit: %u \n", pp->autosplit); - printf("unknown5448[8]: %u \n", pp->unknown5448[8]); - printf("zone_change_count: %u \n", pp->zone_change_count); - printf("unknown5460[16]: %u \n", pp->unknown5460[16]); - printf("drakkin_heritage: %u \n", pp->drakkin_heritage); - printf("drakkin_tattoo: %u \n", pp->drakkin_tattoo); - printf("drakkin_details: %u \n", pp->drakkin_details); - printf("expansions: %u \n", pp->expansions); - printf("toxicity: %u \n", pp->toxicity); - printf("unknown5496: %s \n", pp->unknown5496); - printf("hunger_level: %i \n", pp->hunger_level); - printf("thirst_level: %i \n", pp->thirst_level); - printf("ability_up: %u \n", pp->ability_up); - printf("unknown5524: %s \n", pp->unknown5524); - printf("zone_id: %u \n", pp->zone_id); - printf("zoneInstance: %u \n", pp->zoneInstance); - - // SpellBuff_Struct buffs[BUFF_COUNT]; - - printf("groupMembers: %s \n", pp->groupMembers); - printf("unknown6428: %s \n", pp->unknown6428); - printf("entityid: %u \n", pp->entityid); - printf("leadAAActive: %u \n", pp->leadAAActive); - printf("unknown7092: %u \n", pp->unknown7092); - printf("ldon_points_guk: %i \n", pp->ldon_points_guk); - printf("ldon_points_mir: %i \n", pp->ldon_points_mir); - printf("ldon_points_mmc: %i \n", pp->ldon_points_mmc); - printf("ldon_points_ruj: %i \n", pp->ldon_points_ruj); - printf("ldon_points_tak: %i \n", pp->ldon_points_tak); - printf("ldon_points_available: %i \n", pp->ldon_points_available); - printf("ldon_wins_guk: %i \n", pp->ldon_wins_guk); - printf("ldon_wins_mir: %i \n", pp->ldon_wins_mir); - printf("ldon_wins_mmc: %i \n", pp->ldon_wins_mmc); - printf("ldon_wins_ruj: %i \n", pp->ldon_wins_ruj); - printf("ldon_wins_tak: %i \n", pp->ldon_wins_tak); - printf("ldon_losses_guk: %i \n", pp->ldon_losses_guk); - printf("ldon_losses_mir: %i \n", pp->ldon_losses_mir); - printf("ldon_losses_mmc: %i \n", pp->ldon_losses_mmc); - printf("ldon_losses_ruj: %i \n", pp->ldon_losses_ruj); - printf("ldon_losses_tak: %i \n", pp->ldon_losses_tak); - printf("unknown7160[72]: %u \n", pp->unknown7160[72]); - printf("tribute_time_remaining: %u \n", pp->tribute_time_remaining); - printf("showhelm: %u \n", pp->showhelm); - printf("career_tribute_points: %u \n", pp->career_tribute_points); - printf("unknown7244: %u \n", pp->unknown7244); - printf("tribute_points: %u \n", pp->tribute_points); - printf("unknown7252: %u \n", pp->unknown7252); - printf("tribute_active: %u \n", pp->tribute_active); - - printf("\n=== Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE] ===\n"); - for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ - printf("ID: %u Tribute: %u Tier: %u \n", i, pp->tributes[i].tribute, pp->tributes[i].tier); - } - printf("\n\n"); - - // Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE]; - // /*7264*/ Disciplines_Struct disciplines; - - printf("\n=== Disciplines_Struct disciplines ===\n"); - for (i = 0; i < MAX_PP_DISCIPLINES; i++){ - printf("ID: %u Disc Value: %u \n", i, pp->disciplines.values[i]); - } - printf("\n\n"); - - printf("\n=== recastTimers[MAX_RECAST_TYPES] ===\n"); - for (i = 0; i < MAX_RECAST_TYPES; i++){ - printf("ID: %u Value: %u \n", i, pp->recastTimers[i]); - } - printf("\n\n"); - - printf("unknown7780: %s \n", pp->unknown7780); - printf("endurance: %u \n", pp->endurance); - printf("group_leadership_exp: %u \n", pp->group_leadership_exp); - printf("raid_leadership_exp: %u \n", pp->raid_leadership_exp); - printf("group_leadership_points: %u \n", pp->group_leadership_points); - printf("raid_leadership_points: %u \n", pp->raid_leadership_points); - - // LeadershipAA_Struct leader_abilities; - - printf("\n=== LeadershipAA_Struct leader_abilities ===\n"); - for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ - printf("ID: %u Rank: %u \n", i, pp->leader_abilities.ranks[i]); - } - printf("\n\n"); - - printf("unknown8088[132]: %u \n", pp->unknown8088[132]); - printf("air_remaining: %u \n", pp->air_remaining); - printf("PVPKills: %u \n", pp->PVPKills); - printf("PVPDeaths: %u \n", pp->PVPDeaths); - printf("PVPCurrentPoints: %u \n", pp->PVPCurrentPoints); - printf("PVPCareerPoints: %u \n", pp->PVPCareerPoints); - printf("PVPBestKillStreak: %u \n", pp->PVPBestKillStreak); - printf("PVPWorstDeathStreak: %u \n", pp->PVPWorstDeathStreak); - printf("PVPCurrentKillStreak: %u \n", pp->PVPCurrentKillStreak); - - // PVPStatsEntry_Struct PVPLastKill; - - printf("\n=== PVPStatsEntry_Struct PVPLastKill ===\n"); - printf("Char Name: %s Level: %u Race: %u Class: %u Zone: %u Time: %u Points: %u \n", pp->PVPLastKill.Name, pp->PVPLastKill.Level, pp->PVPLastKill.Race, pp->PVPLastKill.Class, pp->PVPLastKill.Zone, pp->PVPLastKill.Time, pp->PVPLastKill.Points); - printf("\n\n"); - - // /*8304*/ PVPStatsEntry_Struct PVPLastDeath; - - printf("\n=== PVPStatsEntry_Struct PVPLastDeath ===\n"); - printf("Char Name: %s Level: %u Race: %u Class: %u Zone: %u Time: %u Points: %u \n", pp->PVPLastDeath.Name, pp->PVPLastDeath.Level, pp->PVPLastDeath.Race, pp->PVPLastDeath.Class, pp->PVPLastDeath.Zone, pp->PVPLastDeath.Time, pp->PVPLastDeath.Points); - printf("\n\n"); - - printf("PVPNumberOfKillsInLast24Hours: %u \n", pp->PVPNumberOfKillsInLast24Hours); - - // PVPStatsEntry_Struct PVPRecentKills[50]; - - printf("\n===PVPStatsEntry_Struct PVPRecentKills[50] ===\n"); - for (i = 0; i < 50; i++){ - printf("ID: %u Char Name: %s Level: %u Race: %u Class: %u Zone: %u Time: %u Points: %u \n", i, pp->PVPRecentKills[i].Name, pp->PVPRecentKills[i].Level, pp->PVPRecentKills[i].Race, pp->PVPRecentKills[i].Class, pp->PVPRecentKills[i].Zone, pp->PVPRecentKills[i].Time, pp->PVPRecentKills[i].Points); - } - printf("\n\n"); - - printf("aapoints_spent: %u \n", pp->aapoints_spent); - printf("expAA: %u \n", pp->expAA); - printf("aapoints: %u \n", pp->aapoints); - printf("unknown12844[36]: %u \n", pp->unknown12844[36]); - - // Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT]; - - printf("\n=== Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT] ===\n"); - uint16 si = 0; - for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ - // BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE]; - for (si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ - printf("ID: %u item_id: %u icon: %u items name: %s name: %s\n", i, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].items[si].item_name, pp->bandoliers[i].name); - } - } - printf("\n\n"); - - printf("unknown14160[4506]: %u \n", pp->unknown14160[4506]); - - // SuspendedMinion_Struct SuspendedMinion; // No longer in use (In DB) - - // printf("\n=== SuspendedMinion_Struct SuspendedMinion ===\n"); - // printf("SpellID: %u HP: %u Mana: %u \n", i, pp->leader_abilities.ranks[i]); - - // printf("\n\n"); - - printf("timeentitledonaccount: %u \n", pp->timeentitledonaccount); - - // PotionBelt_Struct potionbelt; //there should be 3 more of these - - printf("\n=== PotionBelt_Struct potionbelt ===\n"); - for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ - printf("ID: %u Icon: %u Item ID: %u Item Name: %s\n", i, pp->potionbelt.items[i].icon, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].item_name); - } - printf("\n\n"); - - printf("unknown19568[8]: %u \n", pp->unknown19568[8]); - printf("currentRadCrystals: %u \n", pp->currentRadCrystals); - printf("careerRadCrystals: %u \n", pp->careerRadCrystals); - printf("currentEbonCrystals: %u \n", pp->currentEbonCrystals); - printf("careerEbonCrystals: %u \n", pp->careerEbonCrystals); - printf("groupAutoconsent: %u \n", pp->groupAutoconsent); - printf("raidAutoconsent: %u \n", pp->raidAutoconsent); - printf("guildAutoconsent: %u \n", pp->guildAutoconsent); - printf("unknown19595[5]: %u \n", pp->unknown19595[5]); - printf("RestTimer: %u \n", pp->RestTimer); - - - printf("\n"); - } - - mysql_free_result(result2); - } + /* Verify PP Integrity */ + lengths = results2.LengthOfColumn(1); + if (lengths == sizeof(PlayerProfile_Struct)) { /* If PP is the size it is expected to be */ + memcpy(pp, row2[1], sizeof(PlayerProfile_Struct)); + // std::cout << "SIZE OK\n" << std::endl; + } + /* Continue of PP Size does not match (Usually a created character never logged in) */ + else { continue; } + + lengths_e = results2.LengthOfColumn(11); + if (lengths_e == sizeof(ExtendedProfile_Struct)) { + memcpy(e_pp, row2[11], sizeof(ExtendedProfile_Struct)); + } + if (e_pp->expended_aa > 4000000){ e_pp->expended_aa = 0; } + + // std::cout << "Expended AA: " << e_pp->expended_aa << "\n" << std::endl; + + /* Loading Status on conversion */ + if (runconvert == 1){ + std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; + loadbar(char_iter_count, number_of_characters, 50); + + /* Run inspect message convert */ + if (inspectmessage != ""){ + std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" + "VALUES (%u, '%s')", + character_id, + EscapeString(inspectmessage).c_str() + ); + auto results = QueryDatabase(rquery); + if (!results.RowsAffected()){ std::cout << "ERROR Inspect Messages Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + } + + /* Run Currency Convert */ + std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," + "platinum_bank, gold_bank, silver_bank, copper_bank," + "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " + "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" + "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", + character_id, + pp->platinum, + pp->gold, + pp->silver, + pp->copper, + pp->platinum_bank, + pp->gold_bank, + pp->silver_bank, + pp->copper_bank, + pp->platinum_cursor, + pp->gold_cursor, + pp->silver_cursor, + pp->copper_cursor, + pp->currentRadCrystals, + pp->careerRadCrystals, + pp->currentEbonCrystals, + pp->careerEbonCrystals + ); + auto results = QueryDatabase(rquery); + + if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } + + /* Run Character Data Convert */ + rquery = StringFormat( + "REPLACE INTO `character_data` (" + "id," + "account_id," + "`name`," + "last_name," + "gender," + "race," + "class," + "`level`," + "deity," + "birthday," + "last_login," + "time_played," + "pvp_status," + "level2," + "anon," + "gm," + "intoxication," + "hair_color," + "beard_color," + "eye_color_1," + "eye_color_2," + "hair_style," + "beard," + "ability_time_seconds," + "ability_number," + "ability_time_minutes," + "ability_time_hours," + "title," + "suffix," + "exp," + "points," + "mana," + "cur_hp," + "str," + "sta," + "cha," + "dex," + "`int`," + "agi," + "wis," + "face," + "y," + "x," + "z," + "heading," + "pvp2," + "pvp_type," + "autosplit_enabled," + "zone_change_count," + "drakkin_heritage," + "drakkin_tattoo," + "drakkin_details," + "toxicity," + "hunger_level," + "thirst_level," + "ability_up," + "zone_id," + "zone_instance," + "leadership_exp_on," + "ldon_points_guk," + "ldon_points_mir," + "ldon_points_mmc," + "ldon_points_ruj," + "ldon_points_tak," + "ldon_points_available," + "tribute_time_remaining," + "show_helm," + "career_tribute_points," + "tribute_points," + "tribute_active," + "endurance," + "group_leadership_exp," + "raid_leadership_exp," + "group_leadership_points," + "raid_leadership_points," + "air_remaining," + "pvp_kills," + "pvp_deaths," + "pvp_current_points," + "pvp_career_points," + "pvp_best_kill_streak," + "pvp_worst_death_streak," + "pvp_current_kill_streak," + "aa_points_spent," + "aa_exp," + "aa_points," + "group_auto_consent," + "raid_auto_consent," + "guild_auto_consent," + "RestTimer," + "firstlogon," + "lfg," + "lfp," + "mailkey," + "xtargets," + "e_aa_effects," + "e_percent_to_aa," + "e_expended_aa_spent" + ")" + "VALUES (" + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%i," // toxicity + "%u," // hunger_level + "%u," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_points + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_streak + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent + "%u," // RestTimer + "%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt + "%u," // Looking for Group + "%u," // Looking for P? + "'%s'," // Mailkey + "%u," // X Targets + "%u," // AA Effects + "%u," // Percent to AA + "%u" // e_expended_aa_spent + ")", + character_id, + account_id, + EscapeString(pp->name).c_str(), + EscapeString(pp->last_name).c_str(), + pp->gender, + pp->race, + pp->class_, + pp->level, + pp->deity, + pp->birthday, + pp->lastlogin, + pp->timePlayedMin, + pp->pvp, + pp->level2, + pp->anon, + pp->gm, + pp->intoxication, + pp->haircolor, + pp->beardcolor, + pp->eyecolor1, + pp->eyecolor2, + pp->hairstyle, + pp->beard, + pp->ability_time_seconds, + pp->ability_number, + pp->ability_time_minutes, + pp->ability_time_hours, + EscapeString(pp->title).c_str(), + EscapeString(pp->suffix).c_str(), + pp->exp, + pp->points, + pp->mana, + pp->cur_hp, + pp->STR, + pp->STA, + pp->CHA, + pp->DEX, + pp->INT, + pp->AGI, + pp->WIS, + pp->face, + pp->y, + pp->x, + pp->z, + pp->heading, + pp->pvp2, + pp->pvptype, + pp->autosplit, + pp->zone_change_count, + pp->drakkin_heritage, + pp->drakkin_tattoo, + pp->drakkin_details, + pp->toxicity, + pp->hunger_level, + pp->thirst_level, + pp->ability_up, + pp->zone_id, + pp->zoneInstance, + pp->leadAAActive, + pp->ldon_points_guk, + pp->ldon_points_mir, + pp->ldon_points_mmc, + pp->ldon_points_ruj, + pp->ldon_points_tak, + pp->ldon_points_available, + pp->tribute_time_remaining, + pp->showhelm, + pp->career_tribute_points, + pp->tribute_points, + pp->tribute_active, + pp->endurance, + pp->group_leadership_exp, + pp->raid_leadership_exp, + pp->group_leadership_points, + pp->raid_leadership_points, + pp->air_remaining, + pp->PVPKills, + pp->PVPDeaths, + pp->PVPCurrentPoints, + pp->PVPCareerPoints, + pp->PVPBestKillStreak, + pp->PVPWorstDeathStreak, + pp->PVPCurrentKillStreak, + pp->aapoints_spent, + pp->expAA, + pp->aapoints, + pp->groupAutoconsent, + pp->raidAutoconsent, + pp->guildAutoconsent, + pp->RestTimer, + firstlogon, + lfg, + lfp, + mailkey.c_str(), + xtargets, + e_pp->aa_effects, + e_pp->perAA, + e_pp->expended_aa + ); + results = QueryDatabase(rquery); + if (!results.RowsAffected()){ std::cout << "ERROR PP Data Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + + /* + We set a first entry variable because we need the first initial piece of the query to be declared + This is to speed up the INSERTS and trim down the amount of individual sends during the process. + The speed difference is dramatic + */ + /* Run AA Convert */ + int first_entry = 0; rquery = ""; + for (i = 1; i < MAX_PP_AA_ARRAY; i++){ + if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + + /* Run Bind Home Convert */ + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + + /* Run Bind Convert */ + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + + /* Run Language Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + if (pp->languages[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Skill Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_SKILL; i++){ + if (pp->skills[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Spell Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ + if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]); + } + } + // std::cout << rquery << "\n"; + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Max Memmed Spell Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ + if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Discipline Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_DISCIPLINES; i++){ + if (pp->disciplines.values[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Material Color Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < _MaterialCount; i++){ + if (pp->item_tint[i].color > 0){ + if (first_entry != 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); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%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); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Tribute Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Bandolier Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + if (pp->bandoliers[i].items[si].item_id > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + } + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Potion Belt Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ + if (pp->potionbelt.items[i].item_id > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + /* Run Leadership AA Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ + if (pp->leader_abilities.ranks[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Leadership AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } } - mysql_free_result(result); } if (runconvert == 1){ printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); } diff --git a/common/extprofile.h b/common/extprofile.h index 2e29fbf4a..a8447d4fc 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -21,7 +21,6 @@ #include "eq_packet_structs.h" #include "item.h" - #pragma pack(1) /* @@ -37,24 +36,24 @@ */ struct ExtendedProfile_Struct { // Pet stuff - uint16 pet_id; - uint16 old_pet_hp; - uint16 old_pet_mana; - SpellBuff_Struct pet_buffs[BUFF_COUNT]; - uint32 pet_items[_MaterialCount]; - char merc_name[64]; + uint16 pet_id; /* Not Used */ + uint16 old_pet_hp; /* Not Used */ + uint16 old_pet_mana; /* Not Used */ + SpellBuff_Struct pet_buffs[BUFF_COUNT]; /* Not Used */ + uint32 pet_items[_MaterialCount]; /* Not Used */ + char merc_name[64]; /* Used */ - uint32 aa_effects; - uint32 perAA; //% of exp going to AAs - uint32 expended_aa; // Total of expended AA - uint32 pet_hp; - uint32 pet_mana; - uint32 mercTemplateID; - uint32 mercSuspendedTime; - bool mercIsSuspended; - uint32 mercTimerRemaining; - uint8 mercGender; - int32 mercState; + uint32 aa_effects; /* Used */ + uint32 perAA; /* Used: % of exp going to AAs */ + uint32 expended_aa; /* Used: Total of expended AA */ + uint32 pet_hp; /* Not Used */ + uint32 pet_mana; /* Not Used */ + uint32 mercTemplateID; /* Not Used */ + uint32 mercSuspendedTime; /* Not Used */ + bool mercIsSuspended; /* Not Used */ + uint32 mercTimerRemaining; /* Not Used */ + uint8 mercGender; /* Not Used */ + int32 mercState; /* Not Used */ }; #pragma pack() diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f6f960cc3..37bfe299c 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -114,31 +114,12 @@ bool SharedDatabase::SetGMSpeed(uint32 account_id, uint8 gmspeed) } uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { - uint32 EntitledTime = 0; - - const char *EntitledQuery = "select sum(ascii(substring(profile, 237, 1)) + (ascii(substring(profile, 238, 1)) * 256) +" - "(ascii(substring(profile, 239, 1)) * 65536) + (ascii(substring(profile, 240, 1)) * 16777216))" - "from character_ where account_id = %i"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, EntitledQuery, AccountID), errbuf, &result)) { - - if (mysql_num_rows(result) == 1) { - - row = mysql_fetch_row(result); - - EntitledTime = atoi(row[0]); - } - - mysql_free_result(result); + std::string query = StringFormat("SELECT `time_played` FROM `character_data` WHERE `account_id` = %u", AccountID); + auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + EntitledTime += atoi(row[0]); } - - safe_delete_array(query); - return EntitledTime; } @@ -2003,38 +1984,19 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { return nullptr; } -void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - std::cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); +void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) { + std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id); + auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "SharedDatabase::LoadCharacterInspectMessage", query); + auto row = results.begin(); + memcpy(message, "", sizeof(InspectMessage_Struct)); + for (auto row = results.begin(); row != results.end(); ++row) { + memcpy(message, row[0], sizeof(InspectMessage_Struct)); } } -void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) { - std::cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; - } - - safe_delete_array(query); +void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) { + std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, EscapeString(message->text).c_str()); + auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "SharedDatabase::SaveCharacterInspectMessage", query); } void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { diff --git a/common/shareddb.h b/common/shareddb.h index 5401bfa0a..eeef6125a 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -42,8 +42,8 @@ public: bool SetHideMe(uint32 account_id, uint8 hideme); int32 DeleteStalePlayerCorpses(); int32 DeleteStalePlayerBackups(); - void GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message); - void SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message); + void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message); + void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message); void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message); void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message); bool GetCommandSettings(std::map &commands); diff --git a/zone/aa.cpp b/zone/aa.cpp index f546e59f0..ef4b07aee 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -18,6 +18,8 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) // Test 1 +#include + #include "../common/debug.h" #include "aa.h" #include "mob.h" @@ -316,13 +318,14 @@ void Client::ActivateAA(aaID activate){ } } // Check if AA is expendable - if (aas_send[activate - activate_val]->special_category == 7) - { + if (aas_send[activate - activate_val]->special_category == 7) { + // Add the AA cost to the extended profile to track overall total m_epp.expended_aa += aas_send[activate]->cost; + SetAA(activate, 0); - Save(); + SaveAA(); /* Save Character AA */ SendAA(activate); SendAATable(); } @@ -1047,7 +1050,7 @@ void Client::BuyAA(AA_Action* action) mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level + 1); m_pp.aapoints -= real_cost; - + /* Do Player Profile rank calculations and set player profile */ SaveAA(); /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ @@ -1533,6 +1536,8 @@ void Client::ResetAA(){ m_pp.raid_leadership_points = 0; m_pp.group_leadership_exp = 0; m_pp.raid_leadership_exp = 0; + + database.DeleteCharacterLeadershipAAs(this->CharacterID()); } int Client::GroupLeadershipAAHealthEnhancement() diff --git a/zone/client.cpp b/zone/client.cpp index 2a85bfab7..7c4bf39c0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -503,7 +503,7 @@ bool Client::SaveAA(){ } } } - m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; + m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { if (aa[a]->AA > 0 && aa[a]->value){ if (first_entry != 1){ @@ -582,7 +582,7 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterTribute(this->CharacterID(), &m_pp); SaveTaskState(); /* Save Character Task */ - database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp); /* Save Character Data */ + database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */ LogFile->write(EQEMuLog::Status, "Client::Save %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; @@ -4233,7 +4233,6 @@ void Client::VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber) { } void Client::ClearGroupAAs() { - for(unsigned int i = 0; i < MAX_GROUP_LEADERSHIP_AA_ARRAY; i++) m_pp.leader_abilities.ranks[i] = 0; @@ -4243,28 +4242,18 @@ void Client::ClearGroupAAs() { m_pp.raid_leadership_exp = 0; Save(); + database.SaveCharacterLeadershipAA(this->CharacterID(), &m_pp); } void Client::UpdateGroupAAs(int32 points, uint32 type) { - - switch(type) - { - case 0: - { - m_pp.group_leadership_points += points; - break; - } - case 1: - { - m_pp.raid_leadership_points += points; - break; - } + switch(type) { + case 0: { m_pp.group_leadership_points += points; break; } + case 1: { m_pp.raid_leadership_points += points; break; } } SendLeadershipEXPUpdate(); } -bool Client::IsLeadershipEXPOn() -{ +bool Client::IsLeadershipEXPOn() { if(!m_pp.leadAAActive) return false; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3b34878d5..2a0ade9db 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -494,8 +494,7 @@ int Client::HandlePacket(const EQApplicationPacket *app) return(true); } -void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) -{ +void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { if(app->size != sizeof(ClientZoneEntry_Struct)) return; ClientZoneEntry_Struct *cze = (ClientZoneEntry_Struct *) app->pBuffer; @@ -543,7 +542,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) std::string query; unsigned long* lengths; - /* Set item materials */ + /* Set item material tint */ for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) if (m_pp.item_tint[i].rgb.use_tint == 1) m_pp.item_tint[i].rgb.use_tint = 0xFF; @@ -569,24 +568,24 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (account_creation){ account_creation = atoul(row[6]); } } - /* Load Character Legacy Data: Temp until I move */ - query = StringFormat("SELECT id,profile,zonename,x,y,z,guild_id,rank,extprofile,class,level,lfp,lfg,instanceid,xtargets,firstlogon FROM character_ LEFT JOIN guild_members ON id=char_id WHERE id=%i", cid); + /* Load Character Data */ + query = StringFormat("SELECT `lfp`, `lfg`, `xtargets`, `firstlogon`, `guild_id`, `rank` FROM `character_data` LEFT JOIN `guild_members` ON `id` = `char_id` WHERE `id` = %i", cid); results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { m_pp.lastlogin = time(nullptr); - if (row[6]){ - guild_id = atoi(row[6]); + if (row[4]){ + guild_id = atoi(row[4]); if (guildrank) { - if (row[7] != nullptr){ guildrank = atoi(row[7]); } + if (row[5] != nullptr){ guildrank = atoi(row[5]); } else{ guildrank = GUILD_RANK_NONE; } } } if (RuleB(Character, SharedBankPlat)) m_pp.platinum_shared = database.GetSharedPlatinum(database.GetAccountIDByChar(cid)); - if (LFP){ LFP = atoi(row[11]); } - if (LFG){ LFG = atoi(row[12]); } - if (firstlogon){ firstlogon = atoi(row[15]); } + if (LFP){ LFP = atoi(row[0]); } + if (LFG){ LFG = atoi(row[1]); } + if (firstlogon){ firstlogon = atoi(row[3]); } } loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ @@ -595,13 +594,14 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */ database.LoadCharacterPotions(cid, &m_pp); /* Load Character Potion Belt */ database.LoadCharacterCurrency(cid, &m_pp); /* Load Character Currency into PP */ - database.LoadCharacterData(cid, &m_pp); /* Load Character Data from DB into PP */ + database.LoadCharacterData(cid, &m_pp, &m_epp); /* Load Character Data from DB into PP as well as E_PP */ database.LoadCharacterSkills(cid, &m_pp); /* Load Character Skills */ - database.GetPlayerInspectMessage(m_pp.name, &m_inspect_message); /* Move to another method when can, this is pointless... */ + database.LoadCharacterInspectMessage(cid, &m_inspect_message); /* Load Character Inspect Message */ database.LoadCharacterSpellBook(cid, &m_pp); /* Load Character Spell Book */ database.LoadCharacterMemmedSpells(cid, &m_pp); /* Load Character Memorized Spells */ database.LoadCharacterDisciplines(cid, &m_pp); /* Load Character Disciplines */ database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ + database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ if (level){ level = m_pp.level; } @@ -619,7 +619,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.intoxication = 0; strcpy(name, m_pp.name); strcpy(lastname, m_pp.last_name); - /* If PP is set to wierd coordinates */ + /* If PP is set to weird coordinates */ if ((m_pp.x == -1 && m_pp.y == -1 && m_pp.z == -1) || (m_pp.x == -2 && m_pp.y == -2 && m_pp.z == -2)) { m_pp.x = zone->safe_x(); m_pp.y = zone->safe_y(); @@ -900,8 +900,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (zone->IsPVPZone()) m_pp.pvp = 1; /* Time entitled on Account: Move to account */ - m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; - + m_pp.timeentitledonaccount = database.GetTotalTimeEntitledOnAccount(AccountID()) / 1440; /* Reset rest timer if the durations have been lowered in the database */ if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) m_pp.RestTimer = 0; @@ -926,8 +925,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) in hopes that it adds more consistency... Remake pet */ - if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) - { + if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); if (GetPet() && GetPet()->IsNPC()) { NPC *pet = GetPet()->CastToNPC(); @@ -1022,8 +1020,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) QueuePacket(outapp); safe_delete(outapp); - SetAttackTimer(); - + SetAttackTimer(); conn_state = ZoneInfoSent; return; @@ -7312,7 +7309,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) { InspectMessage_Struct* newmessage = (InspectMessage_Struct*) insr->text; InspectMessage_Struct& playermessage = this->GetInspectMessage(); memcpy(&playermessage, newmessage, sizeof(InspectMessage_Struct)); - database.SetPlayerInspectMessage(name, &playermessage); + database.SaveCharacterInspectMessage(this->CharacterID(), &playermessage); if(tmp != 0 && tmp->IsClient()) { tmp->CastToClient()->QueuePacket(outapp); } // Send answer to requester @@ -7329,7 +7326,7 @@ void Client::Handle_OP_InspectMessageUpdate(const EQApplicationPacket *app) { InspectMessage_Struct* newmessage = (InspectMessage_Struct*) app->pBuffer; InspectMessage_Struct& playermessage = this->GetInspectMessage(); memcpy(&playermessage, newmessage, sizeof(InspectMessage_Struct)); - database.SetPlayerInspectMessage(name, &playermessage); + database.SaveCharacterInspectMessage(this->CharacterID(), &playermessage); } #if 0 // I dont think there's an op for this now, and we check this @@ -9559,6 +9556,8 @@ void Client::Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app) { //sell them the ability. m_pp.group_leadership_points -= cost; m_pp.leader_abilities.ranks[aaid]++; + + database.SaveCharacterLeadershipAA(this->CharacterID(), &m_pp); } //success, send them an update diff --git a/zone/zone.cpp b/zone/zone.cpp index 9ae17381d..dc8d8600c 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -103,7 +103,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { } zone->zonemap = Map::LoadMapFile(zone->map_name); zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name); - zone->pathing = PathManager::LoadPathFile(zone->map_name); + zone->pathing = PathManager::LoadPathFile(zone->map_name); char tmp[10]; if (database.GetVariable("loglevel",tmp, 9)) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ebf3957b6..ef14a3657 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -821,7 +821,7 @@ void ZoneDatabase::UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity) #define StructDist(in, f1, f2) (uint32(&in->f2)-uint32(&in->f1)) -bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp){ +bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){ std::string query = StringFormat( "SELECT " "`name`, " @@ -911,100 +911,106 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* "group_auto_consent, " "raid_auto_consent, " "guild_auto_consent, " - "RestTimer " + "RestTimer, " + "`e_aa_effects`, " + "`e_percent_to_aa`, " + "`e_expended_aa_spent` " "FROM " "character_data " "WHERE `id` = %i ", character_id); auto results = database.QueryDatabase(query); int r = 0; for (auto row = results.begin(); row != results.end(); ++row) { - strcpy(pp->name, row[r]); r++; - strcpy(pp->last_name, row[r]); r++; - pp->gender = atoi(row[r]); r++; - pp->race = atoi(row[r]); r++; - pp->class_ = atoi(row[r]); r++; - pp->level = atoi(row[r]); r++; - pp->deity = atoi(row[r]); r++; - pp->birthday = atoi(row[r]); r++; - pp->lastlogin = atoi(row[r]); r++; - pp->timePlayedMin = atoi(row[r]); r++; - pp->pvp = atoi(row[r]); r++; - pp->level2 = atoi(row[r]); r++; - pp->anon = atoi(row[r]); r++; - pp->gm = atoi(row[r]); r++; - pp->intoxication = atoi(row[r]); r++; - pp->haircolor = atoi(row[r]); r++; - pp->beardcolor = atoi(row[r]); r++; - pp->eyecolor1 = atoi(row[r]); r++; - pp->eyecolor2 = atoi(row[r]); r++; - pp->hairstyle = atoi(row[r]); r++; - pp->beard = atoi(row[r]); r++; - pp->ability_time_seconds = atoi(row[r]); r++; - pp->ability_number = atoi(row[r]); r++; - pp->ability_time_minutes = atoi(row[r]); r++; - pp->ability_time_hours = atoi(row[r]); r++; - strcpy(pp->title, row[r]); r++; - strcpy(pp->suffix, row[r]); r++; - pp->exp = atoi(row[r]); r++; - pp->points = atoi(row[r]); r++; - pp->mana = atoi(row[r]); r++; - pp->cur_hp = atoi(row[r]); r++; - pp->STR = atoi(row[r]); r++; - pp->STA = atoi(row[r]); r++; - pp->CHA = atoi(row[r]); r++; - pp->DEX = atoi(row[r]); r++; - pp->INT = atoi(row[r]); r++; - pp->AGI = atoi(row[r]); r++; - pp->WIS = atoi(row[r]); r++; - pp->face = atoi(row[r]); r++; - pp->y = atof(row[r]); r++; - pp->x = atof(row[r]); r++; - pp->z = atof(row[r]); r++; - pp->heading = atof(row[r]); r++; - pp->pvp2 = atoi(row[r]); r++; - pp->pvptype = atoi(row[r]); r++; - pp->autosplit = atoi(row[r]); r++; - pp->zone_change_count = atoi(row[r]); r++; - pp->drakkin_heritage = atoi(row[r]); r++; - pp->drakkin_tattoo = atoi(row[r]); r++; - pp->drakkin_details = atoi(row[r]); r++; - pp->toxicity = atoi(row[r]); r++; - pp->hunger_level = atoi(row[r]); r++; - pp->thirst_level = atoi(row[r]); r++; - pp->ability_up = atoi(row[r]); r++; - pp->zone_id = atoi(row[r]); r++; - pp->zoneInstance = atoi(row[r]); r++; - pp->leadAAActive = atoi(row[r]); r++; - pp->ldon_points_guk = atoi(row[r]); r++; - pp->ldon_points_mir = atoi(row[r]); r++; - pp->ldon_points_mmc = atoi(row[r]); r++; - pp->ldon_points_ruj = atoi(row[r]); r++; - pp->ldon_points_tak = atoi(row[r]); r++; - pp->ldon_points_available = atoi(row[r]); r++; - pp->tribute_time_remaining = atoi(row[r]); r++; - pp->showhelm = atoi(row[r]); r++; - pp->career_tribute_points = atoi(row[r]); r++; - pp->tribute_points = atoi(row[r]); r++; - pp->tribute_active = atoi(row[r]); r++; - pp->endurance = atoi(row[r]); r++; - pp->group_leadership_exp = atoi(row[r]); r++; - pp->raid_leadership_exp = atoi(row[r]); r++; - pp->group_leadership_points = atoi(row[r]); r++; - pp->raid_leadership_points = atoi(row[r]); r++; - pp->air_remaining = atoi(row[r]); r++; - pp->PVPKills = atoi(row[r]); r++; - pp->PVPDeaths = atoi(row[r]); r++; - pp->PVPCurrentPoints = atoi(row[r]); r++; - pp->PVPCareerPoints = atoi(row[r]); r++; - pp->PVPBestKillStreak = atoi(row[r]); r++; - pp->PVPWorstDeathStreak = atoi(row[r]); r++; - pp->PVPCurrentKillStreak = atoi(row[r]); r++; - pp->aapoints_spent = atoi(row[r]); r++; - pp->expAA = atoi(row[r]); r++; - pp->aapoints = atoi(row[r]); r++; - pp->groupAutoconsent = atoi(row[r]); r++; - pp->raidAutoconsent = atoi(row[r]); r++; - pp->guildAutoconsent = atoi(row[r]); r++; - pp->RestTimer = atoi(row[r]); r++; + strcpy(pp->name, row[r]); r++; // "`name`, " + strcpy(pp->last_name, row[r]); r++; // "last_name, " + pp->gender = atoi(row[r]); r++; // "gender, " + pp->race = atoi(row[r]); r++; // "race, " + pp->class_ = atoi(row[r]); r++; // "class, " + pp->level = atoi(row[r]); r++; // "`level`, " + pp->deity = atoi(row[r]); r++; // "deity, " + pp->birthday = atoi(row[r]); r++; // "birthday, " + pp->lastlogin = atoi(row[r]); r++; // "last_login, " + pp->timePlayedMin = atoi(row[r]); r++; // "time_played, " + pp->pvp = atoi(row[r]); r++; // "pvp_status, " + pp->level2 = atoi(row[r]); r++; // "level2, " + pp->anon = atoi(row[r]); r++; // "anon, " + pp->gm = atoi(row[r]); r++; // "gm, " + pp->intoxication = atoi(row[r]); r++; // "intoxication, " + pp->haircolor = atoi(row[r]); r++; // "hair_color, " + pp->beardcolor = atoi(row[r]); r++; // "beard_color, " + pp->eyecolor1 = atoi(row[r]); r++; // "eye_color_1, " + pp->eyecolor2 = atoi(row[r]); r++; // "eye_color_2, " + pp->hairstyle = atoi(row[r]); r++; // "hair_style, " + pp->beard = atoi(row[r]); r++; // "beard, " + pp->ability_time_seconds = atoi(row[r]); r++; // "ability_time_seconds, " + pp->ability_number = atoi(row[r]); r++; // "ability_number, " + pp->ability_time_minutes = atoi(row[r]); r++; // "ability_time_minutes, " + pp->ability_time_hours = atoi(row[r]); r++; // "ability_time_hours, " + strcpy(pp->title, row[r]); r++; // "title, " + strcpy(pp->suffix, row[r]); r++; // "suffix, " + pp->exp = atoi(row[r]); r++; // "exp, " + pp->points = atoi(row[r]); r++; // "points, " + pp->mana = atoi(row[r]); r++; // "mana, " + pp->cur_hp = atoi(row[r]); r++; // "cur_hp, " + pp->STR = atoi(row[r]); r++; // "str, " + pp->STA = atoi(row[r]); r++; // "sta, " + pp->CHA = atoi(row[r]); r++; // "cha, " + pp->DEX = atoi(row[r]); r++; // "dex, " + pp->INT = atoi(row[r]); r++; // "`int`, " + pp->AGI = atoi(row[r]); r++; // "agi, " + pp->WIS = atoi(row[r]); r++; // "wis, " + pp->face = atoi(row[r]); r++; // "face, " + pp->y = atof(row[r]); r++; // "y, " + pp->x = atof(row[r]); r++; // "x, " + pp->z = atof(row[r]); r++; // "z, " + pp->heading = atof(row[r]); r++; // "heading, " + pp->pvp2 = atoi(row[r]); r++; // "pvp2, " + pp->pvptype = atoi(row[r]); r++; // "pvp_type, " + pp->autosplit = atoi(row[r]); r++; // "autosplit_enabled, " + pp->zone_change_count = atoi(row[r]); r++; // "zone_change_count, " + pp->drakkin_heritage = atoi(row[r]); r++; // "drakkin_heritage, " + pp->drakkin_tattoo = atoi(row[r]); r++; // "drakkin_tattoo, " + pp->drakkin_details = atoi(row[r]); r++; // "drakkin_details, " + pp->toxicity = atoi(row[r]); r++; // "toxicity, " + pp->hunger_level = atoi(row[r]); r++; // "hunger_level, " + pp->thirst_level = atoi(row[r]); r++; // "thirst_level, " + pp->ability_up = atoi(row[r]); r++; // "ability_up, " + pp->zone_id = atoi(row[r]); r++; // "zone_id, " + pp->zoneInstance = atoi(row[r]); r++; // "zone_instance, " + pp->leadAAActive = atoi(row[r]); r++; // "leadership_exp_on, " + pp->ldon_points_guk = atoi(row[r]); r++; // "ldon_points_guk, " + pp->ldon_points_mir = atoi(row[r]); r++; // "ldon_points_mir, " + pp->ldon_points_mmc = atoi(row[r]); r++; // "ldon_points_mmc, " + pp->ldon_points_ruj = atoi(row[r]); r++; // "ldon_points_ruj, " + pp->ldon_points_tak = atoi(row[r]); r++; // "ldon_points_tak, " + pp->ldon_points_available = atoi(row[r]); r++; // "ldon_points_available, " + pp->tribute_time_remaining = atoi(row[r]); r++; // "tribute_time_remaining, " + pp->showhelm = atoi(row[r]); r++; // "show_helm, " + pp->career_tribute_points = atoi(row[r]); r++; // "career_tribute_points, " + pp->tribute_points = atoi(row[r]); r++; // "tribute_points, " + pp->tribute_active = atoi(row[r]); r++; // "tribute_active, " + pp->endurance = atoi(row[r]); r++; // "endurance, " + pp->group_leadership_exp = atoi(row[r]); r++; // "group_leadership_exp, " + pp->raid_leadership_exp = atoi(row[r]); r++; // "raid_leadership_exp, " + pp->group_leadership_points = atoi(row[r]); r++; // "group_leadership_points, " + pp->raid_leadership_points = atoi(row[r]); r++; // "raid_leadership_points, " + pp->air_remaining = atoi(row[r]); r++; // "air_remaining, " + pp->PVPKills = atoi(row[r]); r++; // "pvp_kills, " + pp->PVPDeaths = atoi(row[r]); r++; // "pvp_deaths, " + pp->PVPCurrentPoints = atoi(row[r]); r++; // "pvp_current_points, " + pp->PVPCareerPoints = atoi(row[r]); r++; // "pvp_career_points, " + pp->PVPBestKillStreak = atoi(row[r]); r++; // "pvp_best_kill_streak, " + pp->PVPWorstDeathStreak = atoi(row[r]); r++; // "pvp_worst_death_streak, " + pp->PVPCurrentKillStreak = atoi(row[r]); r++; // "pvp_current_kill_streak, " + pp->aapoints_spent = atoi(row[r]); r++; // "aa_points_spent, " + pp->expAA = atoi(row[r]); r++; // "aa_exp, " + pp->aapoints = atoi(row[r]); r++; // "aa_points, " + pp->groupAutoconsent = atoi(row[r]); r++; // "group_auto_consent, " + pp->raidAutoconsent = atoi(row[r]); r++; // "raid_auto_consent, " + pp->guildAutoconsent = atoi(row[r]); r++; // "guild_auto_consent, " + pp->RestTimer = atoi(row[r]); r++; // "RestTimer, " + m_epp->aa_effects = atoi(row[r]); r++; // "`e_aa_effects`, " + m_epp->perAA = atoi(row[r]); r++; // "`e_percent_to_aa`, " + m_epp->expended_aa = atoi(row[r]); r++; // "`e_expended_aa_spent` " LogFile->write(EQEMuLog::Status, "Loading Character Data for character ID: %i, done", character_id); } return true; @@ -1060,6 +1066,16 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str return true; } +bool ZoneDatabase::LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp){ + std::string query = StringFormat("SELECT slot, rank FROM character_leadership_abilities WHERE `id` = %u", character_id); + auto results = database.QueryDatabase(query); uint32 slot = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + slot = atoi(row[0]); + pp->leader_abilities.ranks[slot] = atoi(row[1]); + } + return true; +} + bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp){ std::string query = StringFormat( "SELECT " @@ -1288,7 +1304,23 @@ bool ZoneDatabase::SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, return true; } -bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp){ +bool ZoneDatabase::SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp){ + uint8 first_entry = 0; std::string query = ""; + for (int i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ + if (pp->leader_abilities.ranks[i] > 0){ + if (first_entry != 1){ + query = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + first_entry = 1; + } + query = query + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + } + } + auto results = QueryDatabase(query); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterLeadershipAA", query); + return true; +} + +bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){ clock_t t = std::clock(); /* Function timer start */ std::string query = StringFormat( "REPLACE INTO `character_data` (" @@ -1381,7 +1413,11 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla " group_auto_consent, " " raid_auto_consent, " " guild_auto_consent, " - " RestTimer) " + " RestTimer, " + " e_aa_effects, " + " e_percent_to_aa, " + " e_expended_aa_spent " + ") " "VALUES (" "%u," // id " id, " "%u," // account_id " account_id, " @@ -1472,7 +1508,10 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla "%u," // group_auto_consent pp->groupAutoconsent, " group_auto_consent, " "%u," // raid_auto_consent pp->raidAutoconsent, " raid_auto_consent, " "%u," // guild_auto_consent pp->guildAutoconsent, " guild_auto_consent, " - "%u" // RestTimer pp->RestTimer, " RestTimer) " + "%u," // RestTimer pp->RestTimer, " RestTimer) " + "%u," // e_aa_effects + "%u," // e_percent_to_aa + "%u" // e_expended_aa_spent ")", character_id, // " id, " account_id, // " account_id, " @@ -1563,7 +1602,10 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla pp->groupAutoconsent, // " group_auto_consent, " pp->raidAutoconsent, // " raid_auto_consent, " pp->guildAutoconsent, // " guild_auto_consent, " - pp->RestTimer // " RestTimer) " + pp->RestTimer, // " RestTimer) " + m_epp->aa_effects, + m_epp->perAA, + m_epp->expended_aa ); auto results = database.QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR ZoneDatabase:SaveCharacterData: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } @@ -1650,7 +1692,11 @@ bool ZoneDatabase::DeleteCharacterBandolier(uint32 character_id, uint32 band_id) std::string query = StringFormat("DELETE FROM `character_bandolier` WHERE `bandolier_id` = %u AND `id` = %u", band_id, character_id); QueryDatabase(query); return true; } -bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ +bool ZoneDatabase::DeleteCharacterLeadershipAAs(uint32 character_id){ + std::string query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", character_id); QueryDatabase(query); return true; +} + +bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ std::string query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 3409537ec..0405fb3a9 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -255,18 +255,19 @@ public: bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp); - bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); + bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); - bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); 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); @@ -278,12 +279,14 @@ public: bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); + bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Deletes */ bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); + bool DeleteCharacterLeadershipAAs(uint32 character_id); /* Character Inventory */ bool NoRentExpired(const char* name); From 4c12d31e4a256c6aeb7610f23211440bffa3d5c8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 6 Sep 2014 22:35:19 -0500 Subject: [PATCH 14/56] Removed command character backup Changed all remaining references from the character_ table to the character_data --- common/database.cpp | 2 +- common/guild_base.cpp | 6 +-- common/shareddb.cpp | 4 +- ucs/database.cpp | 8 ++-- world/adventure_manager.cpp | 2 +- world/worlddb.cpp | 49 +++++----------------- world/zoneserver.cpp | 2 +- zone/client_packet.cpp | 2 +- zone/command.cpp | 84 +------------------------------------ zone/command.h | 1 - zone/guild_mgr.cpp | 53 ----------------------- zone/zonedb.cpp | 2 +- 12 files changed, 26 insertions(+), 189 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 7c8c988cf..0fb0cf846 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -728,7 +728,7 @@ uint32 Database::GetAccountIDByChar(const char* charname) { // Retrieve account_id for a given char_id uint32 Database::GetAccountIDByChar(uint32 char_id) { - std::string query = StringFormat("SELECT `account_id` FROM `character_` WHERE `id` = %i LIMIT 1", char_id); + std::string query = StringFormat("SELECT `account_id` FROM `character_data` WHERE `id` = %i LIMIT 1", char_id); auto results = QueryDatabase(query); if (!results.Success()) { LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); diff --git a/common/guild_base.cpp b/common/guild_base.cpp index 99e54934e..78fee70f9 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -892,10 +892,10 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) { " FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype " #else #define GuildMemberBaseQuery \ -"SELECT c.id,c.name,c.class,c.level,c.timelaston,c.zoneid," \ +"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \ " g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \ " g.banker,g.public_note,g.alt " \ -" FROM character_ AS c LEFT JOIN guild_members AS g ON c.id=g.char_id " +" FROM `character_data` AS c LEFT JOIN guild_members AS g ON c.id=g.char_id " #endif static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) { //fields from `characer_` @@ -1236,7 +1236,7 @@ BaseGuildManager::GuildInfo::GuildInfo() { uint32 BaseGuildManager::DoesAccountContainAGuildLeader(uint32 AccountID) { std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id IN " - "(SELECT id FROM character_ WHERE account_id = %i) AND rank = 2", + "(SELECT id FROM `character_data` WHERE account_id = %i) AND rank = 2", AccountID); auto results = m_db->QueryDatabase(query); if (!results.Success()) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 37bfe299c..d3bcf27f8 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -384,7 +384,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { if (is_charid) { len_query = MakeAnyLenString(&query, "SELECT sb.slotid,sb.itemid,sb.charges,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb " - "INNER JOIN character_ ch ON ch.account_id=sb.acctid " + "INNER JOIN character_data ch ON ch.account_id=sb.acctid " "WHERE ch.id=%i", id); } else { @@ -604,7 +604,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) if (RunQuery(query, MakeAnyLenString(&query, " SELECT `slotid`, `itemid`, `charges`, `color`, `augslot1`, `augslot2`, `augslot3`, `augslot4`, `augslot5`, `instnodrop`, `custom_data`" " FROM `inventory`" - " INNER JOIN character_ ch ON ch.id = charid" + " INNER JOIN `character_data` ch ON ch.id = charid" " WHERE ch.NAME = '%s'" " AND ch.account_id = % i" " ORDER BY `slotid`", diff --git a/ucs/database.cpp b/ucs/database.cpp index d3c44174c..38f3e06f7 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -139,7 +139,7 @@ int Database::FindAccount(const char *characterName, Client *client) { client->ClearCharacters(); std::string query = StringFormat("SELECT `id`, `account_id`, `level` " - "FROM `character_` WHERE `name` = '%s' LIMIT 1", + "FROM `character_data` WHERE `name` = '%s' LIMIT 1", characterName); auto results = QueryDatabase(query); if (!results.Success()) { @@ -159,7 +159,7 @@ int Database::FindAccount(const char *characterName, Client *client) { _log(UCS__TRACE, "Account ID for %s is %i", characterName, accountID); - query = StringFormat("SELECT `id`, `name`, `level` FROM `character_` " + query = StringFormat("SELECT `id`, `name`, `level` FROM `character_data` " "WHERE `account_id` = %i AND `name` != '%s'", accountID, characterName); results = QueryDatabase(query); @@ -174,7 +174,7 @@ int Database::FindAccount(const char *characterName, Client *client) { bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::string MailKey) { - std::string query = StringFormat("SELECT `mailkey` FROM `character_` WHERE `name`='%s' LIMIT 1", + std::string query = StringFormat("SELECT `mailkey` FROM `character_data` WHERE `name`='%s' LIMIT 1", characterName.c_str()); auto results = QueryDatabase(query); if (!results.Success()) { @@ -202,7 +202,7 @@ bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::stri int Database::FindCharacter(const char *characterName) { char *safeCharName = RemoveApostrophes(characterName); - std::string query = StringFormat("SELECT `id` FROM `character_` WHERE `name`='%s' LIMIT 1", safeCharName); + std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name`='%s' LIMIT 1", safeCharName); auto results = QueryDatabase(query); if (!results.Success()) { _log(UCS__ERROR, "FindCharacter failed. %s %s", query.c_str(), results.ErrorMessage().c_str()); diff --git a/world/adventure_manager.cpp b/world/adventure_manager.cpp index 047aca326..4df67ef69 100644 --- a/world/adventure_manager.cpp +++ b/world/adventure_manager.cpp @@ -1069,7 +1069,7 @@ void AdventureManager::LoadLeaderboardInfo() leaderboard_info_percentage_tak.clear(); std::string query = "SELECT ch.name, ch.id, adv_stats.* FROM adventure_stats " - "AS adv_stats LEFT JOIN character_ AS ch ON adv_stats.player_id = ch.id;"; + "AS adv_stats LEFT JOIN `character_data` AS ch ON adv_stats.player_id = ch.id;"; auto results = database.QueryDatabase(query); if(!results.Success()) { LogFile->write(EQEMuLog::Error, "Error in AdventureManager:::GetLeaderboardInfo: %s (%s)", query.c_str(), results.ErrorMessage().c_str()); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index fdbcc704d..4192e0d84 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -182,45 +182,16 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* } int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) { - // if an invalid bind point is specified, use the primary bind - if (bindnum > 4) - bindnum = 0; + /* if an invalid bind point is specified, use the primary bind */ + if (bindnum > 4){ bindnum = 0; } + int is_home = 0; + if (bindnum == 4){ is_home = 1; } - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 affected_rows = 0; - PlayerProfile_Struct pp; - - bool PPValid = false; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile from character_ where id='%i'", CharID), errbuf, &result)) { - row = mysql_fetch_row(result); - unsigned long* lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(PlayerProfile_Struct)) { - memcpy(&pp, row[0], sizeof(PlayerProfile_Struct)); - PPValid = true; - } - mysql_free_result(result); + std::string query = StringFormat("SELECT `zone_id` FROM `character_bind` WHERE `id` = %u AND `is_home` = %u LIMIT 1", CharID, is_home); + auto results = database.QueryDatabase(query); int i = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + return atoi(row[0]); } - safe_delete_array(query); - - if(!PPValid) return 0; - - const char *BindZoneName = StaticGetZoneName(pp.binds[bindnum].zoneId); - - if(!strcmp(BindZoneName, "UNKNWN")) return pp.zone_id; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET zonename = '%s',zoneid=%i,x=%f, y=%f, z=%f, instanceid=0 WHERE id='%i'", - BindZoneName, pp.binds[bindnum].zoneId, pp.binds[bindnum].x, pp.binds[bindnum].y, pp.binds[bindnum].z, - CharID), errbuf, 0,&affected_rows)) { - - return pp.zone_id; - } - safe_delete_array(query); - - return pp.binds[bindnum].zoneId; } bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc) @@ -481,7 +452,7 @@ void WorldDatabase::SetMailKey(int CharID, int IPAddress, int MailKey) { else sprintf(MailKeyString, "%08X", MailKey); - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET mailkey = '%s' WHERE id='%i'", + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE `character_data` SET mailkey = '%s' WHERE id='%i'", MailKeyString, CharID), errbuf)) LogFile->write(EQEMuLog::Error, "WorldDatabase::SetMailKey(%i, %s) : %s", CharID, MailKeyString, errbuf); @@ -497,7 +468,7 @@ bool WorldDatabase::GetCharacterLevel(const char *name, int &level) MYSQL_RES *result; MYSQL_ROW row; - if(RunQuery(query, MakeAnyLenString(&query, "SELECT level FROM character_ WHERE name='%s'", name), errbuf, &result)) + if(RunQuery(query, MakeAnyLenString(&query, "SELECT `level` FROM `character_data` WHERE `name` = '%s'", name), errbuf, &result)) { if(row = mysql_fetch_row(result)) { diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 6529a1f3d..4796104a7 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -454,7 +454,7 @@ bool ZoneServer::Process() { timeinfo = localtime ( &rawtime ); char *telldate=asctime(timeinfo); - std::string query = StringFormat("SELECT name FROM character_ WHERE name = '%s'",scm->deliverto); + std::string query = StringFormat("SELECT name FROM `character_data` WHERE name = '%s'",scm->deliverto); auto results = database.QueryDatabase(query); if (!results.Success()) break; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2a0ade9db..0e8ae509f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4750,7 +4750,7 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) } #ifdef BOTS else if (invitee->IsBot()) { - // The guild system is too tightly coupled with the character_ table so we have to avoid using much of the system + // The guild system is too tightly coupled with the character_data table so we have to avoid using much of the system Bot::ProcessGuildInvite(this, invitee->CastToBot()); return; } diff --git a/zone/command.cpp b/zone/command.cpp index ea85fb9af..e5ec3f074 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -257,12 +257,11 @@ int command_init(void) { command_add("dbspawn",nullptr,0,command_npctypespawn) || command_add("heal","- Completely heal your target",10,command_heal) || command_add("appearance","[type] [value] - Send an appearance packet for you or your target",150,command_appearance) || - command_add("charbackup","[list/restore] - Query or restore character backups",150,command_charbackup) || command_add("nukeitem","[itemid] - Remove itemid from your player target's inventory",150,command_nukeitem) || command_add("peekinv","[worn/cursor/inv/bank/trade/trib/all] - Print out contents of your player target's inventory",100,command_peekinv) || command_add("findnpctype","[search criteria] - Search database NPC types",100,command_findnpctype) || command_add("findzone","[search criteria] - Search database zones",100,command_findzone) || - command_add("fz",nullptr,100,command_findzone) || + command_add("fz",nullptr,100, command_findzone) || command_add("viewnpctype","[npctype id] - Show info about an npctype",100,command_viewnpctype) || command_add("reloadstatic","- Reload Static Zone Data",150,command_reloadstatic) || command_add("reloadquest"," - Clear quest cache (any argument causes it to also stop all timers)",150,command_reloadqst) || @@ -2767,85 +2766,6 @@ void command_appearance(Client *c, const Seperator *sep) } } -void command_charbackup(Client *c, const Seperator *sep) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - if (strcasecmp(sep->arg[1], "list") == 0) { - uint32 charid = 0; - if (sep->IsNumber(2)) - charid = atoi(sep->arg[2]); - else - database.GetAccountIDByChar(sep->arg[2]); - if (charid) { - if (database.RunQuery(query, MakeAnyLenString(&query, - "Select id, backupreason, charid, account_id, zoneid, DATE_FORMAT(ts, '%%m/%%d/%%Y %%H:%%i:%%s') " - " from character_backup where charid=%u", charid), errbuf, &result)) { - safe_delete(query); - uint32 x = 0; - while ((row = mysql_fetch_row(result))) { - c->Message(0, " %u: %s, %s (%u), reason=%u", atoi(row[0]), row[5], database.GetZoneName(atoi(row[4])), atoi(row[4]), atoi(row[1])); - x++; - } - c->Message(0, " %u backups found.", x); - mysql_free_result(result); - } - else { - c->Message(13, "Query error: '%s' %s", query, errbuf); - safe_delete(query); - } - } - else - c->Message(0, "Usage: #charbackup list [char name/id]"); - } - else if (strcasecmp(sep->arg[1], "restore") == 0) { - uint32 charid = 0; - if (sep->IsNumber(2)) - charid = atoi(sep->arg[2]); - else - database.GetAccountIDByChar(sep->arg[2]); - - if (charid && sep->IsNumber(3)) { - uint32 cbid = atoi(sep->arg[3]); - if (database.RunQuery(query, MakeAnyLenString(&query, - "Insert into character_backup (backupreason, charid, account_id, name, profile, level, class, x, y, z, zoneid, alt_adv) " - " select 1, id, account_id, name, profile, level, class, x, y, z, zoneid, alt_adv from character_ where id=%u", charid), errbuf)) { - if (database.RunQuery(query, MakeAnyLenString(&query, - "update character_ inner join character_backup on character_.id = character_backup.charid " - " set character_.name = character_backup.name, " - " character_.profile = character_backup.profile, " - " character_.level = character_backup.level, " - " character_.class = character_backup.class, " - " character_.x = character_backup.x, " - " character_.y = character_backup.y, " - " character_.z = character_backup.z, " - " character_.zoneid = character_backup.zoneid " - " where character_backup.charid=%u and character_backup.id=%u", charid, cbid), errbuf)) { - safe_delete(query); - c->Message(0, "Character restored."); - } - else { - c->Message(13, "Query error: '%s' %s", query, errbuf); - safe_delete(query); - } - } - else { - c->Message(13, "Query error: '%s' %s", query, errbuf); - safe_delete(query); - } - } - else - c->Message(0, "Usage: #charbackup list [char name/id]"); - } - else { - c->Message(0, "#charbackup sub-commands:"); - c->Message(0, " list [char name/id]"); - c->Message(0, " restore [char name/id] [backup#]"); - } -} - void command_nukeitem(Client *c, const Seperator *sep) { int numitems, itemid; @@ -6296,7 +6216,7 @@ void command_ban(Client *c, const Seperator *sep) } else { - database.RunQuery(query, MakeAnyLenString(&query, "SELECT account_id from character_ where name = '%s'", sep->arg[1]), errbuf, &result); + database.RunQuery(query, MakeAnyLenString(&query, "SELECT account_id from `character_data` where name = '%s'", sep->arg[1]), errbuf, &result); if(query) { safe_delete_array(query); diff --git a/zone/command.h b/zone/command.h index ef7302c51..d495faee7 100644 --- a/zone/command.h +++ b/zone/command.h @@ -150,7 +150,6 @@ void command_texture(Client *c, const Seperator *sep); void command_npctypespawn(Client *c, const Seperator *sep); void command_heal(Client *c, const Seperator *sep); void command_appearance(Client *c, const Seperator *sep); -void command_charbackup(Client *c, const Seperator *sep); void command_nukeitem(Client *c, const Seperator *sep); void command_peekinv(Client *c, const Seperator *sep); void command_findnpctype(Client *c, const Seperator *sep); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 37cc7a3de..2172df3c6 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -24,59 +24,6 @@ #include "client.h" #include "entity.h" -/* - -CREATE TABLE guilds ( - id MEDIUMINT UNSIGNED NOT NULL, - name VARCHAR(32) NOT NULL, - leader int NOT NULL, - minstatus SMALLINT NOT NULL, - tribute INT UNSIGNED NOT NULL, - motd TEXT NOT NULL DEFAULT '', - PRIMARY KEY(id), - UNIQUE KEY(name), - UNIQUE KEY(leader) -); - -CREATE TABLE guild_ranks ( - guild_id MEDIUMINT UNSIGNED NOT NULL, - rank TINYINT UNSIGNED NOT NULL, - title VARCHAR(128) NOT NULL, - can_hear TINYINT UNSIGNED NOT NULL, - can_speak TINYINT UNSIGNED NOT NULL, - can_invite TINYINT UNSIGNED NOT NULL, - can_remove TINYINT UNSIGNED NOT NULL, - can_promote TINYINT UNSIGNED NOT NULL, - can_demote TINYINT UNSIGNED NOT NULL, - can_motd TINYINT UNSIGNED NOT NULL, - can_warpeace TINYINT UNSIGNED NOT NULL, - PRIMARY KEY(guild_id,rank) -); - -# guild1 < guild2 by definition. -CREATE TABLE guild_relations ( - guild1 MEDIUMINT UNSIGNED NOT NULL, - guild2 MEDIUMINT UNSIGNED NOT NULL, - relation TINYINT NOT NULL, - PRIMARY KEY(guild1, guild1) -); - -CREATE TABLE guild_members ( - char_id INT NOT NULL, - guild_id MEDIUMINT UNSIGNED NOT NULL, - rank TINYINT UNSIGNED NOT NULL, - tribute_enable TINYINT UNSIGNED NOT NULL DEFAULT 0, - total_tribute INT UNSIGNED NOT NULL DEFAULT 0, - last_tribute INT UNSIGNED NOT NULL DEFAULT 0, - banker TINYINT UNSIGNED NOT NULL DEFAULT 0, - public_note TEXT NOT NULL DEFAULT '', - PRIMARY KEY(char_id) -); - - -*/ - - ZoneGuildManager guild_mgr; GuildBankManager *GuildBanks; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ef14a3657..9a5d95eee 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1705,7 +1705,7 @@ bool ZoneDatabase::NoRentExpired(const char* name){ char *query = 0; MYSQL_RES *result; MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "Select (UNIX_TIMESTAMP(NOW())-timelaston) from character_ where name='%s'", name), errbuf, &result)) { + if (RunQuery(query, MakeAnyLenString(&query, "Select (UNIX_TIMESTAMP(NOW()) - last_login) from `character_data` where name='%s'", name), errbuf, &result)) { safe_delete_array(query); if (mysql_num_rows(result) == 1) { row = mysql_fetch_row(result); From a14371ba5ca55d5b664494acd7594cceab0ebff5 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 7 Sep 2014 04:00:56 -0500 Subject: [PATCH 15/56] Removed debugging Added player profile data loading safety net checking --- common/database.cpp | 3 ++- common/eq_packet_structs.h | 4 ++-- zone/client_packet.cpp | 25 +++++++++++++++---------- zone/zonedb.cpp | 35 ++++++++++++++++++++++++++++++----- zone/zoning.cpp | 11 ----------- 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 0fb0cf846..614ae73d7 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -649,6 +649,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe pp->RestTimer // " RestTimer) " ); auto results = QueryDatabase(query); + ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate", query); return true; } @@ -1247,7 +1248,7 @@ bool Database::CheckDatabaseConversions() { // Testing account = 11001 int char_iter_count = 0; - rquery = StringFormat("SELECT `id` FROM `character_` WHERE `account_id` = 11001"); + rquery = StringFormat("SELECT `id` FROM `character_`"); results = QueryDatabase(rquery); uint8 firstlogon = 0; diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 061f498d4..64effb762 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -801,8 +801,8 @@ struct SuspendedMinion_Struct ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 720; // Set for all functions -static const uint32 MAX_PP_MEMSPELL = 12; // Set to latest client so functions can work right +static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions +static const uint32 MAX_PP_MEMSPELL = 9; // Set to latest client so functions can work right static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0e8ae509f..fd8433e1e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -542,29 +542,26 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { std::string query; unsigned long* lengths; - /* Set item material tint */ - for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) - if (m_pp.item_tint[i].rgb.use_tint == 1) - m_pp.item_tint[i].rgb.use_tint = 0xFF; - uint32 cid = CharacterID(); character_id = cid; /* Global character_id reference */ + clock_t t = std::clock(); /* Function timer start */ + /* Flush and reload factions */ database.RemoveTempFactions(this); database.LoadCharacterFactionValues(cid, factionvalues); /* Load Character Account Data: Temp until I move */ - query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %i", this->AccountID()); + query = StringFormat("SELECT `status`, `name`, `lsaccount_id`, `gmspeed`, `revoked`, `hideme` FROM `account` WHERE `id` = %u", this->AccountID()); auto results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { if (admin){ admin = atoi(row[0]); } if (account_name){ strcpy(account_name, row[1]); } if (lsaccountid && atoi(row[2]) > 0){ lsaccountid = atoi(row[2]); } else{ lsaccountid = 0; } - if (gmspeed){ gmspeed = atoi(row[3]); } - if (revoked){ revoked = atoi(row[4]); } - if (gmhideme){ gmhideme = atoi(row[5]); } + gmspeed = atoi(row[3]); + revoked = atoi(row[4]); + gmhideme = atoi(row[5]); if (account_creation){ account_creation = atoul(row[6]); } } @@ -587,7 +584,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { if (LFG){ LFG = atoi(row[1]); } if (firstlogon){ firstlogon = atoi(row[3]); } } - + loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */ database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ @@ -603,6 +600,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { database.LoadCharacterLanguages(cid, &m_pp); /* Load Character Languages */ database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ + /* Set item material tint */ + for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) + if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255) + m_pp.item_tint[i].rgb.use_tint = 0xFF; + + std::cout << "Character Data Load Took " << (((float)(std::clock() - t)) / CLOCKS_PER_SEC) << " seconds\n" << std::endl; + if (level){ level = m_pp.level; } /* If GM, not trackable */ @@ -4981,6 +4985,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) /* Memorized Spell */ if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id){ + uint16 spell_to_cast = 0; if (castspell->slot < MAX_PP_MEMSPELL) { spell_to_cast = m_pp.mem_spells[castspell->slot]; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 9a5d95eee..82b38c44e 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1032,7 +1032,12 @@ bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_ "`character_memmed_spells` " "WHERE `id` = %u ORDER BY `slot_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->mem_spells[i] = atoi(row[1]); } + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); + if (i < MAX_PP_MEMSPELL){ + pp->mem_spells[i] = atoi(row[1]); + } + } return true; } @@ -1045,7 +1050,12 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str "`character_spells` " "WHERE `id` = %u ORDER BY `slot_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->spell_book[i] = atoi(row[1]); } + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); + if (i < MAX_PP_SPELLBOOK){ + pp->spell_book[i] = atoi(row[1]); + } + } return true; } @@ -1062,7 +1072,12 @@ bool ZoneDatabase::LoadCharacterLanguages(uint32 character_id, PlayerProfile_Str for (i = 0; i < MAX_PP_LANGUAGE; i++){ pp->languages[i] = 0; } - for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->languages[i] = atoi(row[1]); } + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); + if (i < MAX_PP_LANGUAGE){ + pp->languages[i] = atoi(row[1]); + } + } return true; } @@ -1084,7 +1099,12 @@ bool ZoneDatabase::LoadCharacterDisciplines(uint32 character_id, PlayerProfile_S "`character_disciplines`" "WHERE `id` = %u ORDER BY `disc_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (auto row = results.begin(); row != results.end(); ++row) { pp->disciplines.values[i] = atoi(row[0]); i++; } + for (auto row = results.begin(); row != results.end(); ++row) { + if (i < MAX_PP_DISCIPLINES){ + pp->disciplines.values[i] = atoi(row[0]); + } + i++; + } return true; } @@ -1101,7 +1121,12 @@ bool ZoneDatabase::LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct for (i = 0; i < MAX_PP_SKILL; i++){ pp->skills[i] = 0; } - for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); pp->skills[i] = atoi(row[1]); } + for (auto row = results.begin(); row != results.end(); ++row) { + i = atoi(row[0]); + if (i < MAX_PP_SKILL){ + pp->skills[i] = atoi(row[1]); + } + } return true; } diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 0eb204d1f..0cbf39a2c 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -386,17 +386,6 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc strcpy(ztz->name, GetName()); ztz->guild_id = GuildID(); worldserver.SendPacket(pack); - - printf("ZONING REQUEST TO WORLD\n"); - printf("ztz->response %u \n", ztz->response); - printf("ztz->current_zone_id %u \n", ztz->current_zone_id); - printf("ztz->current_instance_id %u \n", ztz->current_instance_id); - printf("ztz->requested_zone_id %u \n", ztz->requested_zone_id); - printf("ztz->requested_instance_id %u \n", ztz->requested_instance_id); - printf("ztz->admin %u \n", ztz->admin); - printf("ztz->ignorerestrictions %u \n", ztz->ignorerestrictions); - printf("ztz->guild_id %u \n", ztz->guild_id); - safe_delete(pack); } From 1f9597a9e2fb73cab22c82a24d1a22c742995605 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 7 Sep 2014 05:35:19 -0500 Subject: [PATCH 16/56] Fix for item dupe via RoF augmenting --- common/item.cpp | 11 +++++++++++ common/item.h | 1 + zone/client_packet.cpp | 6 +++--- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/common/item.cpp b/common/item.cpp index 127f85614..65f57dbf9 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1580,6 +1580,17 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const return (i < EmuConstants::ITEM_COMMON_SIZE) ? i : INVALID_INDEX; } +bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const { + if (m_item->ItemClass != ItemClassCommon || !m_item) + return -1; + + if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) { + return true; + } + + return false; +} + // Retrieve item inside container ItemInst* ItemInst::GetItem(uint8 index) const { diff --git a/common/item.h b/common/item.h index f279bd2aa..c24c708b1 100644 --- a/common/item.h +++ b/common/item.h @@ -274,6 +274,7 @@ public: inline bool IsAugmentable() const { return m_item->AugSlotType[0]!=0 || m_item->AugSlotType[1]!=0 || m_item->AugSlotType[2]!=0 || m_item->AugSlotType[3]!=0 || m_item->AugSlotType[4]!=0; } bool AvailableWearSlot(uint32 aug_wear_slots) const; int8 AvailableAugmentSlot(int32 augtype) const; + bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; inline int32 GetAugmentType() const { return m_item->AugType; } inline bool IsExpendable() const { return ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index fa29c07a6..02bedc17c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6784,10 +6784,10 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if(tobe_auged && auged_with) { - if (((slot=tobe_auged->AvailableAugmentSlot(auged_with->GetAugmentType()))!=-1) && + if (((tobe_auged->IsAugmentSlotAvailable(auged_with->GetAugmentType(), in_augment->augment_index)) != -1) && (tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots))) { - tobe_auged->PutAugment(slot, *auged_with); + tobe_auged->PutAugment(in_augment->augment_index, *auged_with); ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index); if(aug) { @@ -6800,7 +6800,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) } else { - Message(13, "Error: Could not find augmentation at index %i. Aborting."); + Message(13, "Error: Could not find augmentation at index %i. Aborting.", in_augment->augment_index); return; } From 899cf32e6b8d5a586ccb18a709e7c40d1a3e22db Mon Sep 17 00:00:00 2001 From: akkadius Date: Tue, 9 Sep 2014 16:03:24 -0500 Subject: [PATCH 17/56] Added some DB logging to catch any potential query errors, this logs to eqemu_query_error_log.txt at the root folder, currently no rule toggling for this Corrected some character name reservation logic Adjusted telnet console so it does not throw 'Command Unknown' when simply hitting enter key Adjusted System MSG for worldshutdown to use minutes instead of seconds Added warning for when Shared platinum is disabled at the rule level for players to NOT put platinum in the shared bank when they insert platinum in the shared platinum slot Changed a place in the code where disciplines were trained, someone had uint16 allocated to CharacterID and this was causing issues for characters with large ID's in the database Added a fix for bind points getting overwritten with invalid zone data, setting everything to 0,0,0,0 - Since I've added this change I've had no issues for players Fixed some spell book swap logic in the code, removed swap function. Fixed issue with guild ranks not loading properly Commented out some of the non-working tell-que code Took out some of the auto increment settings in the auto database conversion that don't affect anything anyways Added some additional escape string sequences for queries that needed them Added ThrowDBError logging to catch any potential query issues with saves or load functions --- common/database.cpp | 78 ++++++++++++++++++++++++++--------------- world/client.cpp | 2 +- world/console.cpp | 5 ++- world/zonelist.cpp | 4 +-- world/zoneserver.cpp | 50 +++++++++++++------------- zone/client_packet.cpp | 29 ++++++++------- zone/client_process.cpp | 7 +++- zone/command.cpp | 4 +-- zone/questmgr.cpp | 8 ++--- zone/zonedb.cpp | 42 ++++++++++++---------- zone/zonedb.h | 1 - 11 files changed, 130 insertions(+), 100 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 287e65a9d..e6983b368 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -18,6 +18,10 @@ #include "../common/debug.h" #include "../common/rulesys.h" #include +#include + +using namespace std; + #include #include #include @@ -306,11 +310,21 @@ bool Database::SetAccountStatus(const char* name, int16 status) { bool Database::ReserveName(uint32 account_id, char* name) { std::string query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::ReserveName", query); + if (!results.Success() || results.ErrorMessage() != ""){ return false; } return true; } bool Database::ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query){ - if (ErrorMessage != ""){ std::cout << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n" << std::endl; return true; } + if (ErrorMessage != ""){ + std::cout << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n" << std::endl; + + /* Write to file temporarily */ + std::ofstream log("eqemu_query_error_log.txt", std::ios_base::app | std::ios_base::out); + log << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n"; + log.close(); + + return true; + } return false; } @@ -987,7 +1001,7 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_currency` doesn't exist... creating..."); rquery = StringFormat( " CREATE TABLE `character_currency` ( " - " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `platinum` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `gold` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `silver` int(11) UNSIGNED NOT NULL DEFAULT 0, " @@ -1006,7 +1020,7 @@ bool Database::CheckDatabaseConversions() { " `career_ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " " PRIMARY KEY (`id`), " " KEY `id` (`id`) " - " ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; " + " ) ENGINE=InnoDB DEFAULT CHARSET=latin1; " ); QueryDatabase(rquery); printf(" done...\n"); @@ -1018,13 +1032,13 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_alternate_abilities` doesn't exist... creating..."); rquery = StringFormat( " CREATE TABLE `character_alternate_abilities` ( " - " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " " `aa_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " " `aa_value` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " " PRIMARY KEY(`id`,`slot`), " " KEY `id` (`id`) " - " ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); QueryDatabase(rquery); printf(" done...\n"); @@ -1046,7 +1060,7 @@ bool Database::CheckDatabaseConversions() { "`heading` float NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`, `is_home`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1063,7 +1077,7 @@ bool Database::CheckDatabaseConversions() { "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`, `lang_id`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1080,7 +1094,7 @@ bool Database::CheckDatabaseConversions() { "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`, `skill_id`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1097,7 +1111,7 @@ bool Database::CheckDatabaseConversions() { "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`, `slot_id`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1109,12 +1123,12 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_memmed_spells` doesn't exist... creating..."); rquery = StringFormat( "CREATE TABLE `character_memmed_spells` ( " - "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`id` int(11) UNSIGNED NOT NULL DEFAULT 0, " "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`, `slot_id`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1126,12 +1140,12 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_disciplines` doesn't exist... creating..."); rquery = StringFormat( " CREATE TABLE `character_disciplines` ( " - " `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " " `slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " " `disc_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " " PRIMARY KEY(`id`, `slot_id`), " " KEY `id` (`id`) " - " ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); QueryDatabase(rquery); printf(" done...\n"); @@ -1141,7 +1155,7 @@ bool Database::CheckDatabaseConversions() { results = QueryDatabase(rquery); if (results.RowCount() == 0){ printf("Table: `character_material` doesn't exist... creating..."); - rquery = StringFormat( + rquery = StringFormat( "CREATE TABLE `character_material` ( " "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT," "`slot` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," @@ -1164,11 +1178,11 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_tribute` doesn't exist... creating..."); rquery = StringFormat( "CREATE TABLE `character_tribute` ( " - "`id` int(11) unsigned NOT NULL AUTO_INCREMENT, " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " "`tier` tinyint(11) unsigned NOT NULL DEFAULT '0', " "`tribute` int(11) UNSIGNED NOT NULL DEFAULT '0', " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1180,7 +1194,7 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_bandolier` doesn't exist... creating..."); rquery = StringFormat( "CREATE TABLE `character_bandolier` ( " - "`id` int(11) unsigned NOT NULL AUTO_INCREMENT, " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " "`bandolier_id` tinyint(11) unsigned NOT NULL DEFAULT '0', " "`bandolier_slot` tinyint(11) unsigned NOT NULL DEFAULT '0', " "`item_id` int(11) UNSIGNED NOT NULL DEFAULT '0', " @@ -1188,7 +1202,7 @@ bool Database::CheckDatabaseConversions() { "`bandolier_name` varchar(32) NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`,`bandolier_id`, `bandolier_slot`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); QueryDatabase(rquery); printf(" done...\n"); @@ -1200,13 +1214,13 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_potionbelt` doesn't exist... creating..."); rquery = StringFormat( "CREATE TABLE `character_potionbelt` ( " - "`id` int(11) unsigned NOT NULL AUTO_INCREMENT, " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " "`potion_id` tinyint(11) unsigned NOT NULL DEFAULT '0', " "`item_id` int(11) UNSIGNED NOT NULL DEFAULT '0', " "`icon` int(11) UNSIGNED NOT NULL DEFAULT '0', " "PRIMARY KEY(`id`,`potion_id`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1218,11 +1232,11 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_inspect_messages` doesn't exist... creating..."); rquery = StringFormat( "CREATE TABLE `character_inspect_messages` ( " - "`id` int(11) unsigned NOT NULL AUTO_INCREMENT, " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " "`inspect_message` varchar(255) NOT NULL DEFAULT '', " "PRIMARY KEY(`id`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); QueryDatabase(rquery); printf(" done...\n"); @@ -1234,12 +1248,12 @@ bool Database::CheckDatabaseConversions() { printf("Table: `character_leadership_abilities` doesn't exist... creating..."); rquery = StringFormat( "CREATE TABLE `character_leadership_abilities` (" - "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`id` int(11) UNSIGNED NOT NULL DEFAULT 0, " "`slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " "`rank` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " "PRIMARY KEY(`id`,`slot`), " "KEY `id` (`id`) " - ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); QueryDatabase(rquery); printf(" done...\n"); @@ -2650,15 +2664,21 @@ uint32 Database::GetGroupID(const char* name){ /* Is this really getting used properly... A half implementation ? Akkadius */ char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf){ + leaderbuf = ""; std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name = '%s'", name); auto results = QueryDatabase(query); auto row = results.begin(); uint32 group_id = 0; - if (row[0]){ group_id = atoi(row[0]); } + for (auto row = results.begin(); row != results.end(); ++row) { + if (row[0]){ group_id = atoi(row[0]); } + } - query = StringFormat("SELECT `name` FROM `group_id` WHERE `name` != '%s' AND `groupid` = %u", name, group_id); - results = QueryDatabase(query); - row = results.begin(); - if (row[0]){ strcpy(leaderbuf, row[0]); } + if (group_id > 0){ + query = StringFormat("SELECT `leadername` FROM `group_leader` WHERE `gid` = '%u' AND `groupid` = %u LIMIT 1", group_id); + results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + if (row[0]){ strcpy(leaderbuf, row[0]); } + } + } return leaderbuf; } diff --git a/world/client.cpp b/world/client.cpp index c8fea66c9..e7e999ce5 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -486,7 +486,7 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { outapp->pBuffer = new uchar[1]; outapp->size = 1; - bool valid; + bool valid = false; if(!database.CheckNameFilter(char_name)) { valid = false; } else if (char_name[0] < 'A' && char_name[0] > 'Z') { valid = false; } /* Name must begin with an upper-case letter. */ else if (database.ReserveName(GetAccountID(), char_name)) { valid = true; } diff --git a/world/console.cpp b/world/console.cpp index d5433067e..6caa9ce86 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -113,7 +113,7 @@ bool Console::SendChannelMessage(const ServerChannelMessage_Struct* scm) { break; } case 7: { - SendMessage(1, "%s tells you, '%s'", scm->from, scm->message); + SendMessage(1, "[%s] tells you, '%s'", scm->from, scm->message); ServerPacket* pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); memcpy(pack->pBuffer, scm, pack->size); ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*) pack->pBuffer; @@ -847,6 +847,9 @@ void Console::ProcessCommand(const char* command) { zoneserver_list.SendPacket(pack); safe_delete(pack); } + else if (strcasecmp(sep.arg[0], "") == 0){ + /* Hit Enter with no command */ + } else { SendMessage(1, "Command unknown."); } diff --git a/world/zonelist.cpp b/world/zonelist.cpp index fdf9db5cf..c97010aa8 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -87,7 +87,7 @@ void ZSList::Process() { CatchSignal(2); } if(reminder && reminder->Check()){ - SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down, everyone log out now. World will shut down in %i seconds...",shutdowntimer->GetRemainingTime()/1000); + SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down, everyone log out now. World will shut down in %i minutes...", ((shutdowntimer->GetRemainingTime()/1000) / 60)); } LinkedListIterator iterator(list); @@ -718,7 +718,7 @@ void ZSList::GetZoneIDList(std::vector &zones) { void ZSList::WorldShutDown(uint32 time, uint32 interval) { if( time > 0 ) { - SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down in %i seconds, everyone log out before this time.",time); + SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down in %i minutes, everyone log out before this time.", (time / 60)); time *= 1000; interval *= 1000; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 4796104a7..c740ff3bc 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -448,31 +448,31 @@ bool ZoneServer::Process() { else if (cle->Online() == CLE_Status_Zoning) { if (!scm->noreply) { - time_t rawtime; - struct tm * timeinfo; - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - char *telldate=asctime(timeinfo); - - std::string query = StringFormat("SELECT name FROM `character_data` WHERE name = '%s'",scm->deliverto); - auto results = database.QueryDatabase(query); - if (!results.Success()) - break; - - if (results.RowCount() == 0) { - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); - break; - } - - query = StringFormat("INSERT INTO tellque " - "(Date, Receiver, Sender, Message) " - "VALUES('%s', '%s', '%s', '%s')", - telldate, scm->deliverto, scm->from, scm->message); - results = database.QueryDatabase(query); - if (results.Success()) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to the %s's que.", scm->to); - else - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); + // time_t rawtime; + // struct tm * timeinfo; + // time ( &rawtime ); + // timeinfo = localtime ( &rawtime ); + // char *telldate=asctime(timeinfo); + // + // std::string query = StringFormat("SELECT name FROM `character_data` WHERE name = '%s'",scm->deliverto); + // auto results = database.QueryDatabase(query); + // if (!results.Success()) + // break; + // + // if (results.RowCount() == 0) { + // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); + // break; + // } + // + // query = StringFormat("INSERT INTO tellque " + // "(Date, Receiver, Sender, Message) " + // "VALUES('%s', '%s', '%s', '%s')", + // telldate, scm->deliverto, scm->from, scm->message); + // results = database.QueryDatabase(query); + // if (results.Success()) + // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to the %s's que.", scm->to); + // else + // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); } // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 02bedc17c..6865eadfc 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -571,21 +571,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { m_pp.lastlogin = time(nullptr); - if (row[4]){ + if (atoi(row[4]) > 0){ guild_id = atoi(row[4]); - if (guildrank) { - if (row[5] != nullptr){ guildrank = atoi(row[5]); } - else{ guildrank = GUILD_RANK_NONE; } - } + if (row[5] != nullptr){ guildrank = atoi(row[5]); } + else{ guildrank = GUILD_RANK_NONE; } } - if (RuleB(Character, SharedBankPlat)) - m_pp.platinum_shared = database.GetSharedPlatinum(database.GetAccountIDByChar(cid)); - + if (LFP){ LFP = atoi(row[0]); } if (LFG){ LFG = atoi(row[1]); } if (firstlogon){ firstlogon = atoi(row[3]); } } + if (RuleB(Character, SharedBankPlat)) + m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID()); + loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */ database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ @@ -622,6 +621,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { /* If we can maintain intoxication across zones, check for it */ if (!RuleB(Character, MaintainIntoxicationAcrossZones)) m_pp.intoxication = 0; + strcpy(name, m_pp.name); strcpy(lastname, m_pp.last_name); /* If PP is set to weird coordinates */ @@ -751,10 +751,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { aa_points[id] = aa[a]->value; } - if (SPDAT_RECORDS > 0) - { - for (uint32 z = 0; z 0) { + for (uint32 z = 0; z= (uint32)SPDAT_RECORDS) UnmemSpell(z, false); } @@ -5020,7 +5018,8 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app) m_pp.spell_book[swapspell->from_slot] = m_pp.spell_book[swapspell->to_slot]; m_pp.spell_book[swapspell->to_slot] = swapspelltemp; - database.SaveCharacterSpellSwap(this->CharacterID(), swapspelltemp, swapspell->from_slot, swapspell->to_slot); + database.SaveCharacterSpell(this->CharacterID(), m_pp.spell_book[swapspell->from_slot], swapspell->from_slot); + database.SaveCharacterSpell(this->CharacterID(), swapspelltemp, swapspell->to_slot); QueuePacket(app); return; @@ -9573,7 +9572,6 @@ void Client::CompleteConnect() { entity_list.SendUntargetable(this); - client_data_loaded = true; int x; for (x = 0; x < 8; x++) SendWearChange(x); @@ -9659,7 +9657,8 @@ void Client::CompleteConnect() { alternate_currency_loaded = true; ProcessAlternateCurrencyQueue(); - + /* This needs to be set, this determines whether or not data was loaded properly before a save */ + client_data_loaded = true; CalcItemScale(); DoItemEnterZone(); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index bf4c5694b..544200910 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1547,7 +1547,12 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) if (from_bucket == &m_pp.platinum_shared) amount_to_add = 0 - amount_to_take; - database.SetSharedPlatinum(AccountID(),amount_to_add); + database.SetSharedPlatinum(AccountID(),amount_to_add); + } + } + else{ + if (to_bucket == &m_pp.platinum_shared || from_bucket == &m_pp.platinum_shared){ + this->Message(13, "::: WARNING! ::: SHARED BANK IS DISABLED AND YOUR PLATINUM WILL BE DESTROYED IF YOU PUT IT HERE"); } } } diff --git a/zone/command.cpp b/zone/command.cpp index 189f3daf2..c1e304dd1 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2156,8 +2156,8 @@ void command_worldshutdown(Client *c, const Seperator *sep) uint32 interval=0; if (worldserver.Connected()) { if(sep->IsNumber(1) && sep->IsNumber(2) && ((time=atoi(sep->arg[1]))>0) && ((interval=atoi(sep->arg[2]))>0)) { - worldserver.SendEmoteMessage(0,0,15,":SYSTEM MSG:World coming down in %i seconds, everyone log out before this time.",time); - c->Message(0, "Sending shutdown packet now, World will shutdown in: %i Seconds with an interval of: %i",time,interval); + worldserver.SendEmoteMessage(0,0,15,":SYSTEM MSG:World coming down in %i minutes, everyone log out before this time.", (time / 60 )); + c->Message(0, "Sending shutdown packet now, World will shutdown in: %i minutes with an interval of: %i seconds", (time / 60), interval); ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll,sizeof(WorldShutDown_Struct)); WorldShutDown_Struct* wsd = (WorldShutDown_Struct*)pack->pBuffer; wsd->time=time*1000; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 776376bdf..e86e4d601 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -946,7 +946,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { uint16 count; uint16 curspell; - uint16 Char_ID = initiator->CharacterID(); + uint32 Char_ID = initiator->CharacterID(); bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals); bool SpellGlobalCheckResult = 0; @@ -960,7 +960,7 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { spells[curspell].skill != 52 && ( !RuleB(Spells, UseCHAScribeHack) || spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) ) - { + { if(IsDiscipline(curspell)){ //we may want to come up with a function like Client::GetNextAvailableSpellBookSlot() to help speed this up a little for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) { @@ -974,12 +974,12 @@ uint16 QuestManager::traindiscs(uint8 max_level, uint8 min_level) { SpellGlobalCheckResult = initiator->SpellGlobalCheck(curspell, Char_ID); if (SpellGlobalCheckResult) { initiator->GetPP().disciplines.values[r] = curspell; - database.SaveCharacterDisc(Char_ID, r, curspell); + database.SaveCharacterDisc(Char_ID, r, curspell); initiator->SendDisciplineUpdate(); initiator->Message(0, "You have learned a new discipline!"); count++; //success counter } - break; //continue the 1st loop + break; //continue the 1st loop } else { initiator->GetPP().disciplines.values[r] = curspell; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 82b38c44e..d6b59a8c4 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1050,6 +1050,10 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str "`character_spells` " "WHERE `id` = %u ORDER BY `slot_id`", character_id); auto results = database.QueryDatabase(query); int i = 0; + /* Initialize Spells */ + for (i = 0; i < MAX_PP_SPELLBOOK; i++){ + pp->spell_book[i] = 0; + } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); if (i < MAX_PP_SPELLBOOK){ @@ -1241,7 +1245,7 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc } bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp){ - std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z, heading, is_home FROM character_bind WHERE `id` = %u LIMIT 2", character_id); + std::string query = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %u LIMIT 2", character_id); auto results = database.QueryDatabase(query); int i = 0; for (auto row = results.begin(); row != results.end(); ++row) { i = 0; @@ -1274,29 +1278,34 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui } bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home){ + if (zone_id <= 0){ return false; } /* Save Home Bind Point */ std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, x, y, z, heading, is_home); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u x: %f y: %f z: %f heading: %f ishome: %u", character_id, zone_id, instance_id, x, y, z, heading, is_home); auto results = QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterBindPoint", query); return true; } bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){ - std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", character_id, slot_id, color); QueryDatabase(query); + std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", character_id, slot_id, color); auto results = QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterMaterialColor", query); return true; } bool ZoneDatabase::SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value){ - std::string query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, skill_id, value); QueryDatabase(query); + std::string query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, skill_id, value); auto results = QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSkill for character ID: %i, skill_id:%u value:%u done", character_id, skill_id, value); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterSkill", query); return true; } bool ZoneDatabase::SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id){ - std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u value:%u done", character_id, slot_id, disc_id); + std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); auto results = QueryDatabase(query); + LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u done", character_id, slot_id, disc_id); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterDisc", query); return true; } @@ -1317,6 +1326,7 @@ bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_i DoEscapeString(bandolier_name_esc, bandolier_name, strlen(bandolier_name)); std::string query = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%u, %u, %u, %u, %u,'%s')", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name_esc); auto results = QueryDatabase(query); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterBandolier", query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBandolier for character ID: %i, bandolier_id: %u, bandolier_slot: %u item_id: %u, icon:%u band_name:%s done", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } return true; @@ -1325,6 +1335,7 @@ bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_i bool ZoneDatabase::SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon) { std::string query = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%u, %u, %u, %u)", character_id, potion_id, item_id, icon); auto results = QueryDatabase(query); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterPotionBelt", query); if (!results.RowsAffected()){ std::cout << "ERROR Potionbelt Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } return true; } @@ -1540,8 +1551,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla ")", character_id, // " id, " account_id, // " account_id, " - pp->name, // " `name`, " - pp->last_name, // " last_name, " + EscapeString(pp->name).c_str(), // " `name`, " + EscapeString(pp->last_name).c_str(), // " last_name, " pp->gender, // " gender, " pp->race, // " race, " pp->class_, // " class, " @@ -1565,8 +1576,8 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla pp->ability_number, // " ability_number, " pp->ability_time_minutes, // " ability_time_minutes, " pp->ability_time_hours, // " ability_time_hours, " - pp->title, // " title, " - pp->suffix, // " suffix, " + EscapeString(pp->title).c_str(), // " title, " + EscapeString(pp->suffix).c_str(), // " suffix, " pp->exp, // " exp, " pp->points, // " points, " pp->mana, // " mana, " @@ -1633,7 +1644,7 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla m_epp->expended_aa ); auto results = database.QueryDatabase(query); - if (!results.RowsAffected()){ std::cout << "ERROR ZoneDatabase:SaveCharacterData: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } + ThrowDBError(results.ErrorMessage(), "ZoneDatabase:SaveCharacterData", query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } @@ -1675,6 +1686,7 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru pp->currentEbonCrystals, pp->careerEbonCrystals); auto results = database.QueryDatabase(query); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterCurrency", query); LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id); return true; } @@ -1684,19 +1696,11 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur " VALUES (%u, %u, %u)", character_id, aa_id, current_level); auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterAA", rquery); LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %u, aa_id: %u current_level: %u", character_id, aa_id, current_level); return true; } -bool ZoneDatabase::SaveCharacterSpellSwap(uint32 character_id, uint32 spell_id, uint32 from_slot, uint32 to_slot){ - std::string rquery = StringFormat("UPDATE `character_spells` SET `slot_id` = %u WHERE `slot_id` = %u AND `id` = %u", - to_slot, from_slot, character_id); - clock_t t = std::clock(); /* Function timer start */ - auto results = QueryDatabase(rquery); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSpellSwap for character ID: %u, from_slot: %u to_slot: %u spell: %u time: %f seconds", character_id, from_slot, to_slot, spell_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); - return true; -} - bool ZoneDatabase::SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ std::string query = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, slot_id, spell_id); QueryDatabase(query); return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 0405fb3a9..497beb322 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -269,7 +269,6 @@ public: bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); - 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); From 0c38b46bf11d36da91e27480b43eef98476ad1e7 Mon Sep 17 00:00:00 2001 From: akkadius Date: Tue, 9 Sep 2014 16:15:25 -0500 Subject: [PATCH 18/56] Remove namespace std --- common/database.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index e6983b368..bb3a3eab4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -19,9 +19,6 @@ #include "../common/rulesys.h" #include #include - -using namespace std; - #include #include #include From d7dc733480584875a58f53aa42c14cf7e399bddd Mon Sep 17 00:00:00 2001 From: akkadius Date: Thu, 11 Sep 2014 00:44:12 -0500 Subject: [PATCH 19/56] Small db changes --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index bb3a3eab4..4c4d86731 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -306,7 +306,7 @@ bool Database::SetAccountStatus(const char* name, int16 status) { /* This initially creates the character during character create */ bool Database::ReserveName(uint32 account_id, char* name) { std::string query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); - auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::ReserveName", query); + auto results = QueryDatabase(query); if (!results.Success() || results.ErrorMessage() != ""){ return false; } return true; } From e390531dcd24579e9c8e8cf260658dcaa9b36bc0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 11 Sep 2014 03:14:34 -0500 Subject: [PATCH 20/56] Initial character creation escape sequences Added initial skill/language/bind saves to character creation --- common/database.cpp | 53 ++++++++++++++++++++++++++++------ world/client.cpp | 6 ++-- world/worlddb.cpp | 65 +++++++++++++++++++++++++++++++----------- world/worlddb.h | 2 +- zone/client_packet.cpp | 2 +- 5 files changed, 98 insertions(+), 30 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 4c4d86731..cf4fb491d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -573,8 +573,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe ")", character_id, // " id, " account_id, // " account_id, " - pp->name, // " `name`, " - pp->last_name, // " last_name, " + EscapeString(pp->name).c_str(), // " `name`, " + EscapeString(pp->last_name).c_str(), // " last_name, " pp->gender, // " gender, " pp->race, // " race, " pp->class_, // " class, " @@ -598,8 +598,8 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe pp->ability_number, // " ability_number, " pp->ability_time_minutes, // " ability_time_minutes, " pp->ability_time_hours, // " ability_time_hours, " - pp->title, // " title, " - pp->suffix, // " suffix, " + EscapeString(pp->title).c_str(), // " title, " + EscapeString(pp->suffix).c_str(), // " suffix, " pp->exp, // " exp, " pp->points, // " points, " pp->mana, // " mana, " @@ -661,13 +661,50 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe pp->raidAutoconsent, // " raid_auto_consent, " pp->guildAutoconsent, // " guild_auto_consent, " pp->RestTimer // " RestTimer) " - ); + ); auto results = QueryDatabase(query); - ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate", query); + ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Character Data", query); + /* Save Bind Points */ + query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " + "(%u, %u, %u, %f, %f, %f, %f, %i)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 1 + ); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Bind Point", query); + + /* Save Skills */ + int firstquery = 0; + for (int i = 0; i < MAX_PP_SKILL; i++){ + if (pp->skills[i] > 0){ + if (firstquery != 1){ + firstquery = 1; + query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); + } + else{ + query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); + } + } + } + results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Starting Skills", query); + + /* Save Language */ + firstquery = 0; + for (int i = 0; i < MAX_PP_LANGUAGE; i++){ + if (pp->languages[i] > 0){ + if (firstquery != 1){ + firstquery = 1; + query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); + } + else{ + query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); + } + } + } + results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Starting Languages", query); + return true; } - /* This only for new Character creation storing */ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) { uint32 charid = 0; char zone[50]; float x, y, z; @@ -690,7 +727,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven y = pp->y; z = pp->z; - /* Saves Player Profile Data to `character_data` */ + /* Saves Player Profile Data */ SaveCharacterCreate(charid, account_id, pp); /* Insert starting inventory... */ diff --git a/world/client.cpp b/world/client.cpp index e7e999ce5..93e0f782b 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -171,7 +171,7 @@ void Client::SendCharInfo() { EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct)); CharacterSelect_Struct* cs = (CharacterSelect_Struct*)outapp->pBuffer; - database.GetCharSelectInfo(GetAccountID(), cs); + database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit); QueuePacket(outapp); safe_delete(outapp); @@ -699,7 +699,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if(!pZoning && ew->return_home && !ew->tutorial) { CharacterSelect_Struct* cs = new CharacterSelect_Struct; memset(cs, 0, sizeof(CharacterSelect_Struct)); - database.GetCharSelectInfo(GetAccountID(), cs); + database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit); bool home_enabled = false; for(int x = 0; x < 10; ++x) @@ -729,7 +729,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { if(!pZoning && (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial))) { CharacterSelect_Struct* cs = new CharacterSelect_Struct; memset(cs, 0, sizeof(CharacterSelect_Struct)); - database.GetCharSelectInfo(GetAccountID(), cs); + database.GetCharSelectInfo(GetAccountID(), cs, ClientVersionBit); bool tutorial_enabled = false; for(int x = 0; x < 10; ++x) diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 4192e0d84..f26061a5f 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -33,9 +33,11 @@ extern std::vector 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) { +void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs, uint32 ClientVersion) { Inventory *inv; - + uint8 has_home = 0; + uint8 has_bind = 0; + /* Initialize Variables */ for (int i=0; i<10; i++) { strcpy(cs->name[i], ""); @@ -105,24 +107,53 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct* cs->gohome[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. - */ - - /* 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; + /* Set Bind Point Data for any character that may possibly be missing it for any reason */ + cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id); + auto results_bind = database.QueryDatabase(cquery); has_home = 0; has_bind = 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 (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; } + if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; } } + if (has_home == 0 || has_bind == 0){ + cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i", + cs->class_[char_num], cs->deity[char_num], cs->race[char_num]); + auto results_bind = database.QueryDatabase(cquery); + for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) { + /* If a bind_id is specified, make them start there */ + if (atoi(row_d[1]) != 0) { + pp.binds[4].zoneId = (uint32)atoi(row_d[1]); + GetSafePoints(pp.binds[4].zoneId, 0, &pp.binds[4].x, &pp.binds[4].y, &pp.binds[4].z); + } + /* Otherwise, use the zone and coordinates given */ + else { + pp.binds[4].zoneId = (uint32)atoi(row_d[0]); + float x = atof(row_d[2]); + float y = atof(row_d[3]); + float z = atof(row_d[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; + + } + } + pp.binds[0] = pp.binds[4]; + /* If no home bind set, set it */ + if (has_home == 0){ + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", + character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 1); + auto results_bset = QueryDatabase(query); ThrowDBError(results_bset.ErrorMessage(), "WorldDatabase::GetCharSelectInfo Set Home Point", query); + } + /* If no regular bind set, set it */ + if (has_bind == 0){ + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", + character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0); + auto results_bset = QueryDatabase(query); ThrowDBError(results_bset.ErrorMessage(), "WorldDatabase::GetCharSelectInfo Set Bind Point", query); + } + } + /* Bind End */ + /* Character's equipped items @merth: Haven't done bracer01/bracer02 yet. diff --git a/world/worlddb.h b/world/worlddb.h index 24f43d308..ecb39ef61 100644 --- a/world/worlddb.h +++ b/world/worlddb.h @@ -31,7 +31,7 @@ public: bool GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc); bool GetStartZoneSoF(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc); - void GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*); + void GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*, uint32 ClientVersion); int MoveCharacterToBind(int CharID, uint8 bindnum = 0); void GetLauncherList(std::vector &result); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 6865eadfc..755309ef6 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -571,7 +571,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { results = database.QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { m_pp.lastlogin = time(nullptr); - if (atoi(row[4]) > 0){ + if (row[4] && atoi(row[4]) > 0){ guild_id = atoi(row[4]); if (row[5] != nullptr){ guildrank = atoi(row[5]); } else{ guildrank = GUILD_RANK_NONE; } From 87bb5deb5cb84577d58465387321b08530bf4aee Mon Sep 17 00:00:00 2001 From: akkadius Date: Tue, 16 Sep 2014 16:03:27 -0500 Subject: [PATCH 21/56] Added quest::crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var) Added quest::crosszonesignalnpcbynpctypeid(npctype_id, data) Added $client->GetTaskActivityDoneCount(THIS, TaskID, ActivityID) --- common/servertalk.h | 25 +++++++++++++++++++------ world/zoneserver.cpp | 4 +++- zone/client_packet.cpp | 2 +- zone/embparser_api.cpp | 39 ++++++++++++++++++++++++++++++++++++++- zone/perl_client.cpp | 30 ++++++++++++++++++++++++++++++ zone/questmgr.cpp | 23 ++++++++++++++++++++++- zone/questmgr.h | 4 +++- zone/worldserver.cpp | 18 ++++++++++++++++++ 8 files changed, 134 insertions(+), 11 deletions(-) diff --git a/common/servertalk.h b/common/servertalk.h index 5337b6b1d..687abf2d7 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -179,13 +179,15 @@ #define ServerOP_CZMessagePlayer 0x4008 #define ServerOP_ReloadWorld 0x4009 -#define ServerOP_QSPlayerLogTrades 0x4010 -#define ServerOP_QSPlayerLogHandins 0x4011 -#define ServerOP_QSPlayerLogNPCKills 0x4012 -#define ServerOP_QSPlayerLogDeletes 0x4013 -#define ServerOP_QSPlayerLogMoves 0x4014 +#define ServerOP_QSPlayerLogTrades 0x4010 +#define ServerOP_QSPlayerLogHandins 0x4011 +#define ServerOP_QSPlayerLogNPCKills 0x4012 +#define ServerOP_QSPlayerLogDeletes 0x4013 +#define ServerOP_QSPlayerLogMoves 0x4014 #define ServerOP_QSPlayerLogMerchantTransactions 0x4015 -#define ServerOP_QSSendQuery 0x4016 +#define ServerOP_QSSendQuery 0x4016 +#define ServerOP_CZSignalNPC 0x4017 +#define ServerOP_CZSetEntityVariableByNPCTypeID 0x4018 /* Query Serv Generic Packet Flag/Type Enumeration */ enum { QSG_LFGuild = 0 }; @@ -1092,6 +1094,11 @@ struct CZClientSignal_Struct { uint32 data; }; +struct CZNPCSignal_Struct { + uint32 npctype_id; + uint32 data; +}; + struct CZClientSignalByName_Struct { char Name[64]; uint32 data; @@ -1233,6 +1240,12 @@ struct CZMessagePlayer_Struct { char Message[512]; }; +struct CZSetEntVarByNPCTypeID_Struct { + uint32 npctype_id; + char id[256]; + char m_var[256]; +}; + struct ReloadWorld_Struct{ uint32 Option; }; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index c740ff3bc..c05962816 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1266,7 +1266,9 @@ bool ZoneServer::Process() { break; } case ServerOP_CZSignalClientByName: - case ServerOP_CZMessagePlayer: + case ServerOP_CZMessagePlayer: + case ServerOP_CZSignalNPC: + case ServerOP_CZSetEntityVariableByNPCTypeID: case ServerOP_CZSignalClient: { zoneserver_list.SendPacket(pack); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 755309ef6..59d43591e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9435,7 +9435,7 @@ void Client::CompleteConnect() { if (buffs[j1].spellid >(uint32)SPDAT_RECORDS) continue; - const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid]; + const SPDat_Spell_Struct &spell = spells[buffs[j1].spellid]; for (int x1 = 0; x1 < EFFECT_COUNT; x1++) { switch (spell.effectid[x1]) { diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 5adbdedbd..6e337cc03 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3402,6 +3402,41 @@ XS(XS__qs_player_event) XSRETURN_EMPTY; } +XS(XS__crosszonesetentityvariablebynpctypeid); +XS(XS__crosszonesetentityvariablebynpctypeid) +{ + dXSARGS; + + if (items != 3) + Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var)"); + + if (items == 3) { + uint32 npctype_id = (uint32)SvIV(ST(0)); + const char *id = (const char *)SvPV_nolen(ST(1)); + const char *m_var = (const char *)SvPV_nolen(ST(2)); + quest_manager.CrossZoneSetEntityVariableByNPCTypeID(npctype_id, id, m_var); + } + + XSRETURN_EMPTY; +} + +XS(XS__crosszonesignalnpcbynpctypeid); +XS(XS__crosszonesignalnpcbynpctypeid) +{ + dXSARGS; + + if (items != 2) + Perl_croak(aTHX_ "Usage: crosszonesignalnpcbynpctypeid(npctype_id, data)"); + + if (items == 2) { + uint32 npctype_id = (uint32)SvIV(ST(0)); + uint32 data = (uint32)SvIV(ST(1)); + quest_manager.CrossZoneSignalNPCByNPCTypeID(npctype_id, data); + } + + XSRETURN_EMPTY; +} + /* This is the callback perl will look for to setup the quest package's XSUBs @@ -3624,7 +3659,9 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file); newXS(strcpy(buf, "clear_npctype_cache"), XS__clear_npctype_cache, file); newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file); - newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file); + newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file); + newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file); + newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file); XSRETURN_YES; } diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 72e2865c9..03da3bc35 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5072,6 +5072,35 @@ XS(XS_Client_UpdateTaskActivity) XSRETURN_EMPTY; } +XS(XS_Client_GetTaskActivityDoneCount); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTaskActivityDoneCount) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: Client::GetTaskActivityDoneCount(THIS, TaskID, ActivityID)"); + { + Client * THIS; + int RETVAL; + int TaskID = (int)SvIV(ST(1)); + int ActivityID = (int)SvIV(ST(2)); + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *, tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_AssignTask) { @@ -6199,6 +6228,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$"); newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$"); + newXSproto(strcpy(buf, "GetTaskActivityDoneCount"), XS_Client_GetTaskActivityDoneCount, file, "$$$"); newXSproto(strcpy(buf, "GetCorpseCount"), XS_Client_GetCorpseCount, file, "$"); newXSproto(strcpy(buf, "GetCorpseID"), XS_Client_GetCorpseID, file, "$$"); newXSproto(strcpy(buf, "GetCorpseItemAt"), XS_Client_GetCorpseItemAt, file, "$$$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index e86e4d601..e779a5aa7 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2951,6 +2951,15 @@ const char* QuestManager::GetZoneLongName(const char *zone) { return ln.c_str(); } +void QuestManager::CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data){ + ServerPacket* pack = new ServerPacket(ServerOP_CZSignalNPC, sizeof(CZNPCSignal_Struct)); + CZNPCSignal_Struct* CZSN = (CZNPCSignal_Struct*)pack->pBuffer; + CZSN->npctype_id = npctype_id; + CZSN->data = data; + worldserver.SendPacket(pack); + safe_delete(pack); +} + void QuestManager::CrossZoneSignalPlayerByCharID(int charid, uint32 data){ ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClient, sizeof(CZClientSignal_Struct)); CZClientSignal_Struct* CZSC = (CZClientSignal_Struct*) pack->pBuffer; @@ -2968,7 +2977,7 @@ void QuestManager::CrossZoneSignalPlayerByName(const char *CharName, uint32 data CZSC->data = data; worldserver.SendPacket(pack); safe_delete(pack); -} +} void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message){ uint32 message_len = strlen(CharName) + 1; @@ -2978,6 +2987,18 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam CZSC->Type = Type; strn0cpy(CZSC->CharName, CharName, 64); strn0cpy(CZSC->Message, Message, 512); + worldserver.SendPacket(pack); + safe_delete(pack); +} + +void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var){ + uint32 message_len = strlen(id) + 1; + uint32 message_len2 = strlen(m_var) + 1; + ServerPacket* pack = new ServerPacket(ServerOP_CZSetEntityVariableByNPCTypeID, sizeof(CZSetEntVarByNPCTypeID_Struct) + message_len + message_len2); + CZSetEntVarByNPCTypeID_Struct* CZSNBYNID = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer; + CZSNBYNID->npctype_id = npctype_id; + strn0cpy(CZSNBYNID->id, id, 256); + strn0cpy(CZSNBYNID->m_var, m_var, 256); worldserver.SendPacket(pack); safe_delete(pack); } diff --git a/zone/questmgr.h b/zone/questmgr.h index 89a0eca78..2d1184942 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -239,8 +239,10 @@ public: uint16 CreateDoor( const char* model, float x, float y, float z, float heading, uint8 opentype, uint16 size); int32 GetZoneID(const char *zone); const char *GetZoneLongName(const char *zone); - void CrossZoneSignalPlayerByCharID(int charid, uint32 data); + void CrossZoneSignalPlayerByCharID(int charid, uint32 data); + void CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data); void CrossZoneSignalPlayerByName(const char *CharName, uint32 data); + void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var); void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message); bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 152ed4f0d..92d34ff71 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1777,6 +1777,24 @@ void WorldServer::Process() { break; } + case ServerOP_CZSetEntityVariableByNPCTypeID: + { + CZSetEntVarByNPCTypeID_Struct* CZM = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer; + NPC* n = entity_list.GetNPCByNPCTypeID(CZM->npctype_id); + if (n != 0) { + n->SetEntityVariable(CZM->id, CZM->m_var); + } + break; + } + case ServerOP_CZSignalNPC: + { + CZNPCSignal_Struct* CZCN = (CZNPCSignal_Struct*)pack->pBuffer; + NPC* n = entity_list.GetNPCByNPCTypeID(CZCN->npctype_id); + if (n != 0) { + n->SignalNPC(CZCN->data); + } + break; + } case ServerOP_CZSignalClient: { CZClientSignal_Struct* CZCS = (CZClientSignal_Struct*) pack->pBuffer; From eb497077794afbf0c460cfa21331450260980873 Mon Sep 17 00:00:00 2001 From: akkadius Date: Wed, 17 Sep 2014 02:47:13 -0500 Subject: [PATCH 22/56] Changed conversion routine. At the end of conversion, character_ table will be renamed to character_old so that it does not get hit with trying to convert next world bootup Added some file logging during the initial conversion routine --- common/database.cpp | 91 ++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index cf4fb491d..c38b108f4 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -315,9 +315,9 @@ bool Database::ThrowDBError(std::string ErrorMessage, std::string query_title, s if (ErrorMessage != ""){ std::cout << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n" << std::endl; - /* Write to file temporarily */ + /* Write to log file */ std::ofstream log("eqemu_query_error_log.txt", std::ios_base::app | std::ios_base::out); - log << "\nERROR " << query_title << ": " << ErrorMessage << "\n\n" << query << "\n"; + log << "ERROR " << query_title << ": " << ErrorMessage << "\n" << query << "\n"; log.close(); return true; @@ -1025,7 +1025,8 @@ bool Database::CheckDatabaseConversions() { "KEY `account_id` (`account_id`) " ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_currency` */ @@ -1056,7 +1057,8 @@ bool Database::CheckDatabaseConversions() { " KEY `id` (`id`) " " ) ENGINE=InnoDB DEFAULT CHARSET=latin1; " ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_alternate_abilities` */ @@ -1074,7 +1076,8 @@ bool Database::CheckDatabaseConversions() { " KEY `id` (`id`) " " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_bind` */ @@ -1096,7 +1099,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_languages` */ @@ -1113,7 +1117,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_skills` */ @@ -1130,7 +1135,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_spells` */ @@ -1147,7 +1153,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_memmed_spells` */ @@ -1164,7 +1171,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_disciplines` */ @@ -1181,7 +1189,8 @@ bool Database::CheckDatabaseConversions() { " KEY `id` (`id`) " " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_material` */ @@ -1202,7 +1211,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`)" ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_tribute` */ @@ -1218,7 +1228,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_bandolier` */ @@ -1238,7 +1249,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_potionbelt` */ @@ -1256,7 +1268,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_potionbelt` */ @@ -1272,7 +1285,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } /* Check for table `character_leadership_abilities` */ @@ -1289,7 +1303,8 @@ bool Database::CheckDatabaseConversions() { "KEY `id` (`id`) " ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); - QueryDatabase(rquery); + auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); printf(" done...\n"); } @@ -1356,7 +1371,7 @@ bool Database::CheckDatabaseConversions() { EscapeString(inspectmessage).c_str() ); auto results = QueryDatabase(rquery); - if (!results.RowsAffected()){ std::cout << "ERROR Inspect Messages Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + ThrowDBError(results.ErrorMessage(), "Character Inspect Message Convert", rquery); } /* Run Currency Convert */ @@ -1384,6 +1399,7 @@ bool Database::CheckDatabaseConversions() { pp->careerEbonCrystals ); auto results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Character Currency Convert", rquery); if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } @@ -1688,8 +1704,9 @@ bool Database::CheckDatabaseConversions() { e_pp->perAA, e_pp->expended_aa ); - results = QueryDatabase(rquery); - if (!results.RowsAffected()){ std::cout << "ERROR PP Data Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + results = QueryDatabase(rquery); + ThrowDBError(results.ErrorMessage(), "Character Data Convert", rquery); + /* We set a first entry variable because we need the first initial piece of the query to be declared @@ -1708,19 +1725,19 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } - + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error AA Convert", rquery); } + /* Run Bind Home Convert */ rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Bind Home Convert", rquery); } /* Run Bind Convert */ rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Bind Convert", rquery); } /* Run Language Convert */ first_entry = 0; rquery = ""; @@ -1733,7 +1750,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Language Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Language Convert", rquery); } /* Run Skill Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_SKILL; i++){ @@ -1745,7 +1762,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Skill Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Skills Convert Convert", rquery); } /* Run Spell Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ @@ -1758,7 +1775,7 @@ bool Database::CheckDatabaseConversions() { } } // std::cout << rquery << "\n"; - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Spell Convert", rquery); } /* Run Max Memmed Spell Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ @@ -1770,7 +1787,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Memmed Spell Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Memmed Spells Convert", rquery); } /* Run Discipline Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_DISCIPLINES; i++){ @@ -1782,7 +1799,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Discipline Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Discipline Convert", rquery); } /* Run Material Color Convert */ first_entry = 0; rquery = ""; for (i = 0; i < _MaterialCount; i++){ @@ -1794,7 +1811,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%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); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Color Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Material Convert", rquery); } /* Run Tribute Convert */ first_entry = 0; rquery = ""; for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ @@ -1806,7 +1823,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Tribute Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Tribute Convert", rquery); } /* Run Bandolier Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ @@ -1820,7 +1837,7 @@ bool Database::CheckDatabaseConversions() { } } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Bandolier Convert", rquery); } /* Run Potion Belt Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ @@ -1833,7 +1850,7 @@ bool Database::CheckDatabaseConversions() { } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Potion Belt Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Potion Belt Convert", rquery); } /* Run Leadership AA Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ @@ -1845,10 +1862,14 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); } if (!results.RowsAffected()){ std::cout << "ERROR Leadership AA Convert: " << results.ErrorMessage() << "\n\n" << rquery << "\n" << std::endl; } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Leadership AA Convert", rquery); } } } - if (runconvert == 1){ printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); } + if (runconvert == 1){ + std::string rquery = StringFormat("RENAME TABLE `character_` TO `character_old`"); QueryDatabase(rquery); + printf("\n\nRenaming `character_` table to `character_old`, this is a LARGE table so when you don't need it anymore, I would suggest deleting it yourself...\n"); + printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); + } return true; } From f30ae9dd5ae8a63f3b569603f65bc69f1e75128d Mon Sep 17 00:00:00 2001 From: akkadius Date: Wed, 17 Sep 2014 02:52:13 -0500 Subject: [PATCH 23/56] Some descriptor adjustments --- common/database.cpp | 58 ++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index c38b108f4..c44c32157 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1026,7 +1026,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_currency` */ @@ -1058,7 +1058,7 @@ bool Database::CheckDatabaseConversions() { " ) ENGINE=InnoDB DEFAULT CHARSET=latin1; " ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_alternate_abilities` */ @@ -1077,7 +1077,7 @@ bool Database::CheckDatabaseConversions() { " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_bind` */ @@ -1100,7 +1100,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_languages` */ @@ -1118,7 +1118,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_skills` */ @@ -1136,7 +1136,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_spells` */ @@ -1154,7 +1154,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_memmed_spells` */ @@ -1172,7 +1172,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_disciplines` */ @@ -1190,7 +1190,7 @@ bool Database::CheckDatabaseConversions() { " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_material` */ @@ -1212,7 +1212,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_tribute` */ @@ -1229,7 +1229,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_bandolier` */ @@ -1250,7 +1250,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_potionbelt` */ @@ -1269,7 +1269,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_potionbelt` */ @@ -1286,7 +1286,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } /* Check for table `character_leadership_abilities` */ @@ -1304,7 +1304,7 @@ bool Database::CheckDatabaseConversions() { ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " ); auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", rquery); + ThrowDBError(results.ErrorMessage(), "Table create", rquery); printf(" done...\n"); } @@ -1325,7 +1325,7 @@ bool Database::CheckDatabaseConversions() { std::string inspectmessage; for (auto row = results.begin(); row != results.end(); ++row) { - char_iter_count++; + char_iter_count++; squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", atoi(row[0])); auto results2 = QueryDatabase(squery); auto row2 = results2.begin(); @@ -1725,19 +1725,19 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error AA Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "AA Convert", rquery); } /* Run Bind Home Convert */ rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Bind Home Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Bind Home Convert", rquery); } /* Run Bind Convert */ rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Bind Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bind Convert", rquery); } /* Run Language Convert */ first_entry = 0; rquery = ""; @@ -1750,7 +1750,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Language Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Language Convert", rquery); } /* Run Skill Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_SKILL; i++){ @@ -1762,7 +1762,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Skills Convert Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Skills Convert Convert", rquery); } /* Run Spell Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ @@ -1775,7 +1775,7 @@ bool Database::CheckDatabaseConversions() { } } // std::cout << rquery << "\n"; - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Spell Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Spell Convert", rquery); } /* Run Max Memmed Spell Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ @@ -1787,7 +1787,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Memmed Spells Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Memmed Spells Convert", rquery); } /* Run Discipline Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_DISCIPLINES; i++){ @@ -1799,7 +1799,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Discipline Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Discipline Convert", rquery); } /* Run Material Color Convert */ first_entry = 0; rquery = ""; for (i = 0; i < _MaterialCount; i++){ @@ -1811,7 +1811,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%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); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Material Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Material Convert", rquery); } /* Run Tribute Convert */ first_entry = 0; rquery = ""; for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ @@ -1823,7 +1823,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Tribute Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Tribute Convert", rquery); } /* Run Bandolier Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ @@ -1837,7 +1837,7 @@ bool Database::CheckDatabaseConversions() { } } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Bandolier Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bandolier Convert", rquery); } /* Run Potion Belt Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ @@ -1850,7 +1850,7 @@ bool Database::CheckDatabaseConversions() { } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Potion Belt Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Potion Belt Convert", rquery); } /* Run Leadership AA Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ @@ -1862,7 +1862,7 @@ bool Database::CheckDatabaseConversions() { rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); } } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Error Character Leadership AA Convert", rquery); } + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Leadership AA Convert", rquery); } } } if (runconvert == 1){ From 81722962cf672c917b70e1c00384539d2804679e Mon Sep 17 00:00:00 2001 From: akkadius Date: Wed, 17 Sep 2014 14:30:19 -0500 Subject: [PATCH 24/56] KLS Nazi Grammar Fix --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index c44c32157..a3a279af5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -896,7 +896,7 @@ bool Database::CheckDatabaseConversions() { printf(" Database currently has character data being stored via \n"); printf(" the legacy character storage method and will proceed with converting...\n\n"); printf(" It is recommended that you backup your database \n"); - printf(" before continuing the automatic conversion proces...\n\n"); + printf(" before continuing the automatic conversion process...\n\n"); printf("----------------------------------------------------------\n\n"); std::cout << "Press ENTER to continue....." << std::endl << std::endl; std::cin.ignore(1); From 6754dfdf6d7ca4094de30769903a9a673633b1ed Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 17 Sep 2014 17:45:40 -0700 Subject: [PATCH 25/56] Small sanity checks that was causing a few errors --- common/database.cpp | 50 +++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index c44c32157..006242b89 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include // Disgrace: for windows compile @@ -1345,10 +1346,12 @@ bool Database::CheckDatabaseConversions() { lengths = results2.LengthOfColumn(1); if (lengths == sizeof(PlayerProfile_Struct)) { /* If PP is the size it is expected to be */ memcpy(pp, row2[1], sizeof(PlayerProfile_Struct)); - // std::cout << "SIZE OK\n" << std::endl; } /* Continue of PP Size does not match (Usually a created character never logged in) */ - else { continue; } + else { + printf("\nCharacter %s(%u) was missing profile data, character not converted.", row2[2] ? row2[2] : "Unknown", character_id); + continue; + } lengths_e = results2.LengthOfColumn(11); if (lengths_e == sizeof(ExtendedProfile_Struct)) { @@ -1356,8 +1359,6 @@ bool Database::CheckDatabaseConversions() { } if (e_pp->expended_aa > 4000000){ e_pp->expended_aa = 0; } - // std::cout << "Expended AA: " << e_pp->expended_aa << "\n" << std::endl; - /* Loading Status on conversion */ if (runconvert == 1){ std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; @@ -1663,7 +1664,7 @@ bool Database::CheckDatabaseConversions() { pp->ability_up, pp->zone_id, pp->zoneInstance, - pp->leadAAActive, + pp->leadAAActive == 0 ? 0 : 1, pp->ldon_points_guk, pp->ldon_points_mir, pp->ldon_points_mmc, @@ -1728,17 +1729,20 @@ bool Database::CheckDatabaseConversions() { if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "AA Convert", rquery); } /* Run Bind Home Convert */ - rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", - character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Bind Home Convert", rquery); } + if(pp->binds[4].zoneId < 999 && !std::isnan(pp->binds[4].x) && !std::isnan(pp->binds[4].y) && !std::isnan(pp->binds[4].z) && !std::isnan(pp->binds[4].heading)) { + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Bind Home Convert", rquery); } + } /* Run Bind Convert */ - rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", - character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bind Convert", rquery); } - + if(pp->binds[0].zoneId < 999 && !std::isnan(pp->binds[0].x) && !std::isnan(pp->binds[0].y) && !std::isnan(pp->binds[0].z) && !std::isnan(pp->binds[0].heading)) { + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); + if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bind Convert", rquery); } + } /* Run Language Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_LANGUAGE; i++){ @@ -1791,7 +1795,7 @@ bool Database::CheckDatabaseConversions() { /* Run Discipline Convert */ first_entry = 0; rquery = ""; for (i = 0; i < MAX_PP_DISCIPLINES; i++){ - if (pp->disciplines.values[i] > 0){ + if(pp->disciplines.values[i] > 0 && pp->disciplines.values[i] < 60000){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); first_entry = 1; @@ -1827,13 +1831,15 @@ bool Database::CheckDatabaseConversions() { /* Run Bandolier Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ - for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ - if (pp->bandoliers[i].items[si].item_id > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); - first_entry = 1; + if(strlen(pp->bandoliers[i].name) < 32) { + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + if (pp->bandoliers[i].items[si].item_id > 0){ + if (first_entry != 1) { + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); } - rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); } } } @@ -1854,7 +1860,7 @@ bool Database::CheckDatabaseConversions() { /* Run Leadership AA Convert */ first_entry = 0; rquery = ""; for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ - if (pp->leader_abilities.ranks[i] > 0){ + if(pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); first_entry = 1; From 64f5bfd5ceb0220995ab8d2821048285eb4f8c0c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 Sep 2014 23:46:54 -0400 Subject: [PATCH 26/56] Make tell message a bit more understandable. --- world/zoneserver.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 7c4f4f963..dbfb98fee 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -437,13 +437,13 @@ bool ZoneServer::Process() { Console* con = 0; con = console_list.FindByAccountName(&scm->deliverto[1]); if (((!con) || (!con->SendChannelMessage(scm))) && (!scm->noreply)) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); break; } ClientListEntry* cle = client_list.FindCharacter(scm->deliverto); if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { if (!scm->noreply) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); } else if (cle->Online() == CLE_Status_Zoning) { if (!scm->noreply) @@ -460,7 +460,7 @@ bool ZoneServer::Process() { break; if (results.RowCount() == 0) { - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); break; } @@ -470,9 +470,9 @@ bool ZoneServer::Process() { telldate, scm->deliverto, scm->from, scm->message); results = database.QueryDatabase(query); if (results.Success()) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to the %s's que.", scm->to); + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to %s's queue.", scm->to); else - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to, scm->to); } // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); From 347ae1bc341e6f3f44b778e7a724f3f237dd08e4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 Sep 2014 01:29:30 -0400 Subject: [PATCH 27/56] Fix error in 64f5bfd --- world/zoneserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index dbfb98fee..870bd2447 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -472,7 +472,7 @@ bool ZoneServer::Process() { if (results.Success()) zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to %s's queue.", scm->to); else - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to, scm->to); + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); } // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); From 3d6bb964df6156116d2025f088387e27c76a2bbb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 Sep 2014 14:59:50 -0400 Subject: [PATCH 28/56] Stop nuking MySQLRequestResult Success flag --- common/mysql_request_result.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/mysql_request_result.cpp b/common/mysql_request_result.cpp index ffbc3ef40..d2a3afd65 100644 --- a/common/mysql_request_result.cpp +++ b/common/mysql_request_result.cpp @@ -10,7 +10,7 @@ MySQLRequestResult::MySQLRequestResult() MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer) : m_CurrentRow(result), m_OneBeyondRow() { - m_Result = result; + m_Result = result; m_RowsAffected = rowsAffected; m_RowCount = rowCount; m_ColumnCount = columnCount; @@ -22,12 +22,12 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u m_ColumnLengths = nullptr; m_Fields = nullptr; - if (errorBuffer != nullptr) + m_Success = true; + if (errorBuffer != nullptr) m_Success = false; - m_Success = true; - m_ErrorNumber = errorNumber; - m_ErrorBuffer = errorBuffer; + m_ErrorNumber = errorNumber; + m_ErrorBuffer = errorBuffer; } void MySQLRequestResult::FreeInternals() From a2368b4ea763ccb24f62ccec2342f6607dbfe7d1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 Sep 2014 22:55:06 -0400 Subject: [PATCH 29/56] Implement tell queues Default queue size 20 (World:TellQueueSize) This doe not play well with multiple sessions and a toon crashes and relogs Normal tells have issues as well. --- changelog.txt | 7 +++ common/ruletypes.h | 1 + common/servertalk.h | 5 ++ .../git/optional/2014_09_18_TellQueueRule.sql | 1 + .../required/2014_09_18_tellqueuesclean.sql | 1 + world/cliententry.cpp | 20 ++++++ world/cliententry.h | 10 +++ world/zoneserver.cpp | 62 +++++++++---------- zone/client_packet.cpp | 2 + zone/worldserver.cpp | 16 +++++ zone/worldserver.h | 2 + 11 files changed, 94 insertions(+), 33 deletions(-) create mode 100644 utils/sql/git/optional/2014_09_18_TellQueueRule.sql create mode 100644 utils/sql/git/required/2014_09_18_tellqueuesclean.sql diff --git a/changelog.txt b/changelog.txt index a006c9a50..b4384d55b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/18/2014== +demonstar55: Implement tell queues + Currently set to a limit of 20 by default (World:TellQueueSize) I was unable to hit the limit on live though (100+) + The required SQL nukes the old tell queue table, which may or may not be in your DB + Optional SQL adds the rule to the DB to allow easy of change + Note: this does not play well with multiple sessions with the same name on (crash and relog and have multiple sessions) but normal tells don't play well either + == 09/16/2014 == demonstar55: Implement spell formula 137 (BER AA Desperation) Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded. diff --git a/common/ruletypes.h b/common/ruletypes.h index c61590ac4..95fa19854 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -171,6 +171,7 @@ RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = R RULE_BOOL (World, IsGMPetitionWindowEnabled, false) RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items. RULE_BOOL (World, IPLimitDisconnectAll, false) +RULE_INT (World, TellQueueSize, 20) RULE_CATEGORY_END() RULE_CATEGORY( Zone ) diff --git a/common/servertalk.h b/common/servertalk.h index 5337b6b1d..03771eeef 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -83,6 +83,7 @@ #define ServerOP_QGlobalUpdate 0x0063 #define ServerOP_QGlobalDelete 0x0064 #define ServerOP_DepopPlayerCorpse 0x0065 +#define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues #define ServerOP_RaidAdd 0x0100 //in use #define ServerOP_RaidRemove 0x0101 //in use @@ -1237,6 +1238,10 @@ struct ReloadWorld_Struct{ uint32 Option; }; +struct ServerRequestTellQueue_Struct { + char name[64]; +}; + #pragma pack() #endif diff --git a/utils/sql/git/optional/2014_09_18_TellQueueRule.sql b/utils/sql/git/optional/2014_09_18_TellQueueRule.sql new file mode 100644 index 000000000..2a9b43611 --- /dev/null +++ b/utils/sql/git/optional/2014_09_18_TellQueueRule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'World:TellQueueSize', '20', 'Maximum tell queue size.'); diff --git a/utils/sql/git/required/2014_09_18_tellqueuesclean.sql b/utils/sql/git/required/2014_09_18_tellqueuesclean.sql new file mode 100644 index 000000000..04d9b38d1 --- /dev/null +++ b/utils/sql/git/required/2014_09_18_tellqueuesclean.sql @@ -0,0 +1 @@ +DROP TABLE `tellque`; diff --git a/world/cliententry.cpp b/world/cliententry.cpp index d4b85acc3..fa5b60c43 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -93,6 +93,7 @@ ClientListEntry::~ClientListEntry() { Camp(); // updates zoneserver's numplayers client_list.RemoveCLEReferances(this); } + tell_queue.clear(); } void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) { @@ -233,6 +234,7 @@ void ClientListEntry::ClearVars(bool iAll) { pLFG = 0; gm = 0; pClientVersion = 0; + tell_queue.clear(); } void ClientListEntry::Camp(ZoneServer* iZS) { @@ -295,3 +297,21 @@ bool ClientListEntry::CheckAuth(uint32 id, const char* iKey, uint32 ip) { return false; } +void ClientListEntry::ProcessTellQueue() +{ + if (!Server()) + return; + + ServerPacket *pack; + auto it = tell_queue.begin(); + while (it != tell_queue.end()) { + pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1); + memcpy(pack->pBuffer, *it, pack->size); + pack->Deflate(); + Server()->SendPacket(pack); + safe_delete(pack); + it = tell_queue.erase(it); + } + return; +} + diff --git a/world/cliententry.h b/world/cliententry.h index dcf79ca4f..cb096950c 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -5,6 +5,8 @@ #include "../common/md5.h" //#include "../common/eq_packet_structs.h" #include "../common/servertalk.h" +#include "../common/rulesys.h" +#include #define CLE_Status_Never -1 @@ -80,6 +82,11 @@ public: inline const char* GetLFGComments() const { return pLFGComments; } inline uint8 GetClientVersion() { return pClientVersion; } + inline bool TellQueueFull() const { return tell_queue.size() >= RuleI(World, TellQueueSize); } + inline bool TellQueueEmpty() const { return tell_queue.empty(); } + inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); } + void ProcessTellQueue(); + private: void ClearVars(bool iAll = false); @@ -120,6 +127,9 @@ private: uint8 pLFGToLevel; bool pLFGMatchFilter; char pLFGComments[64]; + + // Tell Queue -- really a vector :D + std::vector tell_queue; }; #endif /*CLIENTENTRY_H_*/ diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 870bd2447..211d6f088 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -441,41 +441,27 @@ bool ZoneServer::Process() { break; } ClientListEntry* cle = client_list.FindCharacter(scm->deliverto); - if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { + if (cle == 0 || cle->Online() < CLE_Status_Zoning || + (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { if (!scm->noreply) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); - } - else if (cle->Online() == CLE_Status_Zoning) { - if (!scm->noreply) - { - time_t rawtime; - struct tm * timeinfo; - time ( &rawtime ); - timeinfo = localtime ( &rawtime ); - char *telldate=asctime(timeinfo); - - std::string query = StringFormat("SELECT name FROM character_ WHERE name = '%s'",scm->deliverto); - auto results = database.QueryDatabase(query); - if (!results.Success()) - break; - - if (results.RowCount() == 0) { - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); - break; - } - - query = StringFormat("INSERT INTO tellque " - "(Date, Receiver, Sender, Message) " - "VALUES('%s', '%s', '%s', '%s')", - telldate, scm->deliverto, scm->from, scm->message); - results = database.QueryDatabase(query); - if (results.Success()) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to %s's queue.", scm->to); - else - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); - + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, + "%s is not online at this time.", scm->to); + } else if (cle->Online() == CLE_Status_Zoning) { + if (!scm->noreply) { + if (cle->TellQueueFull()) { + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, + "%s's tell queue is full.", scm->to); + } else { + size_t struct_size = sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1; + ServerChannelMessage_Struct *temp = (ServerChannelMessage_Struct *) new uchar[struct_size]; + memset(temp, 0, struct_size); // just in case, was seeing some corrupt messages, but it shouldn't happen + memcpy(temp, scm, struct_size); + temp->noreply = true; + cle->PushToTellQueue(temp); // deallocation is handled in processing or deconstructor + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, + "Your message has been added to %s's queue.", scm->to); + } } - // zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to); } else if (cle->Server() == 0) { if (!scm->noreply) @@ -1319,6 +1305,16 @@ bool ZoneServer::Process() { zoneserver_list.SendPacket(pack); break; } + case ServerOP_RequestTellQueue: + { + ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer; + ClientListEntry *cle = client_list.FindCharacter(rtq->name); + if (!cle || cle->TellQueueEmpty()) + break; + + cle->ProcessTellQueue(); + break; + } default: { zlog(WORLD__ZONE_ERR,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 261615169..1c98a538f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9834,6 +9834,8 @@ void Client::CompleteConnect() { } entity_list.RefreshClientXTargets(this); + + worldserver.RequestTellQueue(GetName()); } void Client::Handle_OP_KeyRing(const EQApplicationPacket *app) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 791a34ee4..be14e7b93 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -2180,3 +2180,19 @@ void WorldServer::HandleLFPMatches(ServerPacket *pack) { safe_delete(outapp); } } + +void WorldServer::RequestTellQueue(const char *who) +{ + if (!who) + return; + + ServerPacket* pack = new ServerPacket(ServerOP_RequestTellQueue, sizeof(ServerRequestTellQueue_Struct)); + ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer; + + strn0cpy(rtq->name, who, sizeof(rtq->name)); + + SendPacket(pack); + safe_delete(pack); + return; +} + diff --git a/zone/worldserver.h b/zone/worldserver.h index 3c2e03fa6..6feead496 100644 --- a/zone/worldserver.h +++ b/zone/worldserver.h @@ -57,6 +57,8 @@ public: void HandleLFGMatches(ServerPacket *pack); void HandleLFPMatches(ServerPacket *pack); + void RequestTellQueue(const char *who); + private: virtual void OnConnected(); From d26782b0934925f36499594d34a697da1a87917a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 Sep 2014 22:56:16 -0400 Subject: [PATCH 30/56] Nuke #viewmessages --- zone/command.cpp | 49 ------------------------------------------------ zone/command.h | 1 - 2 files changed, 50 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index cf180f2bd..b2f08d3eb 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -333,8 +333,6 @@ int command_init(void) { command_add("guilds",nullptr,0,command_guild) || command_add("zonestatus","- Show connected zoneservers, synonymous with /servers",150,command_zonestatus) || command_add("manaburn","- Use AA Wizard class skill manaburn on target",10,command_manaburn) || - command_add("viewmessage","[id] - View messages in your tell queue",100,command_viewmessage) || - command_add("viewmessages",nullptr,0,command_viewmessage) || command_add("doanim","[animnum] [type] - Send an EmoteAnim for you or your target",50,command_doanim) || command_add("randomfeatures","- Temporarily randomizes the Facial Features of your target",80,command_randomfeatures) || command_add("rf",nullptr,80,command_randomfeatures) || @@ -5294,53 +5292,6 @@ void command_manaburn(Client *c, const Seperator *sep) } } -void command_viewmessage(Client *c, const Seperator *sep) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if(sep->arg[1][0]==0) - { - if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT id,date,receiver,sender,message from tellque where receiver='%s'",c->GetName()), errbuf, &result)) - { - if (mysql_num_rows(result)>0) - { - c->Message(0,"You have messages waiting for you to view."); - c->Message(0,"Type #Viewmessage to view the message."); - c->Message(0," ID , Message Sent Date, Message Sender"); - while ((row = mysql_fetch_row(result))) - c->Message(0,"ID: %s Sent Date: %s Sender: %s ",row[0],row[1],row[3]); - } - else - c->Message(0,"You have no new messages"); - mysql_free_result(result); - } - safe_delete_array(query); - } - else - { - if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT id,date,receiver,sender,message from tellque where id=%s",sep->argplus[1]), errbuf, &result)) - { - if (mysql_num_rows(result)==1) - { - row = mysql_fetch_row(result); - mysql_free_result(result); - if (strcasecmp((const char *) c->GetName(), (const char *) row[2]) == 0) - { - c->Message(15,"ID: %s,Sent Date: %s,Sender: %s,Message: %s",row[0],row[1],row[3],row[4]); - database.RunQuery(query, MakeAnyLenString(&query, "Delete from tellque where id=%s",row[0]), errbuf); - } - else - c->Message(13,"Invalid Message Number, check the number and try again."); - } - else - c->Message(13,"Invalid Message Number, check the number and try again."); - } - safe_delete_array(query); - } -} - void command_doanim(Client *c, const Seperator *sep) { if (!sep->IsNumber(1)) diff --git a/zone/command.h b/zone/command.h index 4846dd09d..9be88bbe7 100644 --- a/zone/command.h +++ b/zone/command.h @@ -217,7 +217,6 @@ void command_guild(Client *c, const Seperator *sep); bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value); void command_zonestatus(Client *c, const Seperator *sep); void command_manaburn(Client *c, const Seperator *sep); -void command_viewmessage(Client *c, const Seperator *sep); void command_doanim(Client *c, const Seperator *sep); void command_randomfeatures(Client *c, const Seperator *sep); void command_face(Client *c, const Seperator *sep); From 52608d9b2dbbc5e069e3b2a6e3bea4874788569f Mon Sep 17 00:00:00 2001 From: akkadius Date: Thu, 18 Sep 2014 22:46:28 -0500 Subject: [PATCH 31/56] Character armor dye save fix --- zone/zonedb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7ebf6f084..4878b6644 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1217,7 +1217,11 @@ bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, u } bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color){ - std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, color, use_tint) VALUES (%u, %u, %u, 255)", character_id, slot_id, color); auto results = QueryDatabase(query); + uint8 red = (color & 0x00FF0000) >> 16; + uint8 green = (color & 0x0000FF00) >> 8; + uint8 blue = (color & 0x000000FF); + + std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, red, green, blue, color, use_tint) VALUES (%u, %u, %u, %u, %u, %u, 255)", character_id, slot_id, red, green, blue, color); auto results = QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterMaterialColor", query); return true; From 8e43134bdafa1b44a1238036a644621d8eb0992c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 19 Sep 2014 18:16:52 -0400 Subject: [PATCH 32/56] Add Client::Tell_StringID for tell queue messages --- changelog.txt | 3 +++ zone/client.cpp | 8 ++++++++ zone/client.h | 1 + zone/string_ids.h | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/changelog.txt b/changelog.txt index b4384d55b..5a00e90f0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/19/2014 == +demonstar55: Added Client::Tell_StringID (used in tell queue messages) + == 09/18/2014== demonstar55: Implement tell queues Currently set to a limit of 20 by default (World:TellQueueSize) I was unable to hit the limit on live though (100+) diff --git a/zone/client.cpp b/zone/client.cpp index 345bec4ca..f3d550fd2 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3134,6 +3134,14 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil safe_delete(outapp); } +void Client::Tell_StringID(uint32 string_id, const char *who, const char *message) +{ + char string_id_str[10]; + snprintf(string_id_str, 10, "%d", string_id); + + Message_StringID(MT_TellEcho, TELL_QUEUED_MESSAGE, who, string_id_str, message); +} + void Client::SetTint(int16 in_slot, uint32 color) { Color_Struct new_color; new_color.color = color; diff --git a/zone/client.h b/zone/client.h index 697e4e2d3..430216900 100644 --- a/zone/client.h +++ b/zone/client.h @@ -260,6 +260,7 @@ public: const char *message5 = nullptr, const char *message6 = nullptr, const char *message7 = nullptr, const char *message8 = nullptr, const char *message9 = nullptr); + void Tell_StringID(uint32 string_id, const char *who, const char *message); void SendBazaarResults(uint32 trader_id,uint32 class_,uint32 race,uint32 stat,uint32 slot,uint32 type,char name[64],uint32 minprice,uint32 maxprice); void SendTraderItem(uint32 item_id,uint16 quantity); uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity); diff --git a/zone/string_ids.h b/zone/string_ids.h index 056513874..a443fabd9 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -249,6 +249,8 @@ #define PLAYER_CHARMED 1461 //You lose control of yourself! #define TRADER_BUSY 1468 //That Trader is currently with a customer. Please wait until their transaction is finished. #define SENSE_CORPSE_DIRECTION 1563 //You sense a corpse in this direction. +#define QUEUED_TELL 2458 //[queued] +#define QUEUE_TELL_FULL 2459 //[zoing and queue is full] #define SUSPEND_MINION_UNSUSPEND 3267 //%1 tells you, 'I live again...' #define SUSPEND_MINION_SUSPEND 3268 //%1 tells you, 'By your command, master.' #define ONLY_SUMMONED_PETS 3269 //3269 This effect only works with summoned pets. @@ -269,6 +271,8 @@ #define CORPSEDRAG_STOP 4066 //You stop dragging the corpse. #define TARGET_TOO_CLOSE 4602 //You are too close to your target. Get farther away. #define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters. +#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3' +#define TOLD_NOT_ONLINE 5046 //%1 is not online at this time. #define PETITION_NO_DELETE 5053 //You do not have a petition in the queue. #define PETITION_DELETED 5054 //Your petition was successfully deleted. #define GAIN_RAIDEXP 5085 //You gained raid experience! From 9b70b73759f464cdffc73868ef277643efd28bf3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 19 Sep 2014 18:17:42 -0400 Subject: [PATCH 33/56] Correct tell queue related messages --- changelog.txt | 1 + common/servertalk.h | 1 + world/zoneserver.cpp | 31 ++++++++++++++++++++++++------- zone/worldserver.cpp | 23 +++++++++++++++-------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5a00e90f0..493e57152 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 09/19/2014 == demonstar55: Added Client::Tell_StringID (used in tell queue messages) +demonstar55: Tell queues (and offline) messages now show correctly == 09/18/2014== demonstar55: Implement tell queues diff --git a/common/servertalk.h b/common/servertalk.h index 03771eeef..a649fe434 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -347,6 +347,7 @@ struct ServerChannelMessage_Struct { uint16 chan_num; uint32 guilddbid; uint16 language; + uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline char message[0]; }; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 211d6f088..8f37e15a6 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -443,14 +443,26 @@ bool ZoneServer::Process() { ClientListEntry* cle = client_list.FindCharacter(scm->deliverto); if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { - if (!scm->noreply) - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, - "%s is not online at this time.", scm->to); + if (!scm->noreply) { + ClientListEntry* sender = client_list.FindCharacter(scm->from); + if (!sender) + break; + scm->noreply = true; + scm->queued = 3; // offline + strcpy(scm->deliverto, scm->from); + // ideally this would be trimming off the message too, oh well + sender->Server()->SendPacket(pack); + } } else if (cle->Online() == CLE_Status_Zoning) { if (!scm->noreply) { + ClientListEntry* sender = client_list.FindCharacter(scm->from); if (cle->TellQueueFull()) { - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, - "%s's tell queue is full.", scm->to); + if (!sender) + break; + scm->noreply = true; + scm->queued = 2; // queue full + strcpy(scm->deliverto, scm->from); + sender->Server()->SendPacket(pack); } else { size_t struct_size = sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1; ServerChannelMessage_Struct *temp = (ServerChannelMessage_Struct *) new uchar[struct_size]; @@ -458,8 +470,13 @@ bool ZoneServer::Process() { memcpy(temp, scm, struct_size); temp->noreply = true; cle->PushToTellQueue(temp); // deallocation is handled in processing or deconstructor - zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, - "Your message has been added to %s's queue.", scm->to); + + if (!sender) + break; + scm->noreply = true; + scm->queued = 1; // queued + strcpy(scm->deliverto, scm->from); + sender->Server()->SendPacket(pack); } } } diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index be14e7b93..c54c2e886 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -168,18 +168,24 @@ void WorldServer::Process() { break; } case ServerOP_ChannelMessage: { - if (!ZoneLoaded) break; + if (!ZoneLoaded) + break; ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer; if (scm->deliverto[0] == 0) { entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->message); - } - else { - Client* client; - client = entity_list.GetClientByName(scm->deliverto); - if (client != 0) { + } else { + Client* client = entity_list.GetClientByName(scm->deliverto); + if (client) { if (client->Connected()) { - client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message); - if (!scm->noreply && scm->chan_num!=2) { //dont echo on group chat + if (scm->queued == 1) // tell was queued + client->Tell_StringID(QUEUED_TELL, scm->to, scm->message); + else if (scm->queued == 2) // tell queue was full + client->Tell_StringID(QUEUE_TELL_FULL, scm->to, scm->message); + else if (scm->queued == 3) // person was offline + client->Message_StringID(MT_TellEcho, TOLD_NOT_ONLINE); + else // normal stuff + client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message); + if (!scm->noreply && scm->chan_num != 2) { //dont echo on group chat // if it's a tell, echo back so it shows up scm->noreply = true; scm->chan_num = 14; @@ -1856,6 +1862,7 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu scm->chan_num = chan_num; scm->guilddbid = guilddbid; scm->language = language; + scm->queued = 0; strcpy(scm->message, buffer); pack->Deflate(); From 7621882b4edcda76fb18b18848889a13e42fb9d9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Sep 2014 02:46:04 -0400 Subject: [PATCH 34/56] Fix toon names being allowed with lower case starting char --- changelog.txt | 1 + world/client.cpp | 26 ++++++++++---------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/changelog.txt b/changelog.txt index 493e57152..892ddbb33 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 09/19/2014 == demonstar55: Added Client::Tell_StringID (used in tell queue messages) demonstar55: Tell queues (and offline) messages now show correctly +demonstar55: Fix starting with capital check == 09/18/2014== demonstar55: Implement tell queues diff --git a/world/client.cpp b/world/client.cpp index f34f4e3df..f5f634083 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -471,8 +471,8 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { return true; } -bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { - +bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) +{ if (GetAccountID() == 0) { clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account"); return false; @@ -482,7 +482,7 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { uchar race = app->pBuffer[64]; uchar clas = app->pBuffer[68]; - clog(WORLD__CLIENT,"Name approval request. Name=%s, race=%s, class=%s",char_name,GetRaceName(race),GetEQClassName(clas)); + clog(WORLD__CLIENT, "Name approval request. Name=%s, race=%s, class=%s", char_name, GetRaceName(race), GetEQClassName(clas)); EQApplicationPacket *outapp; outapp = new EQApplicationPacket; @@ -490,27 +490,21 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) { outapp->pBuffer = new uchar[1]; outapp->size = 1; - bool valid; - if(!database.CheckNameFilter(char_name)) { + bool valid = false; + if (!database.CheckNameFilter(char_name)) valid = false; - } - else if(char_name[0] < 'A' && char_name[0] > 'Z') { + else if (islower(char_name[0])) //name must begin with an upper-case letter. valid = false; - } - else if (database.ReserveName(GetAccountID(), char_name)) { + else if (database.ReserveName(GetAccountID(), char_name)) valid = true; - } - else { - valid = false; - } - outapp->pBuffer[0] = valid? 1 : 0; + + outapp->pBuffer[0] = valid ? 1 : 0; QueuePacket(outapp); safe_delete(outapp); - if(!valid) { + if (!valid) memset(char_name, 0, sizeof(char_name)); - } return true; } From 15eaf4e6d1309cea96e4d98d69ad641f5cc66784 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Sep 2014 14:57:15 -0400 Subject: [PATCH 35/56] Fix issue with not online message from tells --- zone/worldserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index c54c2e886..1db473b0e 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -182,7 +182,7 @@ void WorldServer::Process() { else if (scm->queued == 2) // tell queue was full client->Tell_StringID(QUEUE_TELL_FULL, scm->to, scm->message); else if (scm->queued == 3) // person was offline - client->Message_StringID(MT_TellEcho, TOLD_NOT_ONLINE); + client->Message_StringID(MT_TellEcho, TOLD_NOT_ONLINE, scm->to); else // normal stuff client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message); if (!scm->noreply && scm->chan_num != 2) { //dont echo on group chat From f82699c39bdd45ccb0754e55490826b851d6053e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Sep 2014 15:55:20 -0400 Subject: [PATCH 36/56] Fix crash in SendEnterWorld on illegally long names --- changelog.txt | 3 +++ world/client.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 892ddbb33..57d36c2ad 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/20/2014 == +demonstar55: Fix crash in SendEnterWorld on illegally long names + == 09/19/2014 == demonstar55: Added Client::Tell_StringID (used in tell queue messages) demonstar55: Tell queues (and offline) messages now show correctly diff --git a/world/client.cpp b/world/client.cpp index f5f634083..0970d6866 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -130,7 +130,7 @@ void Client::SendLogServer() void Client::SendEnterWorld(std::string name) { -char char_name[32]= { 0 }; + char char_name[64] = { 0 }; if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) { if(database.GetAccountIDByChar(char_name) != GetAccountID()) { eqs->Close(); From 33b79a3588c3069c5446735f45dd7954e99c6e97 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Sep 2014 15:59:34 -0400 Subject: [PATCH 37/56] Limit character length to 15 (the client doesn't let you enter more) --- changelog.txt | 1 + common/database.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 57d36c2ad..b521da3fe 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 09/20/2014 == demonstar55: Fix crash in SendEnterWorld on illegally long names +demonstar55: The client only lets you enter 15 characters for your name (UF at least) == 09/19/2014 == demonstar55: Added Client::Tell_StringID (used in tell queue messages) diff --git a/common/database.cpp b/common/database.cpp index 88f01a676..ca287c3b5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1140,7 +1140,7 @@ bool Database::CheckNameFilter(const char* name, bool surname) else { // the minimum 4 is enforced by the client too - if(!name || strlen(name) < 4 || strlen(name) > 64) + if(!name || strlen(name) < 4 || strlen(name) > 15) { return false; } From 1049e48acadc0bcfa39d1a02d06651253e19a0d0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Sep 2014 16:58:35 -0400 Subject: [PATCH 38/56] Add Spells:SHDProcIDOffByeOne to support newer spell files In June 2009 SoE stopped doing a +1 to the base for SHD procs So UF+ spell files were not working, set this to false to support these spell files --- changelog.txt | 1 + common/ruletypes.h | 1 + .../optional/2014_09_20_SHDProCIDOffByOne.sql | 1 + zone/spell_effects.cpp | 31 ++++++++++--------- 4 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 utils/sql/git/optional/2014_09_20_SHDProCIDOffByOne.sql diff --git a/changelog.txt b/changelog.txt index b521da3fe..9317d6c17 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 09/20/2014 == demonstar55: Fix crash in SendEnterWorld on illegally long names demonstar55: The client only lets you enter 15 characters for your name (UF at least) +demonstar55: Add rule Spells:SHDProcIDOffByOne for pre-UF spell file, set to true, UF+ set to false == 09/19/2014 == demonstar55: Added Client::Tell_StringID (used in tell queue messages) diff --git a/common/ruletypes.h b/common/ruletypes.h index 95fa19854..058d5ce6f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -321,6 +321,7 @@ RULE_INT ( Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing targe RULE_INT ( Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random) RULE_INT ( Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random) RULE_INT ( Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others. +RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) RULE_CATEGORY_END() diff --git a/utils/sql/git/optional/2014_09_20_SHDProCIDOffByOne.sql b/utils/sql/git/optional/2014_09_20_SHDProCIDOffByOne.sql new file mode 100644 index 000000000..de6eb7d85 --- /dev/null +++ b/utils/sql/git/optional/2014_09_20_SHDProCIDOffByOne.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:SHDProcIDOffByOne', 'true', 'SHD procs are off by 1. Set true for pre-UF spell files, false for UF+.'); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f0bc8498b..a81377f5d 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5598,28 +5598,29 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id) } //for some stupid reason SK procs return theirs one base off... -uint16 Mob::GetProcID(uint16 spell_id, uint8 effect_index) { +uint16 Mob::GetProcID(uint16 spell_id, uint8 effect_index) +{ + if (!RuleB(Spells, SHDProcIDOffByOne)) // UF+ spell files + return spells[spell_id].base[effect_index]; + + // We should actually just be checking if the mob is SHD, but to not force + // custom servers to create new spells, we will still do this bool sk = false; bool other = false; - for(int x = 0; x < 16; x++) - { - if(x == 4){ - if(spells[spell_id].classes[4] < 255) + for (int x = 0; x < 16; x++) { + if (x == 4) { + if (spells[spell_id].classes[4] < 255) sk = true; - } - else{ - if(spells[spell_id].classes[x] < 255) + } else { + if (spells[spell_id].classes[x] < 255) other = true; } } - if(sk && !other) - { - return(spells[spell_id].base[effect_index] + 1); - } - else{ - return(spells[spell_id].base[effect_index]); - } + if (sk && !other) + return spells[spell_id].base[effect_index] + 1; + else + return spells[spell_id].base[effect_index]; } bool Mob::TryDivineSave() From 7140a2054f833306be995c8ae6f3a285e9b0bee2 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 20 Sep 2014 15:09:43 -0700 Subject: [PATCH 39/56] Ban and suspend commands now require a reason that is recorded in the DB --- changelog.txt | 1 + common/database.cpp | 2 +- .../git/required/2014_09_20_ban_messages.sql | 1 + zone/command.cpp | 118 +++++++++++------- 4 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 utils/sql/git/required/2014_09_20_ban_messages.sql diff --git a/changelog.txt b/changelog.txt index b521da3fe..dcf2d55ed 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 09/20/2014 == demonstar55: Fix crash in SendEnterWorld on illegally long names demonstar55: The client only lets you enter 15 characters for your name (UF at least) +KLS: #suspend and #ban now have required messages to record the reason for the ban/suspension. == 09/19/2014 == demonstar55: Added Client::Tell_StringID (used in tell queue messages) diff --git a/common/database.cpp b/common/database.cpp index ca287c3b5..4e7517f16 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -659,7 +659,7 @@ the name "name" or zero if no character with that name was found Zero will also be returned if there is a database error. */ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", charname); + std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", EscapeString(charname).c_str()); auto results = QueryDatabase(query); diff --git a/utils/sql/git/required/2014_09_20_ban_messages.sql b/utils/sql/git/required/2014_09_20_ban_messages.sql new file mode 100644 index 000000000..4612f9962 --- /dev/null +++ b/utils/sql/git/required/2014_09_20_ban_messages.sql @@ -0,0 +1 @@ +ALTER TABLE `account` ADD COLUMN `ban_reason` TEXT NULL DEFAULT NULL AFTER `expansion`, ADD COLUMN `suspend_reason` TEXT NULL DEFAULT NULL AFTER `ban_reason`; diff --git a/zone/command.cpp b/zone/command.cpp index b2f08d3eb..36dc95921 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6258,36 +6258,49 @@ void command_stun(Client *c, const Seperator *sep) c->Message(0, "Usage: #stun [duration]"); } + void command_ban(Client *c, const Seperator *sep) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if(sep->arg[1][0] == 0) + if(sep->arg[1][0] == 0 || sep->arg[2][0] == 0) { - c->Message(0, "Usage: #ban [charname]"); + c->Message(0, "Usage: #ban "); } else { - database.RunQuery(query, MakeAnyLenString(&query, "SELECT account_id from character_ where name = '%s'", sep->arg[1]), errbuf, &result); - if(query) - { - safe_delete_array(query); + auto account_id = database.GetAccountIDByChar(sep->arg[1]); + + std::string message; + int i = 2; + while(1) { + if(sep->arg[i][0] == 0) { + break; + } + + if(message.length() > 0) { + message.push_back(' '); + } + + message += sep->arg[i]; + ++i; } - if(mysql_num_rows(result)) - { - row = mysql_fetch_row(result); - database.RunQuery(query, MakeAnyLenString(&query, "UPDATE account set status = -2 where id = %i", atoi(row[0])), errbuf, 0); - c->Message(13,"Account number %i with the character %s has been banned.", atoi(row[0]), sep->arg[1]); + if(message.length() == 0) { + c->Message(0, "Usage: #ban "); + return; + } - ServerPacket* pack = new ServerPacket(ServerOP_FlagUpdate, 6); - *((uint32*) pack->pBuffer) = atoi(row[0]); - *((int16*) &pack->pBuffer[4]) = -2; - worldserver.SendPacket(pack); - safe_delete(pack); + if(account_id > 0) + { + database.RunQuery(query, MakeAnyLenString(&query, "UPDATE account set status = -2, ban_reason = '%s' where id = %i", EscapeString(message).c_str(), account_id), errbuf, 0); + c->Message(13, "Account number %i with the character %s has been banned with message: \"%s\"", account_id, sep->arg[1], message.c_str()); + + ServerPacket pack(ServerOP_FlagUpdate, 6); + *((uint32*)&pack.pBuffer[0]) = account_id; + *((int16*)&pack.pBuffer[4]) = -2; + worldserver.SendPacket(&pack); Client *client = nullptr; client = entity_list.GetClientByName(sep->arg[1]); @@ -6297,25 +6310,20 @@ void command_ban(Client *c, const Seperator *sep) } else { - ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; + ServerPacket pack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack.pBuffer; strcpy(skp->adminname, c->GetName()); strcpy(skp->name, sep->arg[1]); skp->adminrank = c->Admin(); - worldserver.SendPacket(pack); - safe_delete(pack); + worldserver.SendPacket(&pack); } - - mysql_free_result(result); } else { - c->Message(13,"Character does not exist."); - } - if(query) - { - safe_delete_array(query); + c->Message(13, "Character does not exist."); } + + safe_delete_array(query); } } @@ -6325,7 +6333,7 @@ void command_suspend(Client *c, const Seperator *sep) char *query = nullptr; if((sep->arg[1][0] == 0) || (sep->arg[2][0] == 0)) - c->Message(0, "Usage: #suspend (Specify 0 days to lift the suspension immediately)"); + c->Message(0, "Usage: #suspend (Specify 0 days to lift the suspension immediately) "); else { int Duration = atoi(sep->arg[2]); @@ -6333,22 +6341,40 @@ void command_suspend(Client *c, const Seperator *sep) if(Duration < 0) Duration = 0; - char *EscName = new char[strlen(sep->arg[1]) * 2 + 1]; + std::string message; + if(Duration > 0) { + int i = 3; + while(1) { + if(sep->arg[i][0] == 0) { + break; + } - database.DoEscapeString(EscName, sep->arg[1], strlen(sep->arg[1])); + if(message.length() > 0) { + message.push_back(' '); + } + + message += sep->arg[i]; + ++i; + } + + if(message.length() == 0) { + c->Message(0, "Usage: #suspend (Specify 0 days to lift the suspension immediately) "); + return; + } + } int AccountID; - if((AccountID = database.GetAccountIDByChar(EscName)) > 0) + if((AccountID = database.GetAccountIDByChar(sep->arg[1])) > 0) { - database.RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY)" - " WHERE `id` = %i", Duration, AccountID), errbuf, 0); + database.RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY), " + "suspend_reason = '%s' WHERE `id` = %i", Duration, EscapeString(message).c_str(), AccountID), errbuf, 0); if(Duration) - c->Message(13,"Account number %i with the character %s has been temporarily suspended for %i day(s).", AccountID, sep->arg[1], - Duration); + c->Message(13, "Account number %i with the character %s has been temporarily suspended for %i day(s) with the message: \"%s\"", AccountID, sep->arg[1], + Duration, message.c_str()); else - c->Message(13,"Account number %i with the character %s is no longer suspended.", AccountID, sep->arg[1]); + c->Message(13, "Account number %i with the character %s is no longer suspended.", AccountID, sep->arg[1]); safe_delete_array(query); @@ -6358,22 +6384,20 @@ void command_suspend(Client *c, const Seperator *sep) BannedClient->WorldKick(); else { - ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*) pack->pBuffer; + ServerPacket pack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*)pack.pBuffer; strn0cpy(sks->adminname, c->GetName(), sizeof(sks->adminname)); strn0cpy(sks->name, sep->arg[1], sizeof(sks->name)); sks->adminrank = c->Admin(); - worldserver.SendPacket(pack); - - safe_delete(pack); + worldserver.SendPacket(&pack); } - } else - c->Message(13,"Character does not exist."); - - safe_delete_array(EscName); + } + else { + c->Message(13, "Character does not exist."); + } } } From f9366553a3680dfcfa90d9887c71a5de1e31ebbe Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 01:27:05 -0500 Subject: [PATCH 40/56] Blob changelog.txt --- changelog.txt | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ zone/zoning.cpp | 2 -- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index a006c9a50..44b72c1df 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,99 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/21/2014 == +Akkadius: Player Profile Blob to Database Conversion + - Summary: HUGE difference in database speeds reads/writes and 1:10 datasize difference + - The new character storage engine unlike the character_ table before, is able to properly index data and make use of + proper MySQL/MariaDB caching optimizations and performance has increased phenominally + PERFORMANCE AND STATISTICS FIGURES (Varies on hardware): + - EZ Server Character data size of 2.6GB `character_` table alone now takes up approx 600MB + - Character Data Loads take approx .03 seconds BEFORE MySQL/MariaDB cache + - Character Data Loads take approx .001-.0035 seconds AFTER MySQL/MariaDB cache + - Character Data Saves take approx .0001 - .003 for any particular save operation + - Database Auto Conversion: When the 'character_' table exists, World boot-up will queue an auto-conversion prompt and convert all of your characters, BACKUP + YOUR DATABASE BEFORE CONVERTING, here is an EASY backup script: http://wiki.eqemulator.org/p?MySQL_DB_Backup_Script + - On auto conversion, the following tables are created automatically: + - Table: `character_skills` - Stores Character Skills + - Table: `character_languages` - Stores Character Language + - Table: `character_bind` - Stores Character Bind point and Home Bind point designated by is_home bool field + - Table: `character_alternate_abilities` - Stores all Character AA + - Table: `character_currency` - Stores all Platinum/Gold/Silver/Copper and character related currencies + - Table: `character_data` - Stores basic character data (Fields from `character_` table migrated to this table) + - Table: `character_spells` - Stores character spells + - Table: `character_memmed_spells` - Stores character memorized spells + - Table: `character_disciplines` - Stores character disciplines + - Table: `character_material` - Stores character armor dye textures + - Table: `character_tribute` - Stores character tributes + - Table: `character_bandolier` - Stores character bandoliers + - Table: `character_inspect_messages` - Stores character inspection messages (Moved from `character_` table) + - Table: `character_leadership_abilities` - Stores character Leadership AAs + - Loads: Majority of Player profile loads now occur at Client::Handle_Connect_OP_ZoneEntry + LoadCharacterFactionValues(uint32 character_id, faction_map & val_list); + LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); + LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp); + LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); + - Saves: Occur all over the code now instead of calling full saves + SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home); + SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); + SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); + SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level); + SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color); + SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); + SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value); + SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id); + SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name); + SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon); + SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); + - Deletes: + DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); + DeleteCharacterDisc(uint32 character_id, uint32 slot_id); + DeleteCharacterBandolier(uint32 character_id, uint32 band_id); + DeleteCharacterLeadershipAAs(uint32 character_id); + - Now occur all over the code and only trigger when necessary + - Two FULL saves when looting a corpse, this has been reduced to just currency saves on initial loot and trimmed to one save since AddToMoneyPP did it already + - Every time a player moves coin with any situation (Splits/Trades/Merchant/Skills/Bank Coin Exchange/Coin Moves), a full save is made, this is now just a currency save + - Every time a player skilled up at a skill vendor, a full blob save hit was made, this is not just a currency hit + - Every time an AA was purchased, a full save was made + - Every time a spell was scribed/swapped, disc was trained + - When a client exists a zone, when a client enters a zone + - NOTE: These amount of excessive saves have caused scalability issues that cause the `character_` table to hang which causes process hangs that affect the whole server + because of the slowness of the `character_` table and the blob not allowing any indexing to occur + - All functions that once depended on the `character_` table are now rewritten to appropriately read from the `character_data` table + - Database query errors that occur during conversion or from and load/save/delete character functions are now leveraged via ThrowDBError and logs now go to + Server_Folder_Root/eqemu_query_error_log.txt (You cannot log errors natively through MySQL) + - DBASYNC IS NOW COMPLETELY REMOVED - This was mainly for Character data async loads/saves and merchantlist loads + - Side implementations: + Perl Exports: + - quest::crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var) - Sets entity variables world wide with specified npctype_id + - quest::crosszonesignalnpcbynpctypeid(npctype_id, data) - Signals all NPC entities world wide with specified npctype_id + - $client->GetTaskActivityDoneCount(TaskID, ActivityID) - Gets task activity done count by task id and activity id for client entity + + VIEW TABLE SIZE AFTER CONVERT: + + SELECT CONCAT(table_schema, '.', table_name) as table_name, + CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows, + CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA, + CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') idx, + CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size, + ROUND(index_length / data_length, 2) idxfrac + FROM information_schema.TABLES + WHERE `table_name` LIKE 'character_%' + ORDER BY DATA DESC; + == 09/16/2014 == demonstar55: Implement spell formula 137 (BER AA Desperation) Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded. diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 0cbf39a2c..6a8abb6d4 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -368,8 +368,6 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc outapp->priority = 6; FastQueuePacket(&outapp); - printf("INTERZONE PROCESS\n"); - zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000); } else { // vesuvias - zoneing to another zone so we need to the let the world server From b4f399361695df6f1eb990dc7761a21b3d66fc05 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 20 Sep 2014 23:56:04 -0700 Subject: [PATCH 41/56] Should compile on gcc now --- common/database.cpp | 2 +- common/database.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index aed844f64..d53141e71 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include // Disgrace: for windows compile diff --git a/common/database.h b/common/database.h index c70464094..e1d4c6fd6 100644 --- a/common/database.h +++ b/common/database.h @@ -222,7 +222,7 @@ public: uint32 GetRaidID(const char* name); const char *GetRaidLeaderName(uint32 rid); - bool Database::CheckDatabaseConversions(); + bool CheckDatabaseConversions(); /* * Database Variables From 388c4bc574626473c0dde908cb6efd6f06da554d Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 02:27:57 -0500 Subject: [PATCH 42/56] Fix where if players instance is expired when logging back into it, they will get sent properly to bind. Issue was players player profile instance ID did not match the bind instance ID. --- zone/client_packet.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a27b7dd05..d3c0f5f42 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -614,6 +614,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { /* Set Con State for Reporting */ conn_state = PlayerProfileLoaded; + m_pp.zone_id = zone->GetZoneID(); + m_pp.zoneInstance = zone->GetInstanceID(); + /* Set Total Seconds Played */ TotalSecondsPlayed = m_pp.timePlayedMin * 60; /* Set Max AA XP */ From 4ed88e348e6a0382193775d25edc20caa95d4d0a Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 02:58:56 -0500 Subject: [PATCH 43/56] Merge aftermath --- common/database.cpp | 9 +++++++-- common/database.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 78eec13a7..f66496654 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -782,10 +782,15 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { } if (results.RowCount() != 1) - return 0; + return 0; auto row = results.begin(); - if (row[0]){ accountId = atoi(row[0]); } + + uint32 accountId = atoi(row[0]); + + if (oCharID) + *oCharID = atoi(row[1]); + return accountId; } diff --git a/common/database.h b/common/database.h index e1d4c6fd6..c4d3af336 100644 --- a/common/database.h +++ b/common/database.h @@ -132,7 +132,7 @@ public: */ bool CheckNameFilter(const char* name, bool surname = false); bool CheckUsedName(const char* name); - uint32 GetAccountIDByChar(const char* charname); + uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); uint32 GetGuildIDByCharID(uint32 char_id); From 3ef5d8ef0a5ecc76bd2decebf60e3a845249191c Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 03:43:27 -0500 Subject: [PATCH 44/56] gcc fix vs --- zone/zonedb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/zonedb.h b/zone/zonedb.h index 497beb322..08f442897 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -6,7 +6,7 @@ #include "../common/loottable.h" #include "zonedump.h" #include "../common/faction.h" -#include +#include //#include "doors.h" struct wplist { From db0d1116f85226a065b10371db2523862bad70f4 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 04:12:36 -0500 Subject: [PATCH 45/56] make travis shut up --- zone/zonedb.cpp | 2 +- zone/zonedb.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 4878b6644..15d2a3f4d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1245,7 +1245,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); /* Save Tributes only if we have values... */ for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ - if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != UINT32_MAX){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 0xffffffffui32){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } diff --git a/zone/zonedb.h b/zone/zonedb.h index 08f442897..647e9bfbd 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -6,7 +6,8 @@ #include "../common/loottable.h" #include "zonedump.h" #include "../common/faction.h" -#include +#include + //#include "doors.h" struct wplist { From 4525b512ac14894a9873f345a752602ecd8568fd Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 21 Sep 2014 02:25:05 -0700 Subject: [PATCH 46/56] Build fix plus future travis update --- .travis.yml | 4 +++- zone/zonedb.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5bdd64324..71606e74c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,9 @@ script: - make - ./bin/tests branches: - only: master + only: + - master + - stable notifications: email: false irc: diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 15d2a3f4d..dbf3c2742 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1245,7 +1245,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); /* Save Tributes only if we have values... */ for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ - if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 0xffffffffui32){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 0xffffffffu){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } From cda2217634cbe76584c96d09ede39cfb048a00f6 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 04:26:26 -0500 Subject: [PATCH 47/56] .......................................... --- zone/zonedb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 15d2a3f4d..917928520 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1245,7 +1245,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); /* Save Tributes only if we have values... */ for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ - if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 0xffffffffui32){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } From cd8e30a2ec361ea770d8a765956b403e76bb30fa Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 21 Sep 2014 15:59:02 -0700 Subject: [PATCH 48/56] Bug with MySQLRequestResult --- common/mysql_request_result.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/mysql_request_result.cpp b/common/mysql_request_result.cpp index b4bf30842..e7f147b51 100644 --- a/common/mysql_request_result.cpp +++ b/common/mysql_request_result.cpp @@ -101,6 +101,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem) m_RowsAffected = moveItem.m_RowsAffected; m_LastInsertedID = moveItem.m_LastInsertedID; m_ColumnLengths = moveItem.m_ColumnLengths; + m_ColumnCount = moveItem.m_ColumnCount; m_Fields = moveItem.m_Fields; // Keeps deconstructor from double freeing @@ -128,6 +129,7 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other) m_CurrentRow = other.m_CurrentRow; m_OneBeyondRow = other.m_OneBeyondRow; m_ColumnLengths = other.m_ColumnLengths; + m_ColumnCount = other.m_ColumnCount; m_Fields = other.m_Fields; // Keeps deconstructor from double freeing From 909dda7c0906ac76bec7eb99845e7ac687e86649 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 19:01:50 -0500 Subject: [PATCH 49/56] Array iter fix --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 9bfe21a75..a19961209 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1846,7 +1846,7 @@ bool Database::CheckDatabaseConversions() { if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Tribute Convert", rquery); } /* Run Bandolier Convert */ first_entry = 0; rquery = ""; - for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){ + for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++){ if(strlen(pp->bandoliers[i].name) < 32) { for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ if (pp->bandoliers[i].items[si].item_id > 0){ @@ -1862,7 +1862,7 @@ bool Database::CheckDatabaseConversions() { if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bandolier Convert", rquery); } /* Run Potion Belt Convert */ first_entry = 0; rquery = ""; - for (i = 0; i <= EmuConstants::POTION_BELT_SIZE; i++){ + for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ if (pp->potionbelt.items[i].item_id > 0){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); @@ -1875,7 +1875,7 @@ bool Database::CheckDatabaseConversions() { if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Potion Belt Convert", rquery); } /* Run Leadership AA Convert */ first_entry = 0; rquery = ""; - for (i = 0; i <= MAX_LEADERSHIP_AA_ARRAY; i++){ + for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){ if(pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); From e34c47414fd1dd45eec22587d12bde2c30502249 Mon Sep 17 00:00:00 2001 From: JJ Date: Sun, 21 Sep 2014 20:02:01 -0400 Subject: [PATCH 50/56] Consistent directory locations under common. --- common/patches/client62_constants.h | 2 +- common/patches/rof_constants.h | 2 +- common/patches/sod_constants.h | 2 +- common/patches/sof_constants.h | 2 +- common/patches/titanium_constants.h | 2 +- common/patches/underfoot_constants.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/patches/client62_constants.h b/common/patches/client62_constants.h index e8eb38faa..7d2125028 100644 --- a/common/patches/client62_constants.h +++ b/common/patches/client62_constants.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef CLIENT62_CONSTANTS_H_ #define CLIENT62_CONSTANTS_H_ -#include "../common/types.h" +#include "../types.h" namespace Client62 { namespace maps { diff --git a/common/patches/rof_constants.h b/common/patches/rof_constants.h index 7be8baf72..62a161dc5 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_constants.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef RoF_CONSTANTS_H_ #define RoF_CONSTANTS_H_ -#include "../common/types.h" +#include "../types.h" namespace RoF { namespace maps { diff --git a/common/patches/sod_constants.h b/common/patches/sod_constants.h index 76427d55e..9a8907f13 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/sod_constants.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef SoD_CONSTANTS_H_ #define SoD_CONSTANTS_H_ -#include "../common/types.h" +#include "../types.h" namespace SoD { namespace maps { diff --git a/common/patches/sof_constants.h b/common/patches/sof_constants.h index 0ae0d728d..d80fa2dcb 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_constants.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef SoF_CONSTANTS_H_ #define SoF_CONSTANTS_H_ -#include "../common/types.h" +#include "../types.h" namespace SoF { namespace maps { diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_constants.h index c07244f2d..71625362a 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_constants.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef Titanium_CONSTANTS_H_ #define Titanium_CONSTANTS_H_ -#include "../common/types.h" +#include "../types.h" namespace Titanium { namespace maps { diff --git a/common/patches/underfoot_constants.h b/common/patches/underfoot_constants.h index d34eaeb5b..fdbe54086 100644 --- a/common/patches/underfoot_constants.h +++ b/common/patches/underfoot_constants.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef Underfoot_CONSTANTS_H_ #define Underfoot_CONSTANTS_H_ -#include "../common/types.h" +#include "../types.h" namespace Underfoot { namespace maps { From 7d242045ec637d4fdfa63a4be6cc52190d44b874 Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 23:34:53 -0500 Subject: [PATCH 51/56] Another merge aftermath overwriting character_data reference to old table --- common/database.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index a19961209..7f7af3f2c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -771,7 +771,7 @@ uint32 Database::GetCharacterID(const char *name) { Zero will also be returned if there is a database error. */ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { - std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", EscapeString(charname).c_str()); + std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE name='%s'", EscapeString(charname).c_str()); auto results = QueryDatabase(query); From a5a8bfb0f4488ddf89fd788f8d47cc6d98a97c0e Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 23:48:51 -0500 Subject: [PATCH 52/56] Bye bye commented old junk --- common/guilds.cpp | 316 +--------------------------------------------- 1 file changed, 1 insertion(+), 315 deletions(-) diff --git a/common/guilds.cpp b/common/guilds.cpp index 4f5c08bb6..ddd5d9a59 100644 --- a/common/guilds.cpp +++ b/common/guilds.cpp @@ -24,318 +24,4 @@ #ifndef WIN32 #include //for htonl -#endif - -/* -void Database::GetGuildMembers(uint32 guild_id, GuildMember_Struct* gms){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 count=0; - uint32 length=0; - if (RunQuery(query, MakeAnyLenString(&query, "Select name,profile,timelaston,guildrank,publicnote from character_ where guild=%i", guild_id), errbuf, &result)) { - safe_delete_array(query); - while( ( row = mysql_fetch_row(result) ) ){ - strcpy(gms->member[count].name,row[0]); - length+=strlen(row[0])+strlen(row[4]); - PlayerProfile_Struct* pps=(PlayerProfile_Struct*)row[1]; - gms->member[count].level=htonl(pps->level); - gms->member[count].zoneid=(pps->zone_id*256); - gms->member[count].timelaston=htonl(atol(row[2])); - gms->member[count].class_=htonl(pps->class_); - gms->member[count].rank=atoi(row[3]); - strcpy(gms->member[count].publicnote,row[4]); - count++; - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetGuildMembers query '%s': %s", query, errbuf); - safe_delete_array(query); - } - gms->count=count; - gms->length=length; -} - -uint32 Database::NumberInGuild(uint32 guild_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "Select count(id) from character_ where guild=%i", guild_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in NumberInGuild query '%s': %s", query, errbuf); - safe_delete_array(query); - return 0; - } - return 0; -} -bool Database::SetGuild(char* name, uint32 guild_id, uint8 guildrank) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET guild=%i, guildrank=%i WHERE name='%s'", guild_id, guildrank, name), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) - return true; - else - return false; - } - else { - LogFile->write(EQEMuLog::Error, "Error in SetGuild query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - return false; -} - -bool Database::SetGuild(uint32 charid, uint32 guild_id, uint8 guildrank) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET guild=%i, guildrank=%i WHERE id=%i", guild_id, guildrank, charid), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) - return true; - - else - return false; - } - else { - LogFile->write(EQEMuLog::Error, "Error in SetGuild query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - - return false; -} - -bool Database::DeleteGuild(uint32 guild_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - char *query2 = 0; - uint32 affected_rows = 0; - - if (RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guilds WHERE id=%i;", guild_id), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) { - if(!RunQuery(query2, MakeAnyLenString(&query2, "update character_ set guild=0,guildrank=0 where guild=%i", guild_id), errbuf, 0, &affected_rows)) - LogFile->write(EQEMuLog::Error, "Error in DeleteGuild cleanup query '%s': %s", query2, errbuf); - safe_delete_array(query2); - return true; - } - else - return false; - } - else { - LogFile->write(EQEMuLog::Error, "Error in DeleteGuild query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - - return false; -} - -bool Database::RenameGuild(uint32 guild_id, const char* name) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - char buf[65]; - DoEscapeString(buf, name, strlen(name)) ; - - if (RunQuery(query, MakeAnyLenString(&query, "Update guilds set name='%s' WHERE id=%i;", buf, guild_id), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) - return true; - else - return false; - } - else { - LogFile->write(EQEMuLog::Error, "Error in RenameGuild query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - - return false; -} - - - -bool Database::EditGuild(uint32 guild_id, uint8 ranknum, GuildRankLevel_Struct* grl) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - int chars = 0; - uint32 affected_rows = 0; - char buf[203]; - char buf2[8]; - DoEscapeString(buf, grl->rankname, strlen(grl->rankname)) ; - buf2[GUILD_HEAR] = grl->heargu + '0'; - buf2[GUILD_SPEAK] = grl->speakgu + '0'; - buf2[GUILD_INVITE] = grl->invite + '0'; - buf2[GUILD_REMOVE] = grl->remove + '0'; - buf2[GUILD_PROMOTE] = grl->promote + '0'; - buf2[GUILD_DEMOTE] = grl->demote + '0'; - buf2[GUILD_MOTD] = grl->motd + '0'; - buf2[GUILD_WARPEACE] = grl->warpeace + '0'; - - if (ranknum == 0) - chars = MakeAnyLenString(&query, "Update guilds set rank%ititle='%s' WHERE id=%i;", ranknum, buf, guild_id); - else - chars = MakeAnyLenString(&query, "Update guilds set rank%ititle='%s', rank%i='%s' WHERE id=%i;", ranknum, buf, ranknum, buf2, guild_id); - - if (RunQuery(query, chars, errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) - return true; - else - return false; - } - else { - LogFile->write(EQEMuLog::Error, "Error in EditGuild query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - - return false; -} - -bool Database::GetGuildNameByID(uint32 guild_id, char * name) { - if (!name || !guild_id) return false; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "select name from guilds where id='%i'", guild_id), errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - if (row[0]) - sprintf(name,"%s",row[0]); - mysql_free_result(result); - return true; - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetGuildNameByID query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - - return false; -} - -uint32 Database::GetGuildIDbyLeader(uint32 leader) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM guilds WHERE leader=%i", leader), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 tmp = atoi(row[0]); - mysql_free_result(result); - return tmp; - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in Getguild_idbyLeader query '%s': %s", query, errbuf); - safe_delete_array(query); - } - - return 0; -} - -bool Database::SetGuildLeader(uint32 guild_id, uint32 leader) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - if (RunQuery(query, MakeAnyLenString(&query, "UPDATE guilds SET leader=%i WHERE id=%i", leader, guild_id), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - if (affected_rows == 1) - return true; - else - return false; - } - else { - LogFile->write(EQEMuLog::Error, "Error in SetGuildLeader query '%s': %s", query, errbuf); - safe_delete_array(query); - return false; - } - - return false; -} - -bool Database::SetGuildMOTD(uint32 guild_id, const char* motd) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - char* motdbuf = 0; - uint32 affected_rows = 0; - - motdbuf = new char[(strlen(motd)*2)+3]; - - DoEscapeString(motdbuf, motd, strlen(motd)) ; - - if (RunQuery(query, MakeAnyLenString(&query, "Update guilds set motd='%s' WHERE id=%i;", motdbuf, guild_id), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - delete motdbuf; - if (affected_rows == 1) - return true; - else - return false; - } - else - { - LogFile->write(EQEMuLog::Error, "Error in SetGuildMOTD query '%s': %s", query, errbuf); - safe_delete_array(query); - delete motdbuf; - return false; - } - - return false; -} - -string Database::GetGuildMOTD(uint32 guild_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - string motd_str; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT motd FROM guilds WHERE id=%i", guild_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - if (row[0]) - motd_str = row[0]; - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetGuildMOTD query '%s': %s", query, errbuf); - safe_delete_array(query); - } - return motd_str; -} -*/ - +#endif \ No newline at end of file From 837b9b7ec7bd966795833b696c0c49fa3d4410bf Mon Sep 17 00:00:00 2001 From: akkadius Date: Sun, 21 Sep 2014 23:54:52 -0500 Subject: [PATCH 53/56] NoRentExpired `character_` reference --- zone/zonedb.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index dbf3c2742..a3b1f691d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1662,8 +1662,7 @@ bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spe } bool ZoneDatabase::NoRentExpired(const char* name){ - std::string query = StringFormat("SELECT (UNIX_TIMESTAMP(NOW())-timelaston) " - "FROM character_ WHERE name = '%s'", name); + std::string query = StringFormat("SELECT (UNIX_TIMESTAMP(NOW()) - last_login) FROM `character_data` WHERE name = '%s'", name); auto results = QueryDatabase(query); if (!results.Success()) return false; From c26a6959e486f5684588d7ae04e14d3a3bb39c39 Mon Sep 17 00:00:00 2001 From: akkadius Date: Mon, 22 Sep 2014 01:00:28 -0500 Subject: [PATCH 54/56] #resetaa now covers the function of #resetaa and #refundaa #resetaa will wipe all AA data, refund the spent points into the available points and send character to character select properly Removed #refundaa Removed a lot of debug code for blob conversion Changed status logging for loads/saves to Debug category --- changelog.txt | 7 +++++++ zone/aa.cpp | 8 ++++++++ zone/client.cpp | 10 +++------- zone/client_packet.cpp | 4 ---- zone/command.cpp | 22 +--------------------- zone/zonedb.cpp | 28 +++++++++++++++------------- zone/zonedb.h | 1 + 7 files changed, 35 insertions(+), 45 deletions(-) diff --git a/changelog.txt b/changelog.txt index 01a190eb1..b002c0524 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/22/2014 == +Akkadius: #resetaa now covers the function of #resetaa and #refundaa + - #resetaa will wipe all AA data, refund the spent points into the available points and send character to character select properly +Akkadius: Removed #refundaa +Akkadius: Removed a lot of debug code for blob conversion +Akkadius: Changed status logging for loads/saves to Debug category + == 09/21/2014 == Akkadius: Player Profile Blob to Database Conversion - Summary: HUGE difference in database speeds reads/writes and 1:10 datasize difference diff --git a/zone/aa.cpp b/zone/aa.cpp index ef4b07aee..1f933b30e 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1520,11 +1520,15 @@ bool ZoneDatabase::LoadAAEffects2() { return true; } void Client::ResetAA(){ + RefundAA(); uint32 i; for(i=0;iAA = 0; aa[i]->value = 0; + m_pp.aa_array[MAX_PP_AA_ARRAY].AA = 0; + m_pp.aa_array[MAX_PP_AA_ARRAY].value = 0; } + std::map::iterator itr; for(itr=aa_points.begin();itr!=aa_points.end();++itr) aa_points[itr->first] = 0; @@ -1537,7 +1541,11 @@ void Client::ResetAA(){ m_pp.group_leadership_exp = 0; m_pp.raid_leadership_exp = 0; + database.DeleteCharacterAAs(this->CharacterID()); + SaveAA(); + SendAATable(); database.DeleteCharacterLeadershipAAs(this->CharacterID()); + Kick(); } int Client::GroupLeadershipAAHealthEnhancement() diff --git a/zone/client.cpp b/zone/client.cpp index ed2475779..fad7d1a80 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -478,7 +478,6 @@ void Client::ReportConnectingState() { } bool Client::SaveAA(){ - clock_t t = std::clock(); /* Function timer start */ int first_entry = 0; std::string rquery; /* Save Player AA */ @@ -515,7 +514,6 @@ bool Client::SaveAA(){ } } auto results = database.QueryDatabase(rquery); - LogFile->write(EQEMuLog::Status, "Issuing Client AA Save... CID: %i Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } @@ -523,8 +521,6 @@ bool Client::Save(uint8 iCommitNow) { if(!ClientDataLoaded()) return false; - clock_t t = std::clock(); /* Function timer start */ - /* Wrote current basics to PP for saves */ m_pp.x = x_pos; m_pp.y = y_pos; @@ -584,7 +580,6 @@ bool Client::Save(uint8 iCommitNow) { SaveTaskState(); /* Save Character Task */ database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */ - LogFile->write(EQEMuLog::Status, "Client::Save %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } @@ -7968,7 +7963,7 @@ void Client::RefundAA() { for(int j = 0; j < cur; j++) { m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); refunded = true; - } + } } else { @@ -7980,8 +7975,9 @@ void Client::RefundAA() { } if(refunded) { + SaveAA(); Save(); - Kick(); + // Kick(); } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ea832f28b..928eca1ad 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -546,8 +546,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { uint32 cid = CharacterID(); character_id = cid; /* Global character_id reference */ - clock_t t = std::clock(); /* Function timer start */ - /* Flush and reload factions */ database.RemoveTempFactions(this); database.LoadCharacterFactionValues(cid, factionvalues); @@ -605,8 +603,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) { if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255) m_pp.item_tint[i].rgb.use_tint = 0xFF; - std::cout << "Character Data Load Took " << (((float)(std::clock() - t)) / CLOCKS_PER_SEC) << " seconds\n" << std::endl; - if (level){ level = m_pp.level; } /* If GM, not trackable */ diff --git a/zone/command.cpp b/zone/command.cpp index 9a5dd3f6c..fe8d58faa 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -149,7 +149,7 @@ Access Levels: int command_init(void) { if ( - command_add("resetaa","- Resets a Player's AA in their profile.",200,command_resetaa) || + command_add("resetaa","- Resets a Player's AA in their profile and refunds spent AA's to unspent, disconnects player.",200,command_resetaa) || command_add("qtest","- QueryServ testing command.",255,command_qtest) || command_add("bind","- Sets your targets bind spot to their current location",200,command_bind) || command_add("sendop","[opcode] - LE's Private test command, leave it alone",200,command_sendop) || @@ -403,7 +403,6 @@ int command_init(void) { command_add("guildapprove","[guildapproveid] - Approve a guild with specified ID (guild creator receives the id)",0,command_guildapprove) || command_add("guildlist","[guildapproveid] - Lists character names who have approved the guild specified by the approve id",0,command_guildlist) || command_add("altactivate", "[argument] - activates alternate advancement abilities, use altactivate help for more information", 0, command_altactivate) || - command_add("refundaa", "- Refunds your target's AA points, will disconnect them in the process as well.", 100, command_refundaa) || #ifdef BOTS command_add("bot","- Type \"#bot help\" to the see the list of available commands for bots.", 0, command_bot) || @@ -8534,25 +8533,6 @@ void command_altactivate(Client *c, const Seperator *sep){ } } -void command_refundaa(Client *c, const Seperator *sep){ - Client* refundee = nullptr; - if(c) { - if(c->GetTarget()){ - if(c->GetTarget()->IsClient()) - refundee = c->GetTarget()->CastToClient(); - else - c->Message(0, "Your target must be a client."); - } - else{ - c->Message(0, "You must have a target selected."); - } - - if(refundee) { - refundee->RefundAA(); - } - } -} - void command_traindisc(Client *c, const Seperator *sep) { uint8 max_level, min_level; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index a3b1f691d..1327bd8ee 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -939,7 +939,6 @@ bool ZoneDatabase::LoadCharacterData(uint32 character_id, PlayerProfile_Struct* m_epp->aa_effects = atoi(row[r]); r++; // "`e_aa_effects`, " m_epp->perAA = atoi(row[r]); r++; // "`e_percent_to_aa`, " m_epp->expended_aa = atoi(row[r]); r++; // "`e_expended_aa_spent` " - LogFile->write(EQEMuLog::Status, "Loading Character Data for character ID: %i, done", character_id); } return true; } @@ -1102,7 +1101,6 @@ bool ZoneDatabase::LoadCharacterCurrency(uint32 character_id, PlayerProfile_Stru pp->careerRadCrystals = atoi(row[13]); pp->currentEbonCrystals = atoi(row[14]); pp->careerEbonCrystals = atoi(row[15]); - LogFile->write(EQEMuLog::Status, "Loading Currency for character ID: %i, done", character_id); } return true; } @@ -1201,7 +1199,7 @@ bool ZoneDatabase::LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Str bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value){ std::string query = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, lang_id, value); QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterLanguage for character ID: %i, lang_id:%u value:%u done", character_id, lang_id, value); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterLanguage for character ID: %i, lang_id:%u value:%u done", character_id, lang_id, value); return true; } @@ -1210,7 +1208,7 @@ bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, u /* Save Home Bind Point */ std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, x, y, z, heading, is_home); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u x: %f y: %f z: %f heading: %f ishome: %u", character_id, zone_id, instance_id, x, y, z, heading, is_home); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u x: %f y: %f z: %f heading: %f ishome: %u", character_id, zone_id, instance_id, x, y, z, heading, is_home); auto results = QueryDatabase(query); if (!results.RowsAffected()){ std::cout << "ERROR Bind Home Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterBindPoint", query); return true; @@ -1222,21 +1220,21 @@ bool ZoneDatabase::SaveCharacterMaterialColor(uint32 character_id, uint32 slot_i uint8 blue = (color & 0x000000FF); std::string query = StringFormat("REPLACE INTO `character_material` (id, slot, red, green, blue, color, use_tint) VALUES (%u, %u, %u, %u, %u, %u, 255)", character_id, slot_id, red, green, blue, color); auto results = QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterMaterialColor for character ID: %i, slot_id: %u color: %u done", character_id, slot_id, color); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterMaterialColor", query); return true; } bool ZoneDatabase::SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value){ std::string query = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, skill_id, value); auto results = QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterSkill for character ID: %i, skill_id:%u value:%u done", character_id, skill_id, value); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterSkill for character ID: %i, skill_id:%u value:%u done", character_id, skill_id, value); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterSkill", query); return true; } bool ZoneDatabase::SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id){ std::string query = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, slot_id, disc_id); auto results = QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u done", character_id, slot_id, disc_id); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterDisc for character ID: %i, slot:%u disc_id:%u done", character_id, slot_id, disc_id); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterDisc", query); return true; } @@ -1247,7 +1245,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 0xffffffffu){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); } } return true; @@ -1259,7 +1257,7 @@ bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_i std::string query = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%u, %u, %u, %u, %u,'%s')", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name_esc); auto results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterBandolier", query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterBandolier for character ID: %i, bandolier_id: %u, bandolier_slot: %u item_id: %u, icon:%u band_name:%s done", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterBandolier for character ID: %i, bandolier_id: %u, bandolier_slot: %u item_id: %u, icon:%u band_name:%s done", character_id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name); if (!results.RowsAffected()){ std::cout << "ERROR Bandolier Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } return true; } @@ -1267,7 +1265,7 @@ bool ZoneDatabase::SaveCharacterBandolier(uint32 character_id, uint8 bandolier_i bool ZoneDatabase::SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon) { std::string query = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%u, %u, %u, %u)", character_id, potion_id, item_id, icon); auto results = QueryDatabase(query); - ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterPotionBelt", query); + ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterPotionBelt", query); if (!results.RowsAffected()){ std::cout << "ERROR Potionbelt Save: " << results.ErrorMessage() << "\n\n" << query << "\n" << std::endl; } return true; } @@ -1577,7 +1575,7 @@ bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, Pla ); auto results = database.QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "ZoneDatabase:SaveCharacterData", query); - LogFile->write(EQEMuLog::Status, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); + LogFile->write(EQEMuLog::Debug, "ZoneDatabase::SaveCharacterData %i, done... Took %f seconds", character_id, ((float)(std::clock() - t)) / CLOCKS_PER_SEC); return true; } @@ -1619,7 +1617,7 @@ bool ZoneDatabase::SaveCharacterCurrency(uint32 character_id, PlayerProfile_Stru pp->careerEbonCrystals); auto results = database.QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterCurrency", query); - LogFile->write(EQEMuLog::Status, "Saving Currency for character ID: %i, done", character_id); + LogFile->write(EQEMuLog::Debug, "Saving Currency for character ID: %i, done", character_id); return true; } @@ -1629,7 +1627,7 @@ bool ZoneDatabase::SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 cur character_id, aa_id, current_level); auto results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "ZoneDatabase::SaveCharacterAA", rquery); - LogFile->write(EQEMuLog::Status, "Saving AA for character ID: %u, aa_id: %u current_level: %u", character_id, aa_id, current_level); + LogFile->write(EQEMuLog::Debug, "Saving AA for character ID: %u, aa_id: %u current_level: %u", character_id, aa_id, current_level); return true; } @@ -1657,6 +1655,10 @@ bool ZoneDatabase::DeleteCharacterLeadershipAAs(uint32 character_id){ std::string query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", character_id); QueryDatabase(query); return true; } +bool ZoneDatabase::DeleteCharacterAAs(uint32 character_id){ + std::string query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", character_id); QueryDatabase(query); return true; +} + bool ZoneDatabase::DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id){ std::string query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `slot_id` = %u AND `id` = %u", slot_id, character_id); QueryDatabase(query); return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 647e9bfbd..f476f543c 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -287,6 +287,7 @@ public: bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id); bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id); bool DeleteCharacterLeadershipAAs(uint32 character_id); + bool DeleteCharacterAAs(uint32 character_id); /* Character Inventory */ bool NoRentExpired(const char* name); From fee8a1214ade02a7f3209014ed9cc39bdd0d4e05 Mon Sep 17 00:00:00 2001 From: akkadius Date: Mon, 22 Sep 2014 02:52:23 -0500 Subject: [PATCH 55/56] Putting back in demonstar's lowercase check --- world/client.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index cd028d409..ca90b1f46 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -489,10 +489,20 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) outapp->size = 1; bool valid = false; - if(!database.CheckNameFilter(char_name)) { valid = false; } - else if (char_name[0] < 'A' && char_name[0] > 'Z') { valid = false; } /* Name must begin with an upper-case letter. */ - else if (database.ReserveName(GetAccountID(), char_name)) { valid = true; } - else { valid = false; } + if(!database.CheckNameFilter(char_name)) { + valid = false; + } + /* Name must begin with an upper-case letter. */ + else if (islower(char_name[0])) { + valid = false; + } + else if (database.ReserveName(GetAccountID(), char_name)) { + valid = true; + } + else { + valid = false; + } + outapp->pBuffer[0] = valid? 1 : 0; QueuePacket(outapp); safe_delete(outapp); From 1170b57fd59e43caa215993bbf28c072220fc729 Mon Sep 17 00:00:00 2001 From: akkadius Date: Mon, 22 Sep 2014 16:23:43 -0500 Subject: [PATCH 56/56] Fix starting items for starting_item entries that use slot -1 to find a free slot --- common/database.cpp | 21 ++++++++++++++++----- common/shareddb.cpp | 6 +++--- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 7f7af3f2c..ed90b9a79 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -708,7 +708,9 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe /* This only for new Character creation storing */ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) { - uint32 charid = 0; char zone[50]; float x, y, z; + uint32 charid = 0; + char zone[50]; + float x, y, z; charid = GetCharacterID(pp->name); if(!charid) { @@ -739,7 +741,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", charid, i, newinv->GetItem()->ID, newinv->GetCharges(), newinv->GetColor()); - auto results = QueryDatabase(invquery); + auto results = QueryDatabase(invquery); if (!results.RowsAffected()) LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery.c_str(), results.ErrorMessage().c_str()); @@ -749,9 +751,18 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven #endif } - if (i == MainCursor) { i = EmuConstants::GENERAL_BAGS_BEGIN; continue; } - else if (i == EmuConstants::CURSOR_BAG_END) { i = EmuConstants::BANK_BEGIN; continue; } - else if (i == EmuConstants::BANK_END) { i = EmuConstants::BANK_BAGS_BEGIN; continue; } + if (i == MainCursor) { + i = EmuConstants::GENERAL_BAGS_BEGIN; + continue; + } + else if (i == EmuConstants::CURSOR_BAG_END) { + i = EmuConstants::BANK_BEGIN; + continue; + } + else if (i == EmuConstants::BANK_END) { + i = EmuConstants::BANK_BAGS_BEGIN; + continue; + } i++; } return true; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 69c97b5f0..aecfa0488 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -347,8 +347,8 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { const Item_Struct* myitem; uint32 itemid = 0; - uint32 charges = 0; - uint32 slot = 0; + int32 charges = 0; + int32 slot = 0; auto query = StringFormat( "SELECT `itemid`, `item_charges`, `slot` FROM `starting_items`" " WHERE (`race` = %i OR `race` = 0)" @@ -363,7 +363,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, charges = atoi(row[1]); slot = atoi(row[2]); myitem = GetItem(itemid); - if(!myitem) + if(!myitem) continue; ItemInst* myinst = CreateBaseItem(myitem, charges); if(slot < 0)