1
0

Fix Issue #3 - Class Updates, Name Updates to LS

Support added for class updates to LoginServer when adventure class is updated (such as commoner to sub class, so on).

Name change for GM command /name support added for LS update.  This is a use at your own risk command and you will have to /camp to fully reflect your name update.
This commit is contained in:
Emagi 2025-04-11 09:49:18 -04:00
parent 20c1d1cc8a
commit 1268ecbc94
7 changed files with 51 additions and 5 deletions

View File

@ -421,6 +421,21 @@ bool LWorld::Process() {
} }
break; break;
} }
case ServerOP_NameCharUpdate: {
CharNameUpdate_Struct* cnu = (CharNameUpdate_Struct*) pack->pBuffer;
if (cnu->name_length > 0 && cnu->name_length < 64) {
char name_buffer[64];
// Copy up to name_length characters from cnu->new_name
strncpy(name_buffer, cnu->new_name, cnu->name_length);
// Null-terminate the string just in case
name_buffer[cnu->name_length] = '\0';
database.UpdateCharacterName(cnu->account_id,cnu->char_id,name_buffer,this->GetAccountID());
}
break;
}
case ServerOP_LSInfo: { case ServerOP_LSInfo: {
if (pack->size != sizeof(ServerLSInfo_Struct)) { if (pack->size != sizeof(ServerLSInfo_Struct)) {
this->Kick(ERROR_BADVERSION); this->Kick(ERROR_BADVERSION);

View File

@ -617,6 +617,19 @@ bool LoginDatabase::UpdateCharacterGender(int32 account_id, int32 character_id,
return true; return true;
} }
bool LoginDatabase::UpdateCharacterName(int32 account_id, int32 character_id, char* newName, int32 server_id){
Query query;
string update_charts = string("update login_characters set name='%s' where char_id=%lu and account_id=%lu and server_id=%lu");
query.RunQuery2(Q_UPDATE, update_charts.c_str(),newName,character_id,account_id,server_id);
if(!query.GetAffectedRows())
{
LogWrite(LOGIN__ERROR, 0, "Login", "Error in UpdateCharacterName query '%s': %s", query.GetQuery(), query.GetError());
return false;
}
return true;
}
LoginAccount* LoginDatabase::LoadAccount(const char* name, const char* password, bool attemptAccountCreation){ LoginAccount* LoginDatabase::LoadAccount(const char* name, const char* password, bool attemptAccountCreation){
LoginAccount* acct = NULL; LoginAccount* acct = NULL;
Query query; Query query;

View File

@ -59,6 +59,7 @@ public:
bool UpdateCharacterLevel(int32 account_id, int32 character_id, int8 in_level, int32 server_id); bool UpdateCharacterLevel(int32 account_id, int32 character_id, int8 in_level, int32 server_id);
bool UpdateCharacterRace(int32 account_id, int32 character_id, int16 in_racetype, int8 in_race, int32 server_id); bool UpdateCharacterRace(int32 account_id, int32 character_id, int16 in_racetype, int8 in_race, int32 server_id);
bool UpdateCharacterClass(int32 account_id, int32 character_id, int8 in_class, int32 server_id); bool UpdateCharacterClass(int32 account_id, int32 character_id, int8 in_class, int32 server_id);
bool UpdateCharacterName(int32 account_id, int32 character_id, char* newName, int32 server_id);
bool UpdateCharacterZone(int32 account_id, int32 character_id, int32 zone_id, int32 server_id); bool UpdateCharacterZone(int32 account_id, int32 character_id, int32 zone_id, int32 server_id);
bool UpdateCharacterGender(int32 account_id, int32 character_id, int8 in_gender, int32 server_id); bool UpdateCharacterGender(int32 account_id, int32 character_id, int8 in_gender, int32 server_id);
int32 GetRaceID(char* name); int32 GetRaceID(char* name);

View File

@ -2896,7 +2896,6 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
case COMMAND_CLASS:{ case COMMAND_CLASS:{
if(sep && sep->arg[ndx][0]){ if(sep && sep->arg[ndx][0]){
client->GetPlayer()->SetPlayerAdventureClass(atoi(sep->arg[ndx])); client->GetPlayer()->SetPlayerAdventureClass(atoi(sep->arg[ndx]));
client->UpdateTimeStampFlag ( CLASS_UPDATE_FLAG );
}else }else
client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /class {class_id}"); client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /class {class_id}");
break; break;
@ -3205,9 +3204,12 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
break; break;
} }
case COMMAND_NAME:{ case COMMAND_NAME:{
if(sep && sep->arg[ndx][0]){ if(sep && sep->arg[0]){
client->GetPlayer()->GetInfoStruct()->set_name(std::string(sep->arg[ndx]).substr(0,39)); client->GetPlayer()->GetInfoStruct()->set_name(sep->argplus[0]);
client->GetPlayer()->SetCharSheetChanged(true); client->GetPlayer()->SetCharSheetChanged(true);
client->GetPlayer()->info_changed = true;
client->GetPlayer()->GetZone()->AddChangedSpawn(client->GetPlayer());
client->UpdateTimeStampFlag ( NAME_UPDATE_FLAG );
}else }else
client->Message(CHANNEL_COLOR_YELLOW,"Usage: /name {new_name}"); client->Message(CHANNEL_COLOR_YELLOW,"Usage: /name {new_name}");

View File

@ -6375,6 +6375,8 @@ void Player::SetPlayerAdventureClass(int8 new_class){
charsheet_changed = true; charsheet_changed = true;
if(GetZone()) if(GetZone())
GetZone()->TriggerCharSheetTimer(); GetZone()->TriggerCharSheetTimer();
if(GetClient())
GetClient()->UpdateTimeStampFlag ( CLASS_UPDATE_FLAG );
} }
void Player::AddSkillBonus(int32 spell_id, int32 skill_id, float value) { void Player::AddSkillBonus(int32 spell_id, int32 skill_id, float value) {

View File

@ -4391,7 +4391,10 @@ void WorldDatabase::Save(Client* client){
else if(client->GetCurrentZone()) else if(client->GetCurrentZone())
zone_id = client->GetCurrentZone()->GetZoneID(); zone_id = client->GetCurrentZone()->GetZoneID();
query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update characters set current_zone_id=%u, x=%f, y=%f, z=%f, heading=%f, level=%i,instance_id=%i,last_saved=%i, `class`=%i, `tradeskill_level`=%i, `tradeskill_class`=%i, `group_id`=%u, deity = %u, alignment = %u, zone_duplicating_id = %u where id = %u", zone_id, player->GetX(), player->GetY(), player->GetZ(), player->GetHeading(), player->GetLevel(), instance_id, client->GetLastSavedTimeStamp(), client->GetPlayer()->GetAdventureClass(), client->GetPlayer()->GetTSLevel(), client->GetPlayer()->GetTradeskillClass(), client->GetPlayer()->GetGroupMemberInfo() ? client->GetPlayer()->GetGroupMemberInfo()->group_id : client->GetRejoinGroupID(), client->GetPlayer()->GetDeity(), client->GetPlayer()->GetInfoStruct()->get_alignment(), client->GetDuplicatingZoneID(), client->GetCharacterID()); char charName[64];
strncpy(charName, client->GetPlayer()->GetInfoStruct()->get_name().c_str(),64);
charName[63] = '\0';
query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update characters set name='%s',current_zone_id=%u, x=%f, y=%f, z=%f, heading=%f, level=%i,instance_id=%i,last_saved=%i, `class`=%i, `tradeskill_level`=%i, `tradeskill_class`=%i, `group_id`=%u, deity = %u, alignment = %u, zone_duplicating_id = %u where id = %u", charName, zone_id, player->GetX(), player->GetY(), player->GetZ(), player->GetHeading(), player->GetLevel(), instance_id, client->GetLastSavedTimeStamp(), client->GetPlayer()->GetAdventureClass(), client->GetPlayer()->GetTSLevel(), client->GetPlayer()->GetTradeskillClass(), client->GetPlayer()->GetGroupMemberInfo() ? client->GetPlayer()->GetGroupMemberInfo()->group_id : client->GetRejoinGroupID(), client->GetPlayer()->GetDeity(), client->GetPlayer()->GetInfoStruct()->get_alignment(), client->GetDuplicatingZoneID(), client->GetCharacterID());
query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update character_details set hp=%u, power=%u, str=%i, sta=%i, agi=%i, wis=%i, intel=%i, heat=%i, cold=%i, magic=%i, mental=%i, divine=%i, disease=%i, poison=%i, coin_copper=%u, coin_silver=%u, coin_gold=%u, coin_plat=%u, max_hp = %u, max_power=%u, xp = %u, xp_needed = %u, xp_debt = %f, xp_vitality = %f, tradeskill_xp = %u, tradeskill_xp_needed = %u, tradeskill_xp_vitality = %f, bank_copper = %u, bank_silver = %u, bank_gold = %u, bank_plat = %u, status_points = %u, bind_zone_id=%u, bind_x = %f, bind_y = %f, bind_z = %f, bind_heading = %f, house_zone_id=%u, combat_voice = %i, emote_voice = %i, biography='%s', flags=%u, flags2=%u, last_name='%s', assigned_aa = %i, unassigned_aa = %i, tradeskill_aa = %i, unassigned_tradeskill_aa = %i, prestige_aa = %i, unassigned_prestige_aa = %i, tradeskill_prestige_aa = %i, unassigned_tradeskill_prestige_aa = %i, pet_name = '%s' where char_id = %u", query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update character_details set hp=%u, power=%u, str=%i, sta=%i, agi=%i, wis=%i, intel=%i, heat=%i, cold=%i, magic=%i, mental=%i, divine=%i, disease=%i, poison=%i, coin_copper=%u, coin_silver=%u, coin_gold=%u, coin_plat=%u, max_hp = %u, max_power=%u, xp = %u, xp_needed = %u, xp_debt = %f, xp_vitality = %f, tradeskill_xp = %u, tradeskill_xp_needed = %u, tradeskill_xp_vitality = %f, bank_copper = %u, bank_silver = %u, bank_gold = %u, bank_plat = %u, status_points = %u, bind_zone_id=%u, bind_x = %f, bind_y = %f, bind_z = %f, bind_heading = %f, house_zone_id=%u, combat_voice = %i, emote_voice = %i, biography='%s', flags=%u, flags2=%u, last_name='%s', assigned_aa = %i, unassigned_aa = %i, tradeskill_aa = %i, unassigned_tradeskill_aa = %i, prestige_aa = %i, unassigned_prestige_aa = %i, tradeskill_prestige_aa = %i, unassigned_tradeskill_prestige_aa = %i, pet_name = '%s' where char_id = %u",
player->GetHP(), player->GetPower(), player->GetStrBase(), player->GetStaBase(), player->GetAgiBase(), player->GetWisBase(), player->GetIntBase(), player->GetHeatResistanceBase(), player->GetColdResistanceBase(), player->GetMagicResistanceBase(), player->GetHP(), player->GetPower(), player->GetStrBase(), player->GetStaBase(), player->GetAgiBase(), player->GetWisBase(), player->GetIntBase(), player->GetHeatResistanceBase(), player->GetColdResistanceBase(), player->GetMagicResistanceBase(),
player->GetMentalResistanceBase(), player->GetDivineResistanceBase(), player->GetDiseaseResistanceBase(), player->GetPoisonResistanceBase(), player->GetCoinsCopper(), player->GetCoinsSilver(), player->GetCoinsGold(), player->GetCoinsPlat(), player->GetTotalHPBase(), player->GetTotalPowerBase(), player->GetXP(), player->GetNeededXP(), player->GetXPDebt(), player->GetXPVitality(), player->GetTSXP(), player->GetNeededTSXP(), player->GetTSXPVitality(), player->GetBankCoinsCopper(), player->GetMentalResistanceBase(), player->GetDivineResistanceBase(), player->GetDiseaseResistanceBase(), player->GetPoisonResistanceBase(), player->GetCoinsCopper(), player->GetCoinsSilver(), player->GetCoinsGold(), player->GetCoinsPlat(), player->GetTotalHPBase(), player->GetTotalPowerBase(), player->GetXP(), player->GetNeededXP(), player->GetXPDebt(), player->GetXPVitality(), player->GetTSXP(), player->GetNeededTSXP(), player->GetTSXPVitality(), player->GetBankCoinsCopper(),

View File

@ -5181,7 +5181,17 @@ void Client::DetermineCharacterUpdates() {
LogWrite(MISC__TODO, 1, "TODO", "Armor update req in func: %s, line: %i", __FUNCTION__, __LINE__); LogWrite(MISC__TODO, 1, "TODO", "Armor update req in func: %s, line: %i", __FUNCTION__, __LINE__);
} }
if (flag & NAME_UPDATE_FLAG) { if (flag & NAME_UPDATE_FLAG) {
LogWrite(MISC__TODO, 1, "TODO", "Name update req in func: %s, line: %i", __FUNCTION__, __LINE__); int8 name_length = strnlen(GetPlayer()->GetInfoStruct()->get_name().c_str(), 64); // max of 64 to LS the DB limit
int32 packet_length = sizeof(CharNameUpdate_Struct) + name_length;
ServerPacket* outpack = new ServerPacket(ServerOP_NameCharUpdate, packet_length);
memset(outpack->pBuffer, 0, packet_length);
CharNameUpdate_Struct* cnu = (CharNameUpdate_Struct*)outpack->pBuffer;
cnu->account_id = GetAccountID();
cnu->char_id = GetCharacterID();
cnu->name_length = name_length;
strncpy(cnu->new_name, GetPlayer()->GetInfoStruct()->get_name().c_str(), name_length);
loginserver.SendPacket(outpack);
safe_delete(outpack);
} }
database.UpdateCharacterTimeStamp(GetAccountID(), GetCharacterID(), timestamp); database.UpdateCharacterTimeStamp(GetAccountID(), GetCharacterID(), timestamp);