From 40b2366346c405122b50a741cafa095215a76cb2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 20 Jan 2019 21:33:56 -0600 Subject: [PATCH] Implement and extended #goto via #goto - this will work cross zone, cross instance, in zone etc. It works on top of the original #goto (target) and #goto x y z --- changelog.txt | 2 ++ common/database_instances.cpp | 13 +++++-- zone/client.cpp | 52 ++++++++++++++++++++++++++++ zone/client.h | 2 ++ zone/command.cpp | 64 +++++++++++++++++++++++++++++++---- 5 files changed, 124 insertions(+), 9 deletions(-) diff --git a/changelog.txt b/changelog.txt index 60330e137..9917b0e2d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 1/20/2019 == Uleat: Added 'spells' entry to EQDictionary +Akkadius: Implement and extended #goto via #goto - this will work cross zone, cross instance, in zone etc. + It works on top of the original #goto (target) and #goto x y z == 1/15/2019 == Uleat: Activated per-expansion support for active inventory slot addressing diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 5350d71f9..548a84bdb 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -38,16 +38,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #endif +/** + * @param instance_id + * @param char_id + * @return + */ bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) { std::string query = StringFormat( "REPLACE INTO `instance_list_player` (id, charid) " "VALUES " "(%lu, %lu)", - (unsigned long)instance_id, - (unsigned long)char_id - ); + (unsigned long) instance_id, + (unsigned long) char_id + ); + auto results = QueryDatabase(query); + return results.Success(); } diff --git a/zone/client.cpp b/zone/client.cpp index b625210ee..b0eca3c43 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9075,3 +9075,55 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id) Message(15, "Your secondary weapon appearance has been modified"); } } + +/** + * Used in #goto + * + * @param player_name + */ +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 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)) { + this->Message(15, "Instance no longer exists..."); + return false; + } + + if (instance_id > 0) { + database.AddClientToInstance(instance_id, this->CharacterID()); + } + + this->MovePC(zone_id, instance_id, x, y, z, heading); + + return true; + } + + return false; +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index d1ccbb399..fb9cd2e31 100644 --- a/zone/client.h +++ b/zone/client.h @@ -255,6 +255,8 @@ public: void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id); + bool GotoPlayer(std::string player_name); + //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); diff --git a/zone/command.cpp b/zone/command.cpp index c2b36c6e6..d6e28ddf3 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5349,13 +5349,65 @@ void command_loc(Client *c, const Seperator *sep) void command_goto(Client *c, const Seperator *sep) { - // goto function - if (sep->arg[1][0] == '\0' && c->GetTarget()) - c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ(), c->GetTarget()->GetHeading()); - else if (!(sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3))) + /** + * Goto via target and no args + */ + if (sep->arg[1][0] == '\0' && c->GetTarget()) { + c->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + c->GetTarget()->GetX(), + c->GetTarget()->GetY(), + c->GetTarget()->GetZ(), + c->GetTarget()->GetHeading()); + } + + /** + * Goto via player name + */ + else if (!sep->IsNumber(1) && sep->arg[1]) { + + /** + * Find them in zone first + */ + const char *player_name = sep->arg[1]; + std::string player_name_string = sep->arg[1]; + Client *client = entity_list.GetClientByName(player_name); + if (client) { + c->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + client->GetX(), + client->GetY(), + client->GetZ(), + client->GetHeading()); + + c->Message(15, "Goto player '%s' same zone", player_name_string.c_str()); + } + else if (c->GotoPlayer(player_name_string)) { + c->Message(15, "Goto player '%s' different zone", player_name_string.c_str()); + } + else { + c->Message(15, "Player '%s' not found", player_name_string.c_str()); + } + } + + /** + * Goto via x y z + */ + else if (sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)) { + c->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + atof(sep->arg[1]), + atof(sep->arg[2]), + atof(sep->arg[3]), + c->GetHeading()); + } + else { c->Message(0, "Usage: #goto [x y z]"); - else - c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), atof(sep->arg[1]), atof(sep->arg[2]), atof(sep->arg[3]), c->GetHeading()); + c->Message(0, "Usage: #goto [player_name]"); + } } void command_iteminfo(Client *c, const Seperator *sep)