mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
[Bug Fix] Fix issue where you can set your title to titles you don't have. (#1917)
* [Bug Fix] Fix issue where you can set your title to titles you don't have. * Fixes. * Fix missing logic check for HasTitle Co-authored-by: Natedog2012 <jwalters_06@yahoo.com>
This commit is contained in:
parent
58d5983ef1
commit
7b235a6ede
@ -12838,17 +12838,15 @@ void Client::Handle_OP_SetTitle(const EQApplicationPacket *app)
|
|||||||
|
|
||||||
SetTitle_Struct *sts = (SetTitle_Struct *)app->pBuffer;
|
SetTitle_Struct *sts = (SetTitle_Struct *)app->pBuffer;
|
||||||
|
|
||||||
std::string Title;
|
if (!title_manager.HasTitle(this, sts->title_id)) {
|
||||||
|
return;
|
||||||
if (!sts->is_suffix)
|
|
||||||
{
|
|
||||||
Title = title_manager.GetPrefix(sts->title_id);
|
|
||||||
SetAATitle(Title.c_str());
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
std::string title = !sts->is_suffix ? title_manager.GetPrefix(sts->title_id) : title_manager.GetSuffix(sts->title_id);
|
||||||
Title = title_manager.GetSuffix(sts->title_id);
|
if (!sts->is_suffix) {
|
||||||
SetTitleSuffix(Title.c_str());
|
SetAATitle(title.c_str());
|
||||||
|
} else {
|
||||||
|
SetTitleSuffix(title.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
540
zone/titles.cpp
540
zone/titles.cpp
@ -19,6 +19,7 @@
|
|||||||
#include "../common/eq_packet_structs.h"
|
#include "../common/eq_packet_structs.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
#include "../common/misc_functions.h"
|
#include "../common/misc_functions.h"
|
||||||
|
#include "../common/repositories/titles_repository.h"
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
@ -34,206 +35,191 @@ TitleManager::TitleManager() {
|
|||||||
|
|
||||||
bool TitleManager::LoadTitles()
|
bool TitleManager::LoadTitles()
|
||||||
{
|
{
|
||||||
Titles.clear();
|
titles.clear();
|
||||||
|
|
||||||
std::string query = "SELECT `id`, `skill_id`, `min_skill_value`, `max_skill_value`, "
|
std::string query = "SELECT `id`, `skill_id`, `min_skill_value`, `max_skill_value`, "
|
||||||
"`min_aa_points`, `max_aa_points`, `class`, `gender`, `char_id`, "
|
"`min_aa_points`, `max_aa_points`, `class`, `gender`, `char_id`, "
|
||||||
"`status`, `item_id`, `prefix`, `suffix`, `title_set` FROM titles";
|
"`status`, `item_id`, `prefix`, `suffix`, `title_set` FROM titles";
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success() || !results.RowCount()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row : results) {
|
||||||
TitleEntry Title;
|
TitleEntry title;
|
||||||
Title.TitleID = atoi(row[0]);
|
title.title_id = std::stoi(row[0]);
|
||||||
Title.SkillID = (EQ::skills::SkillType) atoi(row[1]);
|
title.skill_id = (EQ::skills::SkillType) std::stoi(row[1]);
|
||||||
Title.MinSkillValue = atoi(row[2]);
|
title.min_skill_value = std::stoi(row[2]);
|
||||||
Title.MaxSkillValue = atoi(row[3]);
|
title.max_skill_value = std::stoi(row[3]);
|
||||||
Title.MinAAPoints = atoi(row[4]);
|
title.min_aa_points = std::stoi(row[4]);
|
||||||
Title.MaxAAPoints = atoi(row[5]);
|
title.max_aa_points = std::stoi(row[5]);
|
||||||
Title.Class = atoi(row[6]);
|
title.class_id = std::stoi(row[6]);
|
||||||
Title.Gender = atoi(row[7]);
|
title.gender_id = std::stoi(row[7]);
|
||||||
Title.CharID = atoi(row[8]);
|
title.character_id = std::stoi(row[8]);
|
||||||
Title.Status = atoi(row[9]);
|
title.status = std::stoi(row[9]);
|
||||||
Title.ItemID = atoi(row[10]);
|
title.item_id = std::stoi(row[10]);
|
||||||
Title.Prefix = row[11];
|
title.prefix = row[11];
|
||||||
Title.Suffix = row[12];
|
title.suffix = row[12];
|
||||||
Title.TitleSet = atoi(row[13]);
|
title.titleset = std::stoi(row[13]);
|
||||||
Titles.push_back(Title);
|
titles.push_back(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EQApplicationPacket *TitleManager::MakeTitlesPacket(Client *c)
|
EQApplicationPacket *TitleManager::MakeTitlesPacket(Client *client)
|
||||||
{
|
{
|
||||||
std::vector<TitleEntry>::iterator Iterator;
|
std::vector<TitleEntry> available_titles;
|
||||||
|
uint32 length = 4;
|
||||||
std::vector<TitleEntry> AvailableTitles;
|
for (const auto& title : titles) {
|
||||||
|
if (!IsClientEligibleForTitle(client, title)) {
|
||||||
uint32 Length = 4;
|
|
||||||
|
|
||||||
Iterator = Titles.begin();
|
|
||||||
|
|
||||||
while(Iterator != Titles.end())
|
|
||||||
{
|
|
||||||
if(!IsClientEligibleForTitle(c, Iterator))
|
|
||||||
{
|
|
||||||
++Iterator;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvailableTitles.push_back((*Iterator));
|
available_titles.push_back(title);
|
||||||
|
length += title.prefix.length() + title.suffix.length() + 6;
|
||||||
Length += Iterator->Prefix.length() + Iterator->Suffix.length() + 6;
|
|
||||||
|
|
||||||
++Iterator;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_SendTitleList, Length);
|
auto outapp = new EQApplicationPacket(OP_SendTitleList, length);
|
||||||
|
char *buffer = (char *)outapp->pBuffer;
|
||||||
char *Buffer = (char *)outapp->pBuffer;
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, available_titles.size());
|
||||||
|
for (const auto& available_title : available_titles) {
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, AvailableTitles.size());
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, available_title.title_id);
|
||||||
|
VARSTRUCT_ENCODE_STRING(buffer, available_title.prefix.c_str());
|
||||||
Iterator = AvailableTitles.begin();
|
VARSTRUCT_ENCODE_STRING(buffer, available_title.suffix.c_str());
|
||||||
|
|
||||||
while(Iterator != AvailableTitles.end())
|
|
||||||
{
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, Iterator->TitleID);
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(Buffer, Iterator->Prefix.c_str());
|
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_STRING(Buffer, Iterator->Suffix.c_str());
|
|
||||||
|
|
||||||
++Iterator;
|
|
||||||
}
|
}
|
||||||
return(outapp);
|
return(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TitleManager::NumberOfAvailableTitles(Client *c)
|
int TitleManager::NumberOfAvailableTitles(Client *client)
|
||||||
{
|
{
|
||||||
int Count = 0;
|
int count = 0;
|
||||||
|
for (const auto& title : titles) {
|
||||||
std::vector<TitleEntry>::iterator Iterator;
|
if (IsClientEligibleForTitle(client, title)) {
|
||||||
|
++count;
|
||||||
Iterator = Titles.begin();
|
|
||||||
|
|
||||||
while(Iterator != Titles.end())
|
|
||||||
{
|
|
||||||
if(IsClientEligibleForTitle(c, Iterator))
|
|
||||||
++Count;
|
|
||||||
|
|
||||||
++Iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TitleManager::GetPrefix(int TitleID)
|
|
||||||
{
|
|
||||||
std::vector<TitleEntry>::iterator Iterator;
|
|
||||||
|
|
||||||
Iterator = Titles.begin();
|
|
||||||
|
|
||||||
while(Iterator != Titles.end())
|
|
||||||
{
|
|
||||||
if((*Iterator).TitleID == TitleID)
|
|
||||||
return (*Iterator).Prefix;
|
|
||||||
|
|
||||||
++Iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TitleManager::GetSuffix(int TitleID)
|
|
||||||
{
|
|
||||||
std::vector<TitleEntry>::iterator Iterator;
|
|
||||||
|
|
||||||
Iterator = Titles.begin();
|
|
||||||
|
|
||||||
while(Iterator != Titles.end())
|
|
||||||
{
|
|
||||||
if((*Iterator).TitleID == TitleID)
|
|
||||||
return (*Iterator).Suffix;
|
|
||||||
|
|
||||||
++Iterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TitleManager::IsClientEligibleForTitle(Client *c, std::vector<TitleEntry>::iterator Title)
|
|
||||||
{
|
|
||||||
if((Title->CharID >= 0) && (c->CharacterID() != static_cast<uint32>(Title->CharID)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((Title->Status >= 0) && (c->Admin() < Title->Status))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((Title->Gender >= 0) && (c->GetBaseGender() != Title->Gender))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((Title->Class >= 0) && (c->GetBaseClass() != Title->Class))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((Title->MinAAPoints >= 0) && (c->GetSpentAA() < static_cast<uint32>(Title->MinAAPoints)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((Title->MaxAAPoints >= 0) && (c->GetSpentAA() > static_cast<uint32>(Title->MaxAAPoints)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(Title->SkillID >= 0)
|
|
||||||
{
|
|
||||||
if ((Title->MinSkillValue >= 0) && (c->GetRawSkill(static_cast<EQ::skills::SkillType>(Title->SkillID)) < static_cast<uint32>(Title->MinSkillValue)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ((Title->MaxSkillValue >= 0) && (c->GetRawSkill(static_cast<EQ::skills::SkillType>(Title->SkillID)) > static_cast<uint32>(Title->MaxSkillValue)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((Title->ItemID >= 1) && (c->GetInv().HasItem(Title->ItemID, 0, 0xFF) == INVALID_INDEX))
|
return count;
|
||||||
return false;
|
|
||||||
|
|
||||||
if((Title->TitleSet > 0) && (!c->CheckTitle(Title->TitleSet)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TitleManager::IsNewAATitleAvailable(int AAPoints, int Class)
|
std::string TitleManager::GetPrefix(int title_id)
|
||||||
{
|
{
|
||||||
std::vector<TitleEntry>::iterator Iterator;
|
if (!title_id) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
Iterator = Titles.begin();
|
for (const auto& title : titles) {
|
||||||
|
if (title.title_id == title_id) {
|
||||||
|
return title.prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(Iterator != Titles.end())
|
return "";
|
||||||
{
|
}
|
||||||
if((((*Iterator).Class == -1) || ((*Iterator).Class == Class)) && ((*Iterator).MinAAPoints == AAPoints))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
++Iterator;
|
std::string TitleManager::GetSuffix(int title_id)
|
||||||
|
{
|
||||||
|
if (!title_id) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& title : titles) {
|
||||||
|
if (title.title_id == title_id) {
|
||||||
|
return title.suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TitleManager::HasTitle(Client* client, uint32 title_id)
|
||||||
|
{
|
||||||
|
if (!client || !title_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& title : titles) {
|
||||||
|
if (title.title_id == title_id) {
|
||||||
|
return IsClientEligibleForTitle(client, title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TitleManager::IsNewTradeSkillTitleAvailable(int SkillID, int SkillValue)
|
bool TitleManager::IsClientEligibleForTitle(Client *client, TitleEntry title)
|
||||||
{
|
{
|
||||||
std::vector<TitleEntry>::iterator Iterator;
|
if (!client) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Iterator = Titles.begin();
|
if (title.character_id >= 0 && client->CharacterID() != static_cast<uint32>(title.character_id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
while(Iterator != Titles.end())
|
if (title.status >= 0 && client->Admin() < title.status) {
|
||||||
{
|
return false;
|
||||||
if(((*Iterator).SkillID == SkillID) && ((*Iterator).MinSkillValue == SkillValue))
|
}
|
||||||
|
|
||||||
|
if (title.gender_id >= 0 && client->GetBaseGender() != title.gender_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.class_id >= 0 && client->GetBaseClass() != title.class_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.min_aa_points >= 0 && client->GetSpentAA() < title.min_aa_points) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.max_aa_points >= 0 && client->GetSpentAA() > title.max_aa_points) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.skill_id >= 0) {
|
||||||
|
auto skill_id = static_cast<EQ::skills::SkillType>(title.skill_id);
|
||||||
|
if (title.min_skill_value >= 0 && client->GetRawSkill(skill_id) < static_cast<uint32>(title.min_skill_value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.max_skill_value >= 0 && client->GetRawSkill(skill_id) > static_cast<uint32>(title.max_skill_value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.item_id >= 1 && client->GetInv().HasItem(title.item_id) == INVALID_INDEX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title.titleset > 0 && !client->CheckTitle(title.titleset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TitleManager::IsNewAATitleAvailable(int aa_points, int class_id)
|
||||||
|
{
|
||||||
|
for (const auto& title : titles) {
|
||||||
|
if (
|
||||||
|
(title.class_id == -1 || title.class_id == class_id) &&
|
||||||
|
title.min_aa_points == aa_points
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
++Iterator;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TitleManager::IsNewTradeSkillTitleAvailable(int skill_id, int skill_value)
|
||||||
|
{
|
||||||
|
for (const auto& title : titles) {
|
||||||
|
if (title.skill_id == skill_id && title.min_skill_value == skill_value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -241,142 +227,138 @@ bool TitleManager::IsNewTradeSkillTitleAvailable(int SkillID, int SkillValue)
|
|||||||
|
|
||||||
void TitleManager::CreateNewPlayerTitle(Client *client, const char *title)
|
void TitleManager::CreateNewPlayerTitle(Client *client, const char *title)
|
||||||
{
|
{
|
||||||
if(!client || !title)
|
if (!client || !title) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
auto escTitle = new char[strlen(title) * 2 + 1];
|
|
||||||
|
|
||||||
client->SetAATitle(title);
|
client->SetAATitle(title);
|
||||||
|
|
||||||
database.DoEscapeString(escTitle, title, strlen(title));
|
auto query = fmt::format(
|
||||||
auto query = StringFormat("SELECT `id` FROM titles "
|
"SELECT `id` FROM titles WHERE `prefix` = '{}' AND char_id = {}",
|
||||||
"WHERE `prefix` = '%s' AND char_id = %i",
|
EscapeString(title),
|
||||||
escTitle, client->CharacterID());
|
client->CharacterID()
|
||||||
auto results = database.QueryDatabase(query);
|
);
|
||||||
if (results.Success() && results.RowCount() > 0){
|
auto results = database.QueryDatabase(query);
|
||||||
safe_delete_array(escTitle);
|
if (results.Success() && results.RowCount()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
query = StringFormat("INSERT INTO titles (`char_id`, `prefix`) VALUES(%i, '%s')",
|
query = fmt::format(
|
||||||
client->CharacterID(), escTitle);
|
"INSERT INTO titles (`char_id`, `prefix`) VALUES ({}, '{}')",
|
||||||
safe_delete_array(escTitle);
|
client->CharacterID(),
|
||||||
results = database.QueryDatabase(query);
|
EscapeString(title)
|
||||||
if(!results.Success()) {
|
);
|
||||||
return;
|
results = database.QueryDatabase(query);
|
||||||
}
|
if (!results.Success()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_ReloadTitles, 0);
|
auto pack = new ServerPacket(ServerOP_ReloadTitles, 0);
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix)
|
void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix)
|
||||||
{
|
{
|
||||||
if(!client || !suffix)
|
if (!client || !suffix) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
client->SetTitleSuffix(suffix);
|
|
||||||
|
|
||||||
auto escSuffix = new char[strlen(suffix) * 2 + 1];
|
|
||||||
database.DoEscapeString(escSuffix, suffix, strlen(suffix));
|
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT `id` FROM titles "
|
|
||||||
"WHERE `suffix` = '%s' AND char_id = %i",
|
|
||||||
escSuffix, client->CharacterID());
|
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
if (results.Success() && results.RowCount() > 0) {
|
|
||||||
safe_delete_array(escSuffix);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
query = StringFormat("INSERT INTO titles (`char_id`, `suffix`) VALUES(%i, '%s')",
|
|
||||||
client->CharacterID(), escSuffix);
|
|
||||||
safe_delete_array(escSuffix);
|
|
||||||
results = database.QueryDatabase(query);
|
|
||||||
if(!results.Success()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_ReloadTitles, 0);
|
|
||||||
worldserver.SendPacket(pack);
|
|
||||||
safe_delete(pack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::SetAATitle(const char *Title)
|
|
||||||
{
|
|
||||||
strn0cpy(m_pp.title, Title, sizeof(m_pp.title));
|
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct));
|
|
||||||
|
|
||||||
SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer;
|
|
||||||
|
|
||||||
strn0cpy(strs->title, Title, sizeof(strs->title));
|
|
||||||
|
|
||||||
strs->entity_id = GetID();
|
|
||||||
|
|
||||||
entity_list.QueueClients(this, outapp, false);
|
|
||||||
|
|
||||||
safe_delete(outapp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::SetTitleSuffix(const char *Suffix)
|
|
||||||
{
|
|
||||||
strn0cpy(m_pp.suffix, Suffix, sizeof(m_pp.suffix));
|
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct));
|
|
||||||
|
|
||||||
SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer;
|
|
||||||
|
|
||||||
strs->is_suffix = 1;
|
|
||||||
|
|
||||||
strn0cpy(strs->title, Suffix, sizeof(strs->title));
|
|
||||||
|
|
||||||
strs->entity_id = GetID();
|
|
||||||
|
|
||||||
entity_list.QueueClients(this, outapp, false);
|
|
||||||
|
|
||||||
safe_delete(outapp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::EnableTitle(int titleSet) {
|
|
||||||
|
|
||||||
if (CheckTitle(titleSet))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string query = StringFormat("INSERT INTO player_titlesets "
|
|
||||||
"(char_id, title_set) VALUES (%i, %i)",
|
|
||||||
CharacterID(), titleSet);
|
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
if(!results.Success())
|
|
||||||
LogError("Error in EnableTitle query for titleset [{}] and charid [{}]", titleSet, CharacterID());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Client::CheckTitle(int titleSet) {
|
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT `id` FROM player_titlesets "
|
|
||||||
"WHERE `title_set`=%i AND `char_id`=%i LIMIT 1",
|
|
||||||
titleSet, CharacterID());
|
|
||||||
auto results = database.QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.RowCount() == 0)
|
client->SetTitleSuffix(suffix);
|
||||||
return false;
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"SELECT `id` FROM titles WHERE `suffix` = '{}' AND char_id = {}",
|
||||||
|
EscapeString(suffix),
|
||||||
|
client->CharacterID()
|
||||||
|
);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (results.Success() && results.RowCount()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
query = fmt::format(
|
||||||
|
"INSERT INTO titles (`char_id`, `suffix`) VALUES ({}, '{}')",
|
||||||
|
client->CharacterID(),
|
||||||
|
EscapeString(suffix)
|
||||||
|
);
|
||||||
|
results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pack = new ServerPacket(ServerOP_ReloadTitles, 0);
|
||||||
|
worldserver.SendPacket(pack);
|
||||||
|
safe_delete(pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SetAATitle(const char *title)
|
||||||
|
{
|
||||||
|
strn0cpy(m_pp.title, title, sizeof(m_pp.title));
|
||||||
|
auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct));
|
||||||
|
SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer;
|
||||||
|
strn0cpy(strs->title, title, sizeof(strs->title));
|
||||||
|
strs->entity_id = GetID();
|
||||||
|
entity_list.QueueClients(this, outapp, false);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::SetTitleSuffix(const char *suffix)
|
||||||
|
{
|
||||||
|
strn0cpy(m_pp.suffix, suffix, sizeof(m_pp.suffix));
|
||||||
|
auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct));
|
||||||
|
SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer;
|
||||||
|
strs->is_suffix = 1;
|
||||||
|
strn0cpy(strs->title, suffix, sizeof(strs->title));
|
||||||
|
strs->entity_id = GetID();
|
||||||
|
entity_list.QueueClients(this, outapp, false);
|
||||||
|
safe_delete(outapp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::EnableTitle(int title_set)
|
||||||
|
{
|
||||||
|
if (CheckTitle(title_set)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"INSERT INTO player_titlesets (char_id, title_set) VALUES ({}, {})",
|
||||||
|
CharacterID(),
|
||||||
|
title_set
|
||||||
|
);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
LogError("Error in EnableTitle query for titleset [{}] and charid [{}]", title_set, CharacterID());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::CheckTitle(int title_set)
|
||||||
|
{
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"SELECT `id` FROM player_titlesets WHERE `title_set` = {} AND `char_id` = {} LIMIT 1",
|
||||||
|
title_set,
|
||||||
|
CharacterID()
|
||||||
|
);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success() || !results.RowCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::RemoveTitle(int titleSet) {
|
void Client::RemoveTitle(int title_set)
|
||||||
|
{
|
||||||
if (!CheckTitle(titleSet))
|
if (!CheckTitle(title_set)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string query = StringFormat("DELETE FROM player_titlesets "
|
TitlesRepository::DeleteWhere(
|
||||||
"WHERE `title_set` = %i AND `char_id` = %i",
|
database,
|
||||||
titleSet, CharacterID());
|
fmt::format(
|
||||||
database.QueryDatabase(query);
|
"`title_set` = {} AND `char_id` = {}",
|
||||||
|
title_set,
|
||||||
|
CharacterID()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,20 +25,20 @@ class EQApplicationPacket;
|
|||||||
|
|
||||||
struct TitleEntry
|
struct TitleEntry
|
||||||
{
|
{
|
||||||
int TitleID;
|
int title_id;
|
||||||
int SkillID;
|
int skill_id;
|
||||||
int MinSkillValue;
|
int min_skill_value;
|
||||||
int MaxSkillValue;
|
int max_skill_value;
|
||||||
int MinAAPoints;
|
int min_aa_points;
|
||||||
int MaxAAPoints;
|
int max_aa_points;
|
||||||
int Class;
|
int class_id;
|
||||||
int Gender;
|
int gender_id;
|
||||||
int CharID;
|
int character_id;
|
||||||
int Status;
|
int status;
|
||||||
int ItemID;
|
int item_id;
|
||||||
std::string Prefix;
|
std::string prefix;
|
||||||
std::string Suffix;
|
std::string suffix;
|
||||||
int TitleSet;
|
int titleset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TitleManager
|
class TitleManager
|
||||||
@ -48,18 +48,19 @@ public:
|
|||||||
|
|
||||||
bool LoadTitles();
|
bool LoadTitles();
|
||||||
|
|
||||||
EQApplicationPacket *MakeTitlesPacket(Client *c);
|
EQApplicationPacket *MakeTitlesPacket(Client *client);
|
||||||
std::string GetPrefix(int TitleID);
|
std::string GetPrefix(int title_id);
|
||||||
std::string GetSuffix(int TitleID);
|
std::string GetSuffix(int title_id);
|
||||||
int NumberOfAvailableTitles(Client *c);
|
int NumberOfAvailableTitles(Client *client);
|
||||||
bool IsClientEligibleForTitle(Client *c, std::vector<TitleEntry>::iterator Title);
|
bool IsClientEligibleForTitle(Client *client, TitleEntry title);
|
||||||
bool IsNewAATitleAvailable(int AAPoints, int Class);
|
bool IsNewAATitleAvailable(int aa_points, int class_id);
|
||||||
bool IsNewTradeSkillTitleAvailable(int SkillID, int SkillValue);
|
bool IsNewTradeSkillTitleAvailable(int skill_id, int skill_value);
|
||||||
void CreateNewPlayerTitle(Client *c, const char *Title);
|
void CreateNewPlayerTitle(Client *client, const char *title);
|
||||||
void CreateNewPlayerSuffix(Client *c, const char *Suffix);
|
void CreateNewPlayerSuffix(Client *client, const char *suffix);
|
||||||
|
bool HasTitle(Client* client, uint32 title_id);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<TitleEntry> Titles;
|
std::vector<TitleEntry> titles;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TitleManager title_manager;
|
extern TitleManager title_manager;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user