From 619f01e1505dc1e3064ee6d907ecee828d023504 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 20 Jun 2010 07:06:30 +0400 Subject: [PATCH] [10086] Implement use .go command with shiftlinks or player name. * Now if for .go command provided no X Y Z args command will not teleport player to nowhere. * Instead command allow used with player name and work as simplifed .goname (teleport to player _point_ in user instance binding, not to player instance) * Also command can be used with diferent point coordinates provided shift-links: - player (result for example .lookup player account) - creature (result .list creature command) - gameobject (result .list object command) - tele (result .lookup tele) - taxinode (result .lookup taxinode) --- sql/mangos.sql | 3 +- sql/updates/10086_01_mangos_command.sql | 5 + sql/updates/Makefile.am | 2 + src/game/Chat.cpp | 126 +++++++++++++- src/game/Chat.h | 3 + src/game/Level1.cpp | 209 ++++++++++++------------ src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 8 files changed, 239 insertions(+), 113 deletions(-) create mode 100644 sql/updates/10086_01_mangos_command.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 9bdd88f1a..c77906245 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_10056_01_mangos_spell_proc_event` bit(1) default NULL + `required_10086_01_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -577,6 +577,7 @@ INSERT INTO `command` VALUES ('gm ingame',0,'Syntax: .gm ingame\r\n\r\nDisplay a list of available in game Game Masters.'), ('gm list',3,'Syntax: .gm list\r\n\r\nDisplay a list of all Game Masters accounts and security levels.'), ('gm visible',1,'Syntax: .gm visible on/off\r\n\r\nOutput current visibility state or make GM visible(on) and invisible(off) for other players.'), +('go',1,'Syntax: .go [$playername|pointlink|#x #y #z [#mapid]]\r\nTeleport your character to point with coordinates of player $playername, or coordinates of one from shift-link types: player, tele, taxinode, creature, gameobject, or explicit #x #y #z #mapid coordinates.'), ('go creature',1,'Syntax: .go creature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.\r\n.gocreature #creature_name\r\nTeleport your character to creature with this name.\r\n.gocreature id #creature_id\r\nTeleport your character to a creature that was spawned from the template with this entry.\r\n*If* more than one creature is found, then you are teleported to the first that is found inside the database.'), ('go graveyard',1,'Syntax: .go graveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'), ('go grid',1,'Syntax: .go grid #gridX #gridY [#mapId]\r\n\r\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'), diff --git a/sql/updates/10086_01_mangos_command.sql b/sql/updates/10086_01_mangos_command.sql new file mode 100644 index 000000000..ae505e125 --- /dev/null +++ b/sql/updates/10086_01_mangos_command.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_10056_01_mangos_spell_proc_event required_10086_01_mangos_command bit; + +DELETE FROM command WHERE name IN('go'); +INSERT INTO command (name, security, help) VALUES +('go',1,'Syntax: .go [$playername|pointlink|#x #y #z [#mapid]]\r\nTeleport your character to point with coordinates of player $playername, or coordinates of one from shift-link types: player, tele, taxinode, creature, gameobject, or explicit #x #y #z #mapid coordinates.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index af7404e6c..ff1c377bc 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -89,6 +89,7 @@ pkgdata_DATA = \ 10045_01_mangos_spell_proc_event.sql \ 10051_01_characters_character_aura.sql \ 10056_01_mangos_spell_proc_event.sql \ + 10086_01_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -158,4 +159,5 @@ EXTRA_DIST = \ 10045_01_mangos_spell_proc_event.sql \ 10051_01_characters_character_aura.sql \ 10056_01_mangos_spell_proc_event.sql \ + 10086_01_mangos_command.sql \ README diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 893959977..e1491b9e8 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -216,7 +216,7 @@ ChatCommand * ChatHandler::getCommandTable() { "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL }, { "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL }, { "xyz", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL }, - { "", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL }, + { "", SEC_MODERATOR, false, &ChatHandler::HandleGoCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -2133,6 +2133,130 @@ uint64 ChatHandler::extractGuidFromLink(char* text) return 0; } +enum LocationLinkType +{ + LOCATION_LINK_PLAYER = 0, // must be first for selection in not link case + LOCATION_LINK_TELE = 1, + LOCATION_LINK_TAXINODE = 2, + LOCATION_LINK_CREATURE = 3, + LOCATION_LINK_GAMEOBJECT = 4 +}; + +static char const* const locationKeys[] = +{ + "Htele", + "Htaxinode", + "Hplayer", + "Hcreature", + "Hgameobject", + NULL +}; + +bool ChatHandler::extractLocationFromLink(char* text, uint32& mapid, float& x, float& y, float& z) +{ + int type = 0; + + // |color|Hplayer:name|h[name]|h|r + // |color|Htele:id|h[name]|h|r + // |color|Htaxinode:id|h[name]|h|r + // |color|Hcreature:creature_guid|h[name]|h|r + // |color|Hgameobject:go_guid|h[name]|h|r + char* idS = extractKeyFromLink(text,locationKeys,&type); + if(!idS) + return false; + + switch(type) + { + // it also fail case + case LOCATION_LINK_PLAYER: + { + // not link and not name, possible coordinates/etc + if (isNumeric(idS[0])) + return false; + + std::string name = idS; + if(!normalizePlayerName(name)) + return false; + + if(Player* player = sObjectMgr.GetPlayer(name.c_str())) + { + mapid = player->GetMapId(); + x = player->GetPositionX(); + y = player->GetPositionY(); + z = player->GetPositionZ(); + return true; + } + + if(uint64 guid = sObjectMgr.GetPlayerGUIDByName(name)) + { + // to point where player stay (if loaded) + float o; + bool in_flight; + return Player::LoadPositionFromDB(mapid, x, y, z, o, in_flight, guid); + } + + return false; + } + case LOCATION_LINK_TELE: + { + uint32 id = (uint32)atol(idS); + GameTele const* tele = sObjectMgr.GetGameTele(id); + if (!tele) + return false; + mapid = tele->mapId; + x = tele->position_x; + y = tele->position_y; + z = tele->position_z; + return true; + } + case LOCATION_LINK_TAXINODE: + { + uint32 id = (uint32)atol(idS); + TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id); + if (!node) + return false; + mapid = node->map_id; + x = node->x; + y = node->y; + z = node->z; + return true; + } + case LOCATION_LINK_CREATURE: + { + uint32 lowguid = (uint32)atol(idS); + + if(CreatureData const* data = sObjectMgr.GetCreatureData(lowguid) ) + { + mapid = data->mapid; + x = data->posX; + y = data->posY; + z = data->posZ; + return true; + } + else + return false; + } + case LOCATION_LINK_GAMEOBJECT: + { + uint32 lowguid = (uint32)atol(idS); + + if(GameObjectData const* data = sObjectMgr.GetGOData(lowguid) ) + { + mapid = data->mapid; + x = data->posX; + y = data->posY; + z = data->posZ; + return true; + } + else + return false; + } + } + + // unknown type? + return false; +} + std::string ChatHandler::extractPlayerNameFromLink(char* text) { // |color|Hplayer:name|h[name]|h|r diff --git a/src/game/Chat.h b/src/game/Chat.h index 87aa895cf..5250a857b 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -535,6 +535,7 @@ class ChatHandler uint32 extractSpellIdFromLink(char* text); uint64 extractGuidFromLink(char* text); GameTele const* extractGameTeleFromLink(char* text); + bool extractLocationFromLink(char* text, uint32& mapid, float& x, float& y, float& z); std::string extractPlayerNameFromLink(char* text); // select by arg (name/link) or in-game selection online/offline player bool extractPlayerTarget(char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL); @@ -558,6 +559,8 @@ class ChatHandler void HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel); void HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id); void ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc); + bool HandleGoHelper(Player* _player, uint32 mapid, float x, float y, float const* zPtr = NULL); + /** * Stores informations about a deleted character diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 603032f13..a19c7ed7c 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -2226,6 +2226,51 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) return true; } +bool ChatHandler::HandleGoHelper( Player* player, uint32 mapid, float x, float y, float const* zPtr ) +{ + float z; + + if (zPtr) + { + z = *zPtr; + + // check full provided coordinates + if(!MapManager::IsValidMapCoord(mapid,x,y,z)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + } + else + { + // we need check x,y before ask Z or can crash at invalide coordinates + if(!MapManager::IsValidMapCoord(mapid,x,y)) + { + PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); + SetSentErrorMessage(true); + return false; + } + + Map const *map = sMapMgr.CreateBaseMap(mapid); + z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + } + + // stop flight if need + if(player->isInFlight()) + { + player->GetMotionMaster()->MovementExpired(); + player->m_taxi.ClearTaxiDestinations(); + } + // save only in non-flight case + else + player->SaveRecallPosition(); + + player->TeleportTo(mapid, x, y, z, player->GetOrientation()); + + return true; +} + bool ChatHandler::HandleGoTaxinodeCommand(const char* args) { Player* _player = m_session->GetPlayer(); @@ -2249,28 +2294,55 @@ bool ChatHandler::HandleGoTaxinodeCommand(const char* args) return false; } - if ((node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) || - !MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z)) + if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) { PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id); SetSentErrorMessage(true); return false; } - // stop flight if need - if (_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation()); - return true; + return HandleGoHelper(_player, node->map_id, node->x, node->y, &node->z); } +bool ChatHandler::HandleGoCommand(const char* args) +{ + if(!*args) + return false; + + Player* _player = m_session->GetPlayer(); + + uint32 mapid; + float x, y, z; + + // raw coordinates case + if (isNumeric(args[0])) + { + char* px = strtok((char*)args, " "); + char* py = strtok(NULL, " "); + char* pz = strtok(NULL, " "); + char* pmapid = strtok(NULL, " "); + + if (!px || !py || !pz) + return false; + + x = (float)atof(px); + y = (float)atof(py); + z = (float)atof(pz); + if (pmapid) + mapid = (uint32)atoi(pmapid); + else + mapid = _player->GetMapId(); + + } + // link case + else if (!extractLocationFromLink((char*)args, mapid, x, y, z)) + return false; + + return HandleGoHelper(_player, mapid, x, y, &z); +} + + + //teleport at coordinates bool ChatHandler::HandleGoXYCommand(const char* args) { @@ -2293,29 +2365,7 @@ bool ChatHandler::HandleGoXYCommand(const char* args) mapid = (uint32)atoi(pmapid); else mapid = _player->GetMapId(); - if(!MapManager::IsValidMapCoord(mapid,x,y)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if(_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - Map const *map = sMapMgr.CreateBaseMap(mapid); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); - - _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); - - return true; + return HandleGoHelper(_player, mapid, x, y); } //teleport at coordinates, including Z @@ -2343,26 +2393,7 @@ bool ChatHandler::HandleGoXYZCommand(const char* args) else mapid = _player->GetMapId(); - if(!MapManager::IsValidMapCoord(mapid,x,y,z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if(_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); - - return true; + return HandleGoHelper(_player, mapid, x, y, &z); } //teleport at coordinates @@ -2403,49 +2434,33 @@ bool ChatHandler::HandleGoZoneXYCommand(const char* args) // update to parent zone if exist (client map show only zones without parents) AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; - Map const *map = sMapMgr.CreateBaseMap(zoneEntry->mapid); + MapEntry const *mapEntry = sMapStore.LookupEntry(zoneEntry->mapid); - if(map->Instanceable()) + if (mapEntry->Instanceable()) { - PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName()); + PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()], + mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]); SetSentErrorMessage(true); return false; } if (!Zone2MapCoordinates(x,y,zoneEntry->ID)) { - PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName()); + PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()], + mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]); SetSentErrorMessage(true); return false; } - if(!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,zoneEntry->mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if(_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); - _player->TeleportTo(zoneEntry->mapid, x, y, z, _player->GetOrientation()); - - return true; + return HandleGoHelper(_player, mapEntry->MapID, x, y); } //teleport to grid bool ChatHandler::HandleGoGridCommand(const char* args) { - if(!*args) return false; + if (!*args) + return false; + Player* _player = m_session->GetPlayer(); char* px = strtok((char*)args, " "); @@ -2457,37 +2472,13 @@ bool ChatHandler::HandleGoGridCommand(const char* args) float grid_x = (float)atof(px); float grid_y = (float)atof(py); - uint32 mapid; - if (pmapid) - mapid = (uint32)atoi(pmapid); - else mapid = _player->GetMapId(); + uint32 mapid = pmapid ? (uint32)atoi(pmapid) : _player->GetMapId(); // center of grid float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; float y = (grid_y-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; - if(!MapManager::IsValidMapCoord(mapid,x,y)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); - SetSentErrorMessage(true); - return false; - } - - // stop flight if need - if(_player->isInFlight()) - { - _player->GetMotionMaster()->MovementExpired(); - _player->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - _player->SaveRecallPosition(); - - Map const *map = sMapMgr.CreateBaseMap(mapid); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); - _player->TeleportTo(mapid, x, y, z, _player->GetOrientation()); - - return true; + return HandleGoHelper(_player, mapid, x, y); } bool ChatHandler::HandleModifyDrunkCommand(const char* args) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0a7acb120..e28b4c859 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10085" + #define REVISION_NR "10086" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 3e7586ffb..8c440e80e 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_10051_01_characters_character_aura" - #define REVISION_DB_MANGOS "required_10056_01_mangos_spell_proc_event" + #define REVISION_DB_MANGOS "required_10086_01_mangos_command" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__