[Feature] Implement Custom Pet Names (#4594)

* rebase\tidy up to address commends

* I blame git for this one

* last typo

* spaces

* formating fixes I think?

* Repository fixes

* Cleanup

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
catapultam-habeo
2025-01-22 03:31:05 -06:00
committed by GitHub
parent 0acad18067
commit 31abaf8016
16 changed files with 595 additions and 10 deletions
+87 -9
View File
@@ -66,6 +66,7 @@ extern volatile bool RunLoops;
#include "../common/repositories/character_spells_repository.h"
#include "../common/repositories/character_disciplines_repository.h"
#include "../common/repositories/character_data_repository.h"
#include "../common/repositories/character_pet_name_repository.h"
#include "../common/repositories/discovered_items_repository.h"
#include "../common/repositories/inventory_repository.h"
#include "../common/repositories/keyring_repository.h"
@@ -1828,7 +1829,7 @@ void Client::FriendsWho(char *FriendsString) {
Message(0, "Error: World server disconnected");
else {
auto pack =
new ServerPacket(ServerOP_FriendsWho, sizeof(ServerFriendsWho_Struct) + strlen(FriendsString));
new ServerPacket(ServerOP_FriendsWho, sizeof(ServerFriendsWho_Struct) + strlen(FriendsString));
ServerFriendsWho_Struct* FriendsWho = (ServerFriendsWho_Struct*) pack->pBuffer;
FriendsWho->FromID = GetID();
strcpy(FriendsWho->FromName, GetName());
@@ -2209,7 +2210,7 @@ void Client::Stand() {
}
void Client::Sit() {
SetAppearance(eaSitting, false);
SetAppearance(eaSitting, false);
}
void Client::ChangeLastName(std::string last_name) {
@@ -4392,6 +4393,83 @@ void Client::KeyRingList()
}
}
bool Client::IsPetNameChangeAllowed() {
DataBucketKey k = GetScopedBucketKeys();
k.key = "PetNameChangesAllowed";
auto b = DataBucket::GetData(k);
if (!b.value.empty()) {
return true;
}
return false;
}
void Client::InvokeChangePetName(bool immediate) {
if (!IsPetNameChangeAllowed()) {
return;
}
auto packet_op = immediate ? OP_InvokeChangePetNameImmediate : OP_InvokeChangePetName;
auto outapp = new EQApplicationPacket(packet_op, 0);
QueuePacket(outapp);
safe_delete(outapp);
}
void Client::GrantPetNameChange() {
DataBucketKey k = GetScopedBucketKeys();
k.key = "PetNameChangesAllowed";
k.value = "true";
DataBucket::SetData(k);
InvokeChangePetName(true);
}
void Client::ClearPetNameChange() {
DataBucketKey k = GetScopedBucketKeys();
k.key = "PetNameChangesAllowed";
DataBucket::DeleteData(k);
}
bool Client::ChangePetName(std::string new_name)
{
if (new_name.empty()) {
return false;
}
if (!IsPetNameChangeAllowed()) {
return false;
}
auto pet = GetPet();
if (!pet) {
return false;
}
if (pet->GetName() == new_name) {
return false;
}
if (!database.CheckNameFilter(new_name) || database.IsNameUsed(new_name)) {
return false;
}
CharacterPetNameRepository::ReplaceOne(
database,
CharacterPetNameRepository::CharacterPetName{
.character_id = static_cast<int32_t>(CharacterID()),
.name = new_name
}
);
pet->TempName(new_name.c_str());
ClearPetNameChange();
return true;
}
bool Client::IsDiscovered(uint32 item_id) {
const auto& l = DiscoveredItemsRepository::GetWhere(
database,
@@ -5628,13 +5706,13 @@ bool Client::TryReward(uint32 claim_id)
if (amt == 1) {
query = StringFormat("DELETE FROM account_rewards "
"WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id);
"WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id);
auto results = database.QueryDatabase(query);
} else {
query = StringFormat("UPDATE account_rewards SET amount = (amount-1) "
"WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id);
"WHERE account_id = %i AND reward_id = %i",
AccountID(), claim_id);
auto results = database.QueryDatabase(query);
}
@@ -8367,7 +8445,7 @@ int Client::GetQuiverHaste(int delay)
for (int r = EQ::invslot::GENERAL_BEGIN; r <= EQ::invslot::GENERAL_END; r++) {
pi = GetInv().GetItem(r);
if (pi && pi->IsClassBag() && pi->GetItem()->BagType == EQ::item::BagTypeQuiver &&
pi->GetItem()->BagWR > 0)
pi->GetItem()->BagWR > 0)
break;
if (r == EQ::invslot::GENERAL_END)
// we will get here if we don't find a valid quiver
@@ -9841,7 +9919,7 @@ const ExpeditionLockoutTimer* Client::GetExpeditionLockout(
for (const auto& expedition_lockout : m_expedition_lockouts)
{
if ((include_expired || !expedition_lockout.IsExpired()) &&
expedition_lockout.IsSameLockout(expedition_name, event_name))
expedition_lockout.IsSameLockout(expedition_name, event_name))
{
return &expedition_lockout;
}
@@ -9856,7 +9934,7 @@ std::vector<ExpeditionLockoutTimer> Client::GetExpeditionLockouts(
for (const auto& lockout : m_expedition_lockouts)
{
if ((include_expired || !lockout.IsExpired()) &&
lockout.GetExpeditionName() == expedition_name)
lockout.GetExpeditionName() == expedition_name)
{
lockouts.emplace_back(lockout);
}
+6
View File
@@ -307,6 +307,11 @@ public:
void KeyRingAdd(uint32 item_id);
bool KeyRingCheck(uint32 item_id);
void KeyRingList();
bool IsPetNameChangeAllowed();
void GrantPetNameChange();
void ClearPetNameChange();
void InvokeChangePetName(bool immediate = true);
bool ChangePetName(std::string new_name);
bool IsClient() const override { return true; }
bool IsOfClientBot() const override { return true; }
bool IsOfClientBotMerc() const override { return true; }
@@ -2267,6 +2272,7 @@ public:
const std::string &GetMailKeyFull() const;
const std::string &GetMailKey() const;
void ShowZoneShardMenu();
void Handle_OP_ChangePetName(const EQApplicationPacket *app);
};
#endif
+27
View File
@@ -66,6 +66,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/repositories/character_corpses_repository.h"
#include "../common/repositories/guild_tributes_repository.h"
#include "../common/repositories/buyer_buy_lines_repository.h"
#include "../common/repositories/character_pet_name_repository.h"
#include "../common/events/player_event_logs.h"
#include "../common/repositories/character_stats_record_repository.h"
@@ -160,6 +161,7 @@ void MapOpcodes()
ConnectedOpcodes[OP_CancelTrade] = &Client::Handle_OP_CancelTrade;
ConnectedOpcodes[OP_CastSpell] = &Client::Handle_OP_CastSpell;
ConnectedOpcodes[OP_ChannelMessage] = &Client::Handle_OP_ChannelMessage;
ConnectedOpcodes[OP_ChangePetName] = &Client::Handle_OP_ChangePetName;
ConnectedOpcodes[OP_ClearBlockedBuffs] = &Client::Handle_OP_ClearBlockedBuffs;
ConnectedOpcodes[OP_ClearNPCMarks] = &Client::Handle_OP_ClearNPCMarks;
ConnectedOpcodes[OP_ClearSurname] = &Client::Handle_OP_ClearSurname;
@@ -820,6 +822,10 @@ void Client::CompleteConnect()
CharacterID()
)
);
if (IsPetNameChangeAllowed()) {
InvokeChangePetName(false);
}
}
if(ClientVersion() == EQ::versions::ClientVersion::RoF2 && RuleB(Parcel, EnableParcelMerchants)) {
@@ -4568,6 +4574,27 @@ void Client::Handle_OP_ChannelMessage(const EQApplicationPacket *app)
return;
}
void Client::Handle_OP_ChangePetName(const EQApplicationPacket *app) {
if (app->size != sizeof(ChangePetName_Struct)) {
LogError("Got OP_ChangePetName of incorrect size. Expected [{}], got [{}].", sizeof(ChangePetName_Struct), app->size);
return;
}
auto p = (ChangePetName_Struct *) app->pBuffer;
if (!IsPetNameChangeAllowed()) {
p->response_code = ChangePetNameResponse::NotEligible;
QueuePacket(app);
return;
}
p->response_code = ChangePetNameResponse::Denied;
if (ChangePetName(p->new_pet_name)) {
p->response_code = ChangePetNameResponse::Accepted;
}
QueuePacket(app);
}
void Client::Handle_OP_ClearBlockedBuffs(const EQApplicationPacket *app)
{
if (!RuleB(Spells, EnableBlockedBuffs))
+7
View File
@@ -3458,6 +3458,12 @@ void Lua_Client::ShowZoneShardMenu()
self->ShowZoneShardMenu();
}
void Lua_Client::GrantPetNameChange()
{
Lua_Safe_Call_Void();
self->GrantPetNameChange();
}
void Lua_Client::SetAAEXPPercentage(uint8 percentage)
{
Lua_Safe_Call_Void();
@@ -3568,6 +3574,7 @@ luabind::scope lua_register_client() {
.def("CanHaveSkill", (bool(Lua_Client::*)(int))&Lua_Client::CanHaveSkill)
.def("CashReward", &Lua_Client::CashReward)
.def("ChangeLastName", (void(Lua_Client::*)(std::string))&Lua_Client::ChangeLastName)
.def("GrantPetNameChange", &Lua_Client::GrantPetNameChange)
.def("CharacterID", (uint32(Lua_Client::*)(void))&Lua_Client::CharacterID)
.def("CheckIncreaseSkill", (void(Lua_Client::*)(int,Lua_Mob))&Lua_Client::CheckIncreaseSkill)
.def("CheckIncreaseSkill", (void(Lua_Client::*)(int,Lua_Mob,int))&Lua_Client::CheckIncreaseSkill)
+1
View File
@@ -597,6 +597,7 @@ public:
bool ReloadDataBuckets();
void ShowZoneShardMenu();
void GrantPetNameChange();
Lua_Expedition CreateExpedition(luabind::object expedition_info);
Lua_Expedition CreateExpedition(std::string zone_name, uint32 version, uint32 duration, std::string expedition_name, uint32 min_players, uint32 max_players);
+6
View File
@@ -3229,6 +3229,11 @@ perl::array Perl_Client_GetInventorySlots(Client* self)
return result;
}
void Perl_Client_GrantPetNameChange(Client* self)
{
self->GrantPetNameChange();
}
void Perl_Client_SetAAEXPPercentage(Client* self, uint8 percentage)
{
self->SetAAEXPPercentage(percentage);
@@ -3335,6 +3340,7 @@ void perl_register_client()
package.add("CanHaveSkill", &Perl_Client_CanHaveSkill);
package.add("CashReward", &Perl_Client_CashReward);
package.add("ChangeLastName", &Perl_Client_ChangeLastName);
package.add("GrantPetNameChange", &Perl_Client_GrantPetNameChange);
package.add("CharacterID", &Perl_Client_CharacterID);
package.add("CheckIncreaseSkill", (bool(*)(Client*, int))&Perl_Client_CheckIncreaseSkill);
package.add("CheckIncreaseSkill", (bool(*)(Client*, int, int))&Perl_Client_CheckIncreaseSkill);
+7
View File
@@ -22,6 +22,7 @@
#include "../common/repositories/pets_repository.h"
#include "../common/repositories/pets_beastlord_data_repository.h"
#include "../common/repositories/character_pet_name_repository.h"
#include "entity.h"
#include "client.h"
@@ -164,6 +165,12 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
// 4 - Keep DB name
// 5 - `s ward
if (IsClient() && !petname) {
const auto vanity_name = CharacterPetNameRepository::FindOne(database, CastToClient()->CharacterID());
if (!vanity_name.name.empty()) {
petname = vanity_name.name.c_str();
}
}
if (petname != nullptr) {
// Name was provided, use it.