From e390531dcd24579e9c8e8cf260658dcaa9b36bc0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 11 Sep 2014 03:14:34 -0500 Subject: [PATCH] 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; }