diff --git a/sql/mangos.sql b/sql/mangos.sql index 098d2bb8a..30340d0f8 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_10089_01_mangos_game_event_pool` bit(1) default NULL + `required_10106_02_mangos_mangos_string` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -577,11 +577,11 @@ 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',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/creature_entry, gameobject/gameobject_entry, or explicit #x #y #z #mapid coordinates.'), +('go creature',1,'Syntax: .go creature (#creature_guid|$creature_name|id #creature_id)\r\nTeleport your character to creature with guid #creature_guid, or teleport your character to creature with name including as part $creature_name substring, or teleport your character to a creature that was spawned from the template with this entry #creature_id.'), ('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).'), -('go object',1,'Syntax: .go object #object_guid\r\nTeleport your character to gameobject with guid #object_guid'), +('go object',1,'Syntax: .go object (#gameobject_guid|$gameobject_name|id #gameobject_id)\r\nTeleport your character to gameobject with guid #gameobject_guid, or teleport your character to gameobject with name including as part $gameobject_name substring, or teleport your character to a gameobject that was spawned from the template with this entry #gameobject_id.'), ('go taxinode',1,'Syntax: .go taxinode #taxinode\r\n\r\nTeleport player to taxinode coordinates. You can look up zone using .lookup taxinode $namepart'), ('go trigger',1,'Syntax: .go trigger #trigger_id\r\n\r\nTeleport your character to areatrigger with id #trigger_id. Character will be teleported to trigger target if selected areatrigger is telporting trigger.'), ('go xy',1,'Syntax: .go xy #x #y [#mapid]\r\n\r\nTeleport player to point with (#x,#y) coordinates at ground(water) level at map #mapid or same map if #mapid not provided.'), @@ -3176,7 +3176,6 @@ INSERT INTO `mangos_string` VALUES (266,'Nothing found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (267,'Object not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (268,'Creature not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(269,'Warning: Mob found more than once - you will be teleported to the first one found in DB.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (270,'Creature Removed',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (271,'Creature moved.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (272,'Creature (GUID:%u) must be on the same map as player!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/10106_01_mangos_command.sql b/sql/updates/10106_01_mangos_command.sql new file mode 100644 index 000000000..e53369024 --- /dev/null +++ b/sql/updates/10106_01_mangos_command.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_10089_01_mangos_game_event_pool required_10106_01_mangos_command bit; + +DELETE FROM command WHERE name IN('go', 'go creature','go object'); +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/creature_entry, gameobject/gameobject_entry, or explicit #x #y #z #mapid coordinates.'), +('go creature',1,'Syntax: .go creature (#creature_guid|$creature_name|id #creature_id)\r\nTeleport your character to creature with guid #creature_guid, or teleport your character to creature with name including as part $creature_name substring, or teleport your character to a creature that was spawned from the template with this entry #creature_id.'), +('go object',1,'Syntax: .go object (#gameobject_guid|$gameobject_name|id #gameobject_id)\r\nTeleport your character to gameobject with guid #gameobject_guid, or teleport your character to gameobject with name including as part $gameobject_name substring, or teleport your character to a gameobject that was spawned from the template with this entry #gameobject_id.'); diff --git a/sql/updates/10106_02_mangos_mangos_string.sql b/sql/updates/10106_02_mangos_mangos_string.sql new file mode 100644 index 000000000..6048f180a --- /dev/null +++ b/sql/updates/10106_02_mangos_mangos_string.sql @@ -0,0 +1,3 @@ +ALTER TABLE db_version CHANGE COLUMN required_10106_01_mangos_command required_10106_02_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN (269); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 0703cd7eb..015257138 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -91,6 +91,8 @@ pkgdata_DATA = \ 10056_01_mangos_spell_proc_event.sql \ 10086_01_mangos_command.sql \ 10089_01_mangos_game_event_pool.sql \ + 10106_01_mangos_command.sql \ + 10106_02_mangos_mangos_string.sql \ README ## Additional files to include when running 'make dist' @@ -162,4 +164,6 @@ EXTRA_DIST = \ 10056_01_mangos_spell_proc_event.sql \ 10086_01_mangos_command.sql \ 10089_01_mangos_game_event_pool.sql \ + 10106_01_mangos_command.sql \ + 10106_02_mangos_mangos_string.sql \ README diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index e1491b9e8..901b77280 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1928,38 +1928,6 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, return NULL; } -char const *fmtstring( char const *format, ... ) -{ - va_list argptr; - #define MAX_FMT_STRING 32000 - static char temp_buffer[MAX_FMT_STRING]; - static char string[MAX_FMT_STRING]; - static int index = 0; - char *buf; - int len; - - va_start(argptr, format); - vsnprintf(temp_buffer,MAX_FMT_STRING, format, argptr); - va_end(argptr); - - len = strlen(temp_buffer); - - if( len >= MAX_FMT_STRING ) - return "ERROR"; - - if (len + index >= MAX_FMT_STRING-1) - { - index = 0; - } - - buf = &string[index]; - memcpy( buf, temp_buffer, len+1 ); - - index += len + 1; - - return buf; -} - GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry) { if(!m_session) @@ -2135,11 +2103,13 @@ uint64 ChatHandler::extractGuidFromLink(char* text) 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 + 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, + LOCATION_LINK_CREATURE_ENTRY = 5, + LOCATION_LINK_GAMEOBJECT_ENTRY = 6 }; static char const* const locationKeys[] = @@ -2149,6 +2119,8 @@ static char const* const locationKeys[] = "Hplayer", "Hcreature", "Hgameobject", + "Hcreature_entry", + "Hgameobject_entry", NULL }; @@ -2161,6 +2133,8 @@ bool ChatHandler::extractLocationFromLink(char* text, uint32& mapid, float& x, f // |color|Htaxinode:id|h[name]|h|r // |color|Hcreature:creature_guid|h[name]|h|r // |color|Hgameobject:go_guid|h[name]|h|r + // |color|Hcreature_entry:creature_id|h[name]|h|r + // |color|Hgameobject_entry:go_id|h[name]|h|r char* idS = extractKeyFromLink(text,locationKeys,&type); if(!idS) return false; @@ -2251,6 +2225,54 @@ bool ChatHandler::extractLocationFromLink(char* text, uint32& mapid, float& x, f else return false; } + case LOCATION_LINK_CREATURE_ENTRY: + { + uint32 id = (uint32)atol(idS); + + if (sObjectMgr.GetCreatureTemplate(id)) + { + FindCreatureData worker(id, m_session ? m_session->GetPlayer() : NULL); + + sObjectMgr.DoCreatureData(worker); + + if (CreatureDataPair const* dataPair = worker.GetResult()) + { + mapid = dataPair->second.mapid; + x = dataPair->second.posX; + y = dataPair->second.posY; + z = dataPair->second.posZ; + return true; + } + else + return false; + } + else + return false; + } + case LOCATION_LINK_GAMEOBJECT_ENTRY: + { + uint32 id = (uint32)atol(idS); + + if (sObjectMgr.GetGameObjectInfo(id)) + { + FindGOData worker(id, m_session ? m_session->GetPlayer() : NULL); + + sObjectMgr.DoGOData(worker); + + if (GameObjectDataPair const* dataPair = worker.GetResult()) + { + mapid = dataPair->second.mapid; + x = dataPair->second.posX; + y = dataPair->second.posY; + z = dataPair->second.posZ; + return true; + } + else + return false; + } + else + return false; + } } // unknown type? diff --git a/src/game/Chat.h b/src/game/Chat.h index 5250a857b..047cde760 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -559,7 +559,7 @@ 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); + bool HandleGoHelper(Player* _player, uint32 mapid, float x, float y, float const* zPtr = NULL, float const* ortPtr = NULL); /** @@ -614,6 +614,4 @@ class CliHandler : public ChatHandler Print* m_print; }; -char const *fmtstring( char const *format, ... ); - #endif diff --git a/src/game/Language.h b/src/game/Language.h index 38ec3467e..9b6668745 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -253,7 +253,7 @@ enum MangosStrings LANG_COMMAND_TARGETOBJNOTFOUND = 266, LANG_COMMAND_GOOBJNOTFOUND = 267, LANG_COMMAND_GOCREATNOTFOUND = 268, - LANG_COMMAND_GOCREATMULTIPLE = 269, + // 269, not used LANG_COMMAND_DELCREATMESSAGE = 270, LANG_COMMAND_CREATUREMOVED = 271, LANG_COMMAND_CREATUREATSAMEMAP = 272, diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index c51d46301..60150af00 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -599,17 +599,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) if (!Player::LoadPositionFromDB(map,x,y,z,o,in_flight,target_guid)) 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(map, x, y, z,_player->GetOrientation()); + return HandleGoHelper(_player, map, x, y, &z); } return true; @@ -633,15 +623,7 @@ bool ChatHandler::HandleRecallCommand(const char* args) return false; } - // stop flight if need - if(target->isInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->m_taxi.ClearTaxiDestinations(); - } - - target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); - return true; + return HandleGoHelper(target, target->m_recallMap, target->m_recallX, target->m_recallY, &target->m_recallZ, &target->m_recallO); } //Edit Player HP @@ -1780,18 +1762,7 @@ bool ChatHandler::HandleTeleCommand(const char * args) 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(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation); - return true; + return HandleGoHelper(_player, tele->mapId, tele->position_x, tele->position_y, &tele->position_z, &tele->orientation); } bool ChatHandler::HandleLookupAreaCommand(const char* args) @@ -2030,17 +2001,7 @@ bool ChatHandler::HandleTeleNameCommand(const char * args) if (needReportToTarget(target)) ChatHandler(target).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); - // stop flight if need - if(target->isInFlight()) - { - target->GetMotionMaster()->MovementExpired(); - target->m_taxi.ClearTaxiDestinations(); - } - // save only in non-flight case - else - target->SaveRecallPosition(); - - target->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); + return HandleGoHelper(target, tele->mapId, tele->position_x, tele->position_y, &tele->position_z, &tele->orientation); } else { @@ -2226,16 +2187,20 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) return true; } -bool ChatHandler::HandleGoHelper( Player* player, uint32 mapid, float x, float y, float const* zPtr ) +bool ChatHandler::HandleGoHelper( Player* player, uint32 mapid, float x, float y, float const* zPtr, float const* ortPtr) { float z; + float ort = player->GetOrientation(); if (zPtr) { z = *zPtr; + if (ortPtr) + ort = *ortPtr; + // check full provided coordinates - if(!MapManager::IsValidMapCoord(mapid,x,y,z)) + if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) { PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid); SetSentErrorMessage(true); @@ -2266,7 +2231,7 @@ bool ChatHandler::HandleGoHelper( Player* player, uint32 mapid, float x, float y else player->SaveRecallPosition(); - player->TeleportTo(mapid, x, y, z, player->GetOrientation()); + player->TeleportTo(mapid, x, y, z, ort); return true; } diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 0c39204f3..27ee038da 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -165,25 +165,7 @@ bool ChatHandler::HandleGoTriggerCommand(const char* args) return false; } - if(!MapManager::IsValidMapCoord(at->mapid,at->x,at->y,at->z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,at->x,at->y,at->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(at->mapid, at->x, at->y, at->z, _player->GetOrientation()); - return true; + return HandleGoHelper(_player, at->mapid, at->x, at->y, &at->z); } bool ChatHandler::HandleGoGraveyardCommand(const char* args) @@ -210,25 +192,7 @@ bool ChatHandler::HandleGoGraveyardCommand(const char* args) return false; } - if(!MapManager::IsValidMapCoord(gy->map_id,gy->x,gy->y,gy->z)) - { - PSendSysMessage(LANG_INVALID_TARGET_COORD,gy->x,gy->y,gy->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(gy->map_id, gy->x, gy->y, gy->z, _player->GetOrientation()); - return true; + return HandleGoHelper(_player, gy->map_id, gy->x, gy->y, &gy->z); } /** \brief Teleport the GM to the specified creature @@ -244,155 +208,221 @@ bool ChatHandler::HandleGoGraveyardCommand(const char* args) //teleport to creature bool ChatHandler::HandleGoCreatureCommand(const char* args) { - if(!*args) + if (!*args) return false; + Player* _player = m_session->GetPlayer(); - // "id" or number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + // "id" or number or [name] Shift-click form |color|Hcreature:creature_id|h[name]|h|r char* pParam1 = extractKeyFromLink((char*)args,"Hcreature"); if (!pParam1) return false; - std::ostringstream whereClause; + CreatureData const* data = NULL; + // User wants to teleport to the NPC's template entry - if( strcmp(pParam1, "id") == 0 ) + if (strcmp(pParam1, "id") == 0) { - //sLog.outError("DEBUG: ID found"); - - // Get the "creature_template.entry" // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r char* tail = strtok(NULL,""); - if(!tail) + if (!tail) return false; char* cId = extractKeyFromLink(tail,"Hcreature_entry"); - if(!cId) + if (!cId) return false; int32 tEntry = atoi(cId); - //sLog.outError("DEBUG: ID value: %d", tEntry); - if(!tEntry) + if (!tEntry) return false; - whereClause << "WHERE id = '" << tEntry << "'"; + if (!sObjectMgr.GetCreatureTemplate(tEntry)) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + FindCreatureData worker(tEntry, m_session ? m_session->GetPlayer() : NULL); + + sObjectMgr.DoCreatureData(worker); + + CreatureDataPair const* dataPair = worker.GetResult(); + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; } else { - //sLog.outError("DEBUG: ID *not found*"); - - int32 guid = atoi(pParam1); + int32 lowguid = atoi(pParam1); // Number is invalid - maybe the user specified the mob's name - if(!guid) + if (lowguid) { - std::string name = pParam1; - WorldDatabase.escape_string(name); - whereClause << ", creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" '" << name << "'"; + data = sObjectMgr.GetCreatureData(lowguid); + if (!data) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } } else { - whereClause << "WHERE guid = '" << guid << "'"; + std::string name = pParam1; + WorldDatabase.escape_string(name); + QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature, creature_template WHERE creature.id = creature_template.entry AND creature_template.name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + FindCreatureData worker(0, m_session ? m_session->GetPlayer() : NULL); + + do { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + + CreatureDataPair const* cr_data = sObjectMgr.GetCreatureDataPair(guid); + if (!cr_data) + continue; + + worker(*cr_data); + + } while (result->NextRow()); + + delete result; + + CreatureDataPair const* dataPair = worker.GetResult(); + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; } } - //sLog.outError("DEBUG: %s", whereClause.c_str()); - QueryResult *result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map FROM creature %s", whereClause.str().c_str() ); - if (!result) - { - SendSysMessage(LANG_COMMAND_GOCREATNOTFOUND); - SetSentErrorMessage(true); - return false; - } - if( result->GetRowCount() > 1 ) - { - SendSysMessage(LANG_COMMAND_GOCREATMULTIPLE); - } - - Field *fields = result->Fetch(); - float x = fields[0].GetFloat(); - float y = fields[1].GetFloat(); - float z = fields[2].GetFloat(); - float ort = fields[3].GetFloat(); - int mapid = fields[4].GetUInt16(); - - delete result; - - if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) - { - 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, ort); - return true; + return HandleGoHelper(_player, data->mapid, data->posX, data->posY, &data->posZ); } //teleport to gameobject bool ChatHandler::HandleGoObjectCommand(const char* args) { - if(!*args) + if (!*args) return false; Player* _player = m_session->GetPlayer(); // number or [name] Shift-click form |color|Hgameobject:go_guid|h[name]|h|r - char* cId = extractKeyFromLink((char*)args,"Hgameobject"); - if(!cId) + char* pParam1 = extractKeyFromLink((char*)args,"Hgameobject"); + if (!pParam1) return false; - int32 guid = atoi(cId); - if(!guid) - return false; + GameObjectData const* data = NULL; - float x, y, z, ort; - int mapid; - - // by DB guid - if (GameObjectData const* go_data = sObjectMgr.GetGOData(guid)) + // User wants to teleport to the NPC's template entry + if (strcmp(pParam1, "id") == 0) { - x = go_data->posX; - y = go_data->posY; - z = go_data->posZ; - ort = go_data->orientation; - mapid = go_data->mapid; + // number or [name] Shift-click form |color|Hgameobject_entry:creature_id|h[name]|h|r + char* tail = strtok(NULL,""); + if (!tail) + return false; + char* cId = extractKeyFromLink(tail,"Hgameobject_entry"); + if (!cId) + return false; + + int32 tEntry = atoi(cId); + if (!tEntry) + return false; + + if (!sObjectMgr.GetGameObjectInfo(tEntry)) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + FindGOData worker(tEntry, m_session ? m_session->GetPlayer() : NULL); + + sObjectMgr.DoGOData(worker); + + GameObjectDataPair const* dataPair = worker.GetResult(); + + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; } else { - SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); - SetSentErrorMessage(true); - return false; + int32 guid = atoi(pParam1); + + if (guid) + { + // by DB guid + data = sObjectMgr.GetGOData(guid); + if (!data) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + } + else + { + std::string name = pParam1; + WorldDatabase.escape_string(name); + QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM gameobject, gameobject_template WHERE gameobject.id = gameobject_template.entry AND gameobject_template.name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"), name.c_str()); + if (!result) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + FindGOData worker(0, m_session ? m_session->GetPlayer() : NULL); + + do { + Field *fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + + GameObjectDataPair const* go_data = sObjectMgr.GetGODataPair(guid); + if (!go_data) + continue; + + worker(*go_data); + + } while (result->NextRow()); + + delete result; + + GameObjectDataPair const* dataPair = worker.GetResult(); + if (!dataPair) + { + SendSysMessage(LANG_COMMAND_GOOBJNOTFOUND); + SetSentErrorMessage(true); + return false; + } + + data = &dataPair->second; + } } - if(!MapManager::IsValidMapCoord(mapid,x,y,z,ort)) - { - 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, ort); - return true; + return HandleGoHelper(_player, data->mapid, data->posX, data->posY, &data->posZ); } bool ChatHandler::HandleGameObjectTargetCommand(const char* args) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index dda243d7e..2579242d4 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -35,6 +35,7 @@ #include "Transports.h" #include "ProgressBar.h" #include "Language.h" +#include "PoolManager.h" #include "GameEventMgr.h" #include "Spell.h" #include "Chat.h" @@ -8624,3 +8625,103 @@ Quest const* GetQuestTemplateStore(uint32 entry) { return sObjectMgr.GetQuestTemplate(entry); } + +bool FindCreatureData::operator()( CreatureDataPair const& dataPair ) +{ + // skip wrong entry ids + if (i_id && dataPair.second.id != i_id) + return false; + + if (!i_anyData) + i_anyData = &dataPair; + + // without player we can't find more stricted cases, so use fouded + if (!i_player) + return true; + + // skip diff. map cases + if (dataPair.second.mapid != i_player->GetMapId()) + return false; + + float new_dist = i_player->GetDistance2d(dataPair.second.posX, dataPair.second.posY); + + if (!i_mapData || new_dist < i_mapDist) + { + i_mapData = &dataPair; + i_mapDist = new_dist; + } + + // skip not spawned (in any state), + uint16 pool_id = sPoolMgr.IsPartOfAPool(dataPair.first); + if (pool_id && !sPoolMgr.IsSpawnedObject(dataPair.first)) + return false; + + if (!i_spawnedData || new_dist < i_spawnedDist) + { + i_spawnedData = &dataPair; + i_spawnedDist = new_dist; + } + + return false; +} + +CreatureDataPair const* FindCreatureData::GetResult() const +{ + if (i_spawnedData) + return i_spawnedData; + + if (i_mapData) + return i_mapData; + + return i_anyData; +} + +bool FindGOData::operator()( GameObjectDataPair const& dataPair ) +{ + // skip wrong entry ids + if (i_id && dataPair.second.id != i_id) + return false; + + if (!i_anyData) + i_anyData = &dataPair; + + // without player we can't find more stricted cases, so use fouded + if (!i_player) + return true; + + // skip diff. map cases + if (dataPair.second.mapid != i_player->GetMapId()) + return false; + + float new_dist = i_player->GetDistance2d(dataPair.second.posX, dataPair.second.posY); + + if (!i_mapData || new_dist < i_mapDist) + { + i_mapData = &dataPair; + i_mapDist = new_dist; + } + + // skip not spawned (in any state) + uint16 pool_id = sPoolMgr.IsPartOfAPool(dataPair.first); + if (pool_id && !sPoolMgr.IsSpawnedObject(dataPair.first)) + return false; + + if (!i_spawnedData || new_dist < i_spawnedDist) + { + i_spawnedData = &dataPair; + i_spawnedDist = new_dist; + } + + return false; +} + +GameObjectDataPair const* FindGOData::GetResult() const +{ + if (i_mapData) + return i_mapData; + + if (i_spawnedData) + return i_spawnedData; + + return i_anyData; +} diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index c34ed115f..78b79b91b 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -155,7 +155,51 @@ struct MangosStringLocale }; typedef UNORDERED_MAP CreatureDataMap; +typedef CreatureDataMap::value_type CreatureDataPair; + +class FindCreatureData +{ + public: + FindCreatureData(uint32 id, Player* player) : i_id(id), i_player(player), + i_anyData(NULL), i_mapData(NULL), i_mapDist(0.0f), i_spawnedData(NULL), i_spawnedDist(0.0f) {} + + bool operator() (CreatureDataPair const& dataPair); + CreatureDataPair const* GetResult() const; + + private: + uint32 i_id; + Player* i_player; + + CreatureDataPair const* i_anyData; + CreatureDataPair const* i_mapData; + float i_mapDist; + CreatureDataPair const* i_spawnedData; + float i_spawnedDist; +}; + typedef UNORDERED_MAP GameObjectDataMap; +typedef GameObjectDataMap::value_type GameObjectDataPair; + +class FindGOData +{ + public: + FindGOData(uint32 id, Player* player) : i_id(id), i_player(player), + i_anyData(NULL), i_mapData(NULL), i_mapDist(0.0f), i_spawnedData(NULL), i_spawnedDist(0.0f) {} + + bool operator() (GameObjectDataPair const& dataPair); + GameObjectDataPair const* GetResult() const; + + private: + uint32 i_id; + Player* i_player; + + GameObjectDataPair const* i_anyData; + GameObjectDataPair const* i_mapData; + float i_mapDist; + GameObjectDataPair const* i_spawnedData; + float i_spawnedDist; +}; + typedef UNORDERED_MAP CreatureLocaleMap; typedef UNORDERED_MAP GameObjectLocaleMap; typedef UNORDERED_MAP ItemLocaleMap; @@ -712,14 +756,30 @@ class ObjectMgr return mMapObjectGuids[MAKE_PAIR32(mapid,spawnMode)][cell_id]; } - CreatureData const* GetCreatureData(uint32 guid) const + CreatureDataPair const* GetCreatureDataPair(uint32 guid) const { CreatureDataMap::const_iterator itr = mCreatureDataMap.find(guid); if(itr==mCreatureDataMap.end()) return NULL; - return &itr->second; + return &*itr; } + + CreatureData const* GetCreatureData(uint32 guid) const + { + CreatureDataPair const* dataPair = GetCreatureDataPair(guid); + return dataPair ? &dataPair->second : NULL; + } + CreatureData& NewOrExistCreatureData(uint32 guid) { return mCreatureDataMap[guid]; } void DeleteCreatureData(uint32 guid); + + template + void DoCreatureData(Worker& worker) const + { + for (CreatureDataMap::const_iterator itr = mCreatureDataMap.begin(); itr != mCreatureDataMap.end(); ++itr) + if (worker(*itr)) + break; + } + CreatureLocale const* GetCreatureLocale(uint32 entry) const { CreatureLocaleMap::const_iterator itr = mCreatureLocaleMap.find(entry); @@ -769,15 +829,30 @@ class ObjectMgr return &itr->second; } - GameObjectData const* GetGOData(uint32 guid) const + GameObjectDataPair const* GetGODataPair(uint32 guid) const { GameObjectDataMap::const_iterator itr = mGameObjectDataMap.find(guid); if(itr==mGameObjectDataMap.end()) return NULL; - return &itr->second; + return &*itr; } + + GameObjectData const* GetGOData(uint32 guid) const + { + GameObjectDataPair const* dataPair = GetGODataPair(guid); + return dataPair ? &dataPair->second : NULL; + } + GameObjectData& NewGOData(uint32 guid) { return mGameObjectDataMap[guid]; } void DeleteGOData(uint32 guid); + template + void DoGOData(Worker& worker) const + { + for (GameObjectDataMap::const_iterator itr = mGameObjectDataMap.begin(); itr != mGameObjectDataMap.end(); ++itr) + if (worker(*itr)) // arg = GameObjectDataPair + break; + } + MangosStringLocale const* GetMangosStringLocale(int32 entry) const { MangosStringLocaleMap::const_iterator itr = mMangosStringLocaleMap.find(entry); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e3ab05ca3..f894ab4f5 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 "10105" + #define REVISION_NR "10106" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index eb8a6c0c2..8cbb2837a 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_10089_01_mangos_game_event_pool" + #define REVISION_DB_MANGOS "required_10106_02_mangos_mangos_string" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__