From 3e8d34825a47bc3aa83641664e2189a7f7ae043a Mon Sep 17 00:00:00 2001 From: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 20 Aug 2022 10:23:41 -0400 Subject: [PATCH] [Quest API] Add Goto Player Teleport Methods. (#2379) * [Quest API] Add Player Teleport Methods. These methods will allow server operators to teleport players directly to other players via the quest API using the #goto command's functionality. - Add $client->TeleportToPlayerByCharID(character_id) to Perl. - Add $client->TeleportToPlayerByName(player_name) to Perl. - Add $client->TeleportGroupToPlayerByCharID(character_id) to Perl. - Add $client->TeleportGroupToPlayerByName(player_name) to Perl. - Add $client->TeleportRaidToPlayerByCharID(character_id) to Perl. - Add $client->TeleportRaidToPlayerByName(player_name) to Perl. - Add client:TeleportToPlayerByCharID(character_id) to Lua. - Add client:TeleportToPlayerByName(player_name) to Lua. - Add client:TeleportGroupToPlayerByCharID(character_id) to Lua. - Add client:TeleportGroupToPlayerByName(player_name) to Lua. - Add client:TeleportRaidToPlayerByCharID(character_id) to Lua. - Add client:TeleportRaidToPlayerByName(player_name) to Lua. * Simplify by using repositories * Simplify Co-authored-by: Akkadius --- zone/client.cpp | 77 ++++++++++++++++++++++++++------------------ zone/client.h | 2 ++ zone/lua_client.cpp | 36 +++++++++++++++++++++ zone/lua_client.h | 6 ++++ zone/perl_client.cpp | 36 +++++++++++++++++++++ 5 files changed, 126 insertions(+), 31 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 602df6f8a..8070bb148 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -65,6 +65,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" extern QueryServ* QServ; @@ -9373,44 +9374,22 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id) */ bool Client::GotoPlayer(std::string player_name) { - std::string query = StringFormat( - "SELECT" - " character_data.zone_id," - " character_data.zone_instance," - " character_data.x," - " character_data.y," - " character_data.z," - " character_data.heading " - "FROM" - " character_data " - "WHERE" - " TRUE" - " AND character_data.name = '%s'" - " AND character_data.last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name.c_str()); + auto characters = CharacterDataRepository::GetWhere( + database, + fmt::format("name = '{}' AND last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name) + ); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - auto zone_id = static_cast(atoi(row[0])); - auto instance_id = static_cast(atoi(row[1])); - auto x = static_cast(atof(row[2])); - auto y = static_cast(atof(row[3])); - auto z = static_cast(atof(row[4])); - auto heading = static_cast(atof(row[5])); - - if (instance_id > 0 && !database.CheckInstanceExists(instance_id)) { + for (auto &c: characters) { + if (c.zone_instance > 0 && !database.CheckInstanceExists(c.zone_instance)) { Message(Chat::Yellow, "Instance no longer exists..."); return false; } - if (instance_id > 0) { - database.AddClientToInstance(instance_id, CharacterID()); + if (c.zone_instance > 0) { + database.AddClientToInstance(c.zone_instance, CharacterID()); } - MovePC(zone_id, instance_id, x, y, z, heading); + MovePC(c.zone_id, c.zone_instance, c.x, c.y, c.z, c.heading); return true; } @@ -9418,6 +9397,42 @@ bool Client::GotoPlayer(std::string player_name) return false; } +bool Client::GotoPlayerGroup(const std::string& player_name) +{ + if (!GetGroup()) { + return GotoPlayer(player_name); + } + + for (auto &m: GetGroup()->members) { + if (m && m->IsClient()) { + auto c = m->CastToClient(); + if (!c->GotoPlayer(player_name)) { + return false; + } + } + } + + return true; +} + +bool Client::GotoPlayerRaid(const std::string& player_name) +{ + if (!GetRaid()) { + return GotoPlayer(player_name); + } + + for (auto &m: GetRaid()->members) { + if (m.member && m.member->IsClient()) { + auto c = m.member->CastToClient(); + if (!c->GotoPlayer(player_name)) { + return false; + } + } + } + + return true; +} + glm::vec4 &Client::GetLastPositionBeforeBulkUpdate() { return last_position_before_bulk_update; diff --git a/zone/client.h b/zone/client.h index 3c950d318..44148e11c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -243,6 +243,8 @@ public: void SendChatLineBreak(uint16 color = Chat::White); bool GotoPlayer(std::string player_name); + bool GotoPlayerGroup(const std::string& player_name); + bool GotoPlayerRaid(const std::string& player_name); //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 0b32b3f36..88f4760d5 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -2575,6 +2575,36 @@ void Lua_Client::TaskSelector(luabind::adl::object table) { self->TaskQuestSetSelector(self, task_count, tasks); } +bool Lua_Client::TeleportToPlayerByCharID(uint32 character_id) { + Lua_Safe_Call_Bool(); + return self->GotoPlayer(database.GetCharNameByID(character_id)); +} + +bool Lua_Client::TeleportToPlayerByName(std::string player_name) { + Lua_Safe_Call_Bool(); + return self->GotoPlayer(player_name); +} + +bool Lua_Client::TeleportGroupToPlayerByCharID(uint32 character_id) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerGroup(database.GetCharNameByID(character_id)); +} + +bool Lua_Client::TeleportGroupToPlayerByName(std::string player_name) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerGroup(player_name); +} + +bool Lua_Client::TeleportRaidToPlayerByCharID(uint32 character_id) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerRaid(database.GetCharNameByID(character_id)); +} + +bool Lua_Client::TeleportRaidToPlayerByName(std::string player_name) { + Lua_Safe_Call_Bool(); + return self->GotoPlayerRaid(player_name); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -2975,6 +3005,12 @@ luabind::scope lua_register_client() { .def("TakePlatinum", (bool(Lua_Client::*)(uint32))&Lua_Client::TakePlatinum) .def("TakePlatinum", (bool(Lua_Client::*)(uint32,bool))&Lua_Client::TakePlatinum) .def("TaskSelector", (void(Lua_Client::*)(luabind::adl::object))&Lua_Client::TaskSelector) + .def("TeleportToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportToPlayerByCharID) + .def("TeleportToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportToPlayerByName) + .def("TeleportGroupToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportGroupToPlayerByCharID) + .def("TeleportGroupToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportGroupToPlayerByName) + .def("TeleportRaidToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportRaidToPlayerByCharID) + .def("TeleportRaidToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportRaidToPlayerByName) .def("Thirsty", (bool(Lua_Client::*)(void))&Lua_Client::Thirsty) .def("TrainDisc", (void(Lua_Client::*)(int))&Lua_Client::TrainDisc) .def("TrainDiscBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::TrainDiscBySpellID) diff --git a/zone/lua_client.h b/zone/lua_client.h index 3ef0c2f62..55cafc432 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -122,6 +122,12 @@ public: void MoveZoneInstance(uint16 instance_id); void MoveZoneInstanceGroup(uint16 instance_id); void MoveZoneInstanceRaid(uint16 instance_id); + bool TeleportToPlayerByCharID(uint32 character_id); + bool TeleportToPlayerByName(std::string player_name); + bool TeleportGroupToPlayerByCharID(uint32 character_id); + bool TeleportGroupToPlayerByName(std::string player_name); + bool TeleportRaidToPlayerByCharID(uint32 character_id); + bool TeleportRaidToPlayerByName(std::string player_name); void ChangeLastName(std::string last_name); int GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 race, uint32 class_, uint32 deity, uint32 faction, Lua_NPC npc); void SetFactionLevel(uint32 char_id, uint32 npc_id, int char_class, int char_race, int char_deity); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d809c4b17..14d7f19b5 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -2419,6 +2419,36 @@ void Perl_Client_TaskSelector(Client* self, perl::array task_ids) self->TaskQuestSetSelector(self, task_count, tasks); } +bool Perl_Client_TeleportToPlayerByCharacterID(Client* self, uint32 character_id) +{ + return self->GotoPlayer(database.GetCharNameByID(character_id)); +} + +bool Perl_Client_TeleportToPlayerByName(Client* self, std::string player_name) +{ + return self->GotoPlayer(player_name); +} + +bool Perl_Client_TeleportGroupToPlayerByCharacterID(Client* self, uint32 character_id) +{ + return self->GotoPlayerGroup(database.GetCharNameByID(character_id)); +} + +bool Perl_Client_TeleportGroupToPlayerByName(Client* self, std::string player_name) +{ + return self->GotoPlayerGroup(player_name); +} + +bool Perl_Client_TeleportRaidToPlayerByCharacterID(Client* self, uint32 character_id) +{ + return self->GotoPlayerRaid(database.GetCharNameByID(character_id)); +} + +bool Perl_Client_TeleportRaidToPlayerByName(Client* self, std::string player_name) +{ + return self->GotoPlayerRaid(player_name); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -2823,6 +2853,12 @@ void perl_register_client() package.add("TakeMoneyFromPP", (bool(*)(Client*, uint64_t, bool))&Perl_Client_TakeMoneyFromPP); package.add("TakePlatinum", (bool(*)(Client*, uint32))&Perl_Client_TakePlatinum); package.add("TakePlatinum", (bool(*)(Client*, uint32, bool))&Perl_Client_TakePlatinum); + package.add("TeleportToPlayerByCharID", &Perl_Client_TeleportToPlayerByCharacterID); + package.add("TeleportToPlayerByName", &Perl_Client_TeleportToPlayerByName); + package.add("TeleportGroupToPlayerByCharID", &Perl_Client_TeleportGroupToPlayerByCharacterID); + package.add("TeleportGroupToPlayerByName", &Perl_Client_TeleportGroupToPlayerByName); + package.add("TeleportRaidToPlayerByCharID", &Perl_Client_TeleportRaidToPlayerByCharacterID); + package.add("TeleportRaidToPlayerByName", &Perl_Client_TeleportRaidToPlayerByName); package.add("TaskSelector", &Perl_Client_TaskSelector); package.add("Thirsty", &Perl_Client_Thirsty); package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID);