Files
TrinityCore2/src/server/game/Chat/Commands/Level1.cpp
T

769 lines
23 KiB
C++
Executable File

/*
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Common.h"
#include "DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "World.h"
#include "ObjectMgr.h"
#include "TicketMgr.h"
#include "Player.h"
#include "AccountMgr.h"
#include "Opcodes.h"
#include "Chat.h"
#include "Log.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Language.h"
#include "CellImpl.h"
#include "InstanceSaveMgr.h"
#include "Util.h"
#include "Group.h"
#ifdef _DEBUG_VMAPS
#include "VMapFactory.h"
#endif
bool ChatHandler::HandleNameAnnounceCommand(const char* args)
{
WorldPacket data;
if (!*args)
return false;
std::string name("Console");
if (WorldSession* session = GetSession())
name = session->GetPlayer()->GetName();
sWorld->SendWorldText(LANG_ANNOUNCE_COLOR, name.c_str(), args);
return true;
}
bool ChatHandler::HandleGMNameAnnounceCommand(const char* args)
{
WorldPacket data;
if (!*args)
return false;
std::string name("Console");
if (WorldSession* session = GetSession())
name = session->GetPlayer()->GetName();
sWorld->SendGMText(LANG_GM_ANNOUNCE_COLOR, name.c_str(), args);
return true;
}
// global announce
bool ChatHandler::HandleAnnounceCommand(const char* args)
{
if (!*args)
return false;
char buff[2048];
sprintf(buff, GetTrinityString(LANG_SYSTEMMESSAGE), args);
sWorld->SendServerMessage(SERVER_MSG_STRING, buff);
return true;
}
// announce to logged in GMs
bool ChatHandler::HandleGMAnnounceCommand(const char* args)
{
if (!*args)
return false;
sWorld->SendGMText(LANG_GM_BROADCAST, args);
return true;
}
//notification player at the screen
bool ChatHandler::HandleNotifyCommand(const char* args)
{
if (!*args)
return false;
std::string str = GetTrinityString(LANG_GLOBAL_NOTIFY);
str += args;
WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
data << str;
sWorld->SendGlobalMessage(&data);
return true;
}
//notification GM at the screen
bool ChatHandler::HandleGMNotifyCommand(const char* args)
{
if (!*args)
return false;
std::string str = GetTrinityString(LANG_GM_NOTIFY);
str += args;
WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
data << str;
sWorld->SendGlobalGMMessage(&data);
return true;
}
//Summon Player
bool ChatHandler::HandleSummonCommand(const char* args)
{
Player* target;
uint64 target_guid;
std::string target_name;
if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
return false;
Player* _player = m_session->GetPlayer();
if (target == _player || target_guid == _player->GetGUID())
{
PSendSysMessage(LANG_CANT_TELEPORT_SELF);
SetSentErrorMessage(true);
return false;
}
if (target)
{
std::string nameLink = playerLink(target_name);
// check online security
if (HasLowerSecurity(target, 0))
return false;
if (target->IsBeingTeleported())
{
PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
Map* pMap = m_session->GetPlayer()->GetMap();
if (pMap->IsBattlegroundOrArena())
{
// only allow if gm mode is on
if (!_player->isGameMaster())
{
PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
// if both players are in different bgs
else if (target->GetBattlegroundId() && m_session->GetPlayer()->GetBattlegroundId() != target->GetBattlegroundId())
target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff
// all's well, set bg id
// when porting out from the bg, it will be reset to 0
target->SetBattlegroundId(m_session->GetPlayer()->GetBattlegroundId(), m_session->GetPlayer()->GetBattlegroundTypeId());
// remember current position as entry point for return at bg end teleportation
if (!target->GetMap()->IsBattlegroundOrArena())
target->SetBattlegroundEntryPoint();
}
else if (pMap->IsDungeon())
{
Map* cMap = target->GetMap();
if (cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId())
target->UnbindInstance(pMap->GetInstanceId(), target->GetDungeonDifficulty(), true);
// we are in instance, and can summon only player in our group with us as lead
if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() ||
(target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) ||
(m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()))
// the last check is a bit excessive, but let it be, just in case
{
PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
}
PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), "");
if (needReportToTarget(target))
ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str());
// stop flight if need
if (target->isInFlight())
{
target->GetMotionMaster()->MovementExpired();
target->CleanupAfterTaxiFlight();
}
// save only in non-flight case
else
target->SaveRecallPosition();
// before GM
float x, y, z;
m_session->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize());
target->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation());
target->SetPhaseMask(m_session->GetPlayer()->GetPhaseMask(), true);
}
else
{
// check offline security
if (HasLowerSecurity(NULL, target_guid))
return false;
std::string nameLink = playerLink(target_name);
PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), GetTrinityString(LANG_OFFLINE));
// in point where GM stay
Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(),
m_session->GetPlayer()->GetPositionX(),
m_session->GetPlayer()->GetPositionY(),
m_session->GetPlayer()->GetPositionZ(),
m_session->GetPlayer()->GetOrientation(),
m_session->GetPlayer()->GetZoneId(),
target_guid);
}
return true;
}
//Teleport to Player
bool ChatHandler::HandleAppearCommand(const char* args)
{
Player* target;
uint64 target_guid;
std::string target_name;
if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
return false;
Player* _player = m_session->GetPlayer();
if (target == _player || target_guid == _player->GetGUID())
{
SendSysMessage(LANG_CANT_TELEPORT_SELF);
SetSentErrorMessage(true);
return false;
}
if (target)
{
// check online security
if (HasLowerSecurity(target, 0))
return false;
std::string chrNameLink = playerLink(target_name);
Map* cMap = target->GetMap();
if (cMap->IsBattlegroundOrArena())
{
// only allow if gm mode is on
if (!_player->isGameMaster())
{
PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
// if both players are in different bgs
else if (_player->GetBattlegroundId() && _player->GetBattlegroundId() != target->GetBattlegroundId())
_player->LeaveBattleground(false); // Note: should be changed so _player gets no Deserter debuff
// all's well, set bg id
// when porting out from the bg, it will be reset to 0
_player->SetBattlegroundId(target->GetBattlegroundId(), target->GetBattlegroundTypeId());
// remember current position as entry point for return at bg end teleportation
if (!_player->GetMap()->IsBattlegroundOrArena())
_player->SetBattlegroundEntryPoint();
}
else if (cMap->IsDungeon())
{
// we have to go to instance, and can go to player only if:
// 1) we are in his group (either as leader or as member)
// 2) we are not bound to any group and have GM mode on
if (_player->GetGroup())
{
// we are in group, we can go only if we are in the player group
if (_player->GetGroup() != target->GetGroup())
{
PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY, chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
}
else
{
// we are not in group, let's verify our GM mode
if (!_player->isGameMaster())
{
PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM, chrNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
}
// if the player or the player's group is bound to another instance
// the player will not be bound to another one
InstancePlayerBind *pBind = _player->GetBoundInstance(target->GetMapId(), target->GetDifficulty(cMap->IsRaid()));
if (!pBind)
{
Group* group = _player->GetGroup();
// if no bind exists, create a solo bind
InstanceGroupBind *gBind = group ? group->GetBoundInstance(target) : NULL; // if no bind exists, create a solo bind
if (!gBind)
if (InstanceSave *save = sInstanceSaveMgr->GetInstanceSave(target->GetInstanceId()))
_player->BindToInstance(save, !save->CanReset());
}
if (cMap->IsRaid())
_player->SetRaidDifficulty(target->GetRaidDifficulty());
else
_player->SetDungeonDifficulty(target->GetDungeonDifficulty());
}
PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str());
// stop flight if need
if (_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->CleanupAfterTaxiFlight();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
// to point to see at target with same orientation
float x, y, z;
target->GetContactPoint(_player, x, y, z);
_player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE);
_player->SetPhaseMask(target->GetPhaseMask(), true);
}
else
{
// check offline security
if (HasLowerSecurity(NULL, target_guid))
return false;
std::string nameLink = playerLink(target_name);
PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str());
// to point where player stay (if loaded)
float x, y, z, o;
uint32 map;
bool in_flight;
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->CleanupAfterTaxiFlight();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
_player->TeleportTo(map, x, y, z, _player->GetOrientation());
}
return true;
}
// Teleport player to last position
bool ChatHandler::HandleRecallCommand(const char* args)
{
Player* target;
if (!extractPlayerTarget((char*)args, &target))
return false;
// check online security
if (HasLowerSecurity(target, 0))
return false;
if (target->IsBeingTeleported())
{
PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(target).c_str());
SetSentErrorMessage(true);
return false;
}
// stop flight if need
if (target->isInFlight())
{
target->GetMotionMaster()->MovementExpired();
target->CleanupAfterTaxiFlight();
}
target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO);
return true;
}
//Enable On\OFF all taxi paths
bool ChatHandler::HandleTaxiCheatCommand(const char* args)
{
if (!*args)
{
SendSysMessage(LANG_USE_BOL);
SetSentErrorMessage(true);
return false;
}
std::string argstr = (char*)args;
Player *chr = getSelectedPlayer();
if (!chr)
{
chr=m_session->GetPlayer();
}
// check online security
else if (HasLowerSecurity(chr, 0))
return false;
if (argstr == "on")
{
chr->SetTaxiCheater(true);
PSendSysMessage(LANG_YOU_GIVE_TAXIS, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetNameLink().c_str());
return true;
}
if (argstr == "off")
{
chr->SetTaxiCheater(false);
PSendSysMessage(LANG_YOU_REMOVE_TAXIS, GetNameLink(chr).c_str());
if (needReportToTarget(chr))
ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetNameLink().c_str());
return true;
}
SendSysMessage(LANG_USE_BOL);
SetSentErrorMessage(true);
return false;
}
bool ChatHandler::HandleLookupAreaCommand(const char* args)
{
if (!*args)
return false;
std::string namepart = args;
std::wstring wnamepart;
if (!Utf8toWStr (namepart, wnamepart))
return false;
bool found = false;
uint32 count = 0;
uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS);
// converting string that we try to find to lower case
wstrToLower (wnamepart);
// Search in AreaTable.dbc
for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows (); ++areaflag)
{
AreaTableEntry const *areaEntry = sAreaStore.LookupEntry (areaflag);
if (areaEntry)
{
int loc = GetSessionDbcLocale ();
std::string name = areaEntry->area_name[loc];
if (name.empty())
continue;
if (!Utf8FitTo (name, wnamepart))
{
loc = 0;
for (; loc < TOTAL_LOCALES; ++loc)
{
if (loc == GetSessionDbcLocale ())
continue;
name = areaEntry->area_name[loc];
if (name.empty ())
continue;
if (Utf8FitTo (name, wnamepart))
break;
}
}
if (loc < TOTAL_LOCALES)
{
if (maxResults && count++ == maxResults)
{
PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
return true;
}
// send area in "id - [name]" format
std::ostringstream ss;
if (m_session)
ss << areaEntry->ID << " - |cffffffff|Harea:" << areaEntry->ID << "|h[" << name << ' ' << localeNames[loc]<< "]|h|r";
else
ss << areaEntry->ID << " - " << name << ' ' << localeNames[loc];
SendSysMessage (ss.str ().c_str());
if (!found)
found = true;
}
}
}
if (!found)
SendSysMessage (LANG_COMMAND_NOAREAFOUND);
return true;
}
//Find tele in game_tele order by name
bool ChatHandler::HandleLookupTeleCommand(const char * args)
{
if (!*args)
{
SendSysMessage(LANG_COMMAND_TELE_PARAMETER);
SetSentErrorMessage(true);
return false;
}
char const* str = strtok((char*)args, " ");
if (!str)
return false;
std::string namepart = str;
std::wstring wnamepart;
if (!Utf8toWStr(namepart, wnamepart))
return false;
// converting string that we try to find to lower case
wstrToLower(wnamepart);
std::ostringstream reply;
uint32 count = 0;
uint32 maxResults = sWorld->getIntConfig(CONFIG_MAX_RESULTS_LOOKUP_COMMANDS);
bool limitReached = false;
GameTeleMap const & teleMap = sObjectMgr->GetGameTeleMap();
for (GameTeleMap::const_iterator itr = teleMap.begin(); itr != teleMap.end(); ++itr)
{
GameTele const* tele = &itr->second;
if (tele->wnameLow.find(wnamepart) == std::wstring::npos)
continue;
if (maxResults && count++ == maxResults)
{
limitReached = true;
break;
}
if (m_session)
reply << " |cffffffff|Htele:" << itr->first << "|h[" << tele->name << "]|h|r\n";
else
reply << " " << itr->first << ' ' << tele->name << "\n";
}
if (reply.str().empty())
SendSysMessage(LANG_COMMAND_TELE_NOLOCATION);
else
PSendSysMessage(LANG_COMMAND_TELE_LOCATION, reply.str().c_str());
if (limitReached)
PSendSysMessage(LANG_COMMAND_LOOKUP_MAX_RESULTS, maxResults);
return true;
}
//Enable\Dissable accept whispers (for GM)
bool ChatHandler::HandleWhispersCommand(const char* args)
{
if (!*args)
{
PSendSysMessage(LANG_COMMAND_WHISPERACCEPTING, m_session->GetPlayer()->isAcceptWhispers() ? GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF));
return true;
}
std::string argstr = (char*)args;
// whisper on
if (argstr == "on")
{
m_session->GetPlayer()->SetAcceptWhispers(true);
SendSysMessage(LANG_COMMAND_WHISPERON);
return true;
}
// whisper off
if (argstr == "off")
{
// Remove all players from the Gamemaster's whisper whitelist
m_session->GetPlayer()->ClearWhisperWhiteList();
m_session->GetPlayer()->SetAcceptWhispers(false);
SendSysMessage(LANG_COMMAND_WHISPEROFF);
return true;
}
SendSysMessage(LANG_USE_BOL);
SetSentErrorMessage(true);
return false;
}
//Save all players in the world
bool ChatHandler::HandleSaveAllCommand(const char* /*args*/)
{
sObjectAccessor->SaveAllPlayers();
SendSysMessage(LANG_PLAYERS_SAVED);
return true;
}
//Send mail by command
bool ChatHandler::HandleSendMailCommand(const char* args)
{
// format: name "subject text" "mail text"
Player* target;
uint64 target_guid;
std::string target_name;
if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name))
return false;
char* tail1 = strtok(NULL, "");
if (!tail1)
return false;
char* msgSubject = extractQuotedArg(tail1);
if (!msgSubject)
return false;
char* tail2 = strtok(NULL, "");
if (!tail2)
return false;
char* msgText = extractQuotedArg(tail2);
if (!msgText)
return false;
// msgSubject, msgText isn't NUL after prev. check
std::string subject = msgSubject;
std::string text = msgText;
// from console show not existed sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM);
//- TODO: Fix poor design
SQLTransaction trans = CharacterDatabase.BeginTransaction();
MailDraft(subject, text)
.SendMailTo(trans, MailReceiver(target, GUID_LOPART(target_guid)), sender);
CharacterDatabase.CommitTransaction(trans);
std::string nameLink = playerLink(target_name);
PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());
return true;
}
//Summon group of player
bool ChatHandler::HandleGroupSummonCommand(const char* args)
{
Player* target;
if (!extractPlayerTarget((char*)args, &target))
return false;
// check online security
if (HasLowerSecurity(target, 0))
return false;
Group *grp = target->GetGroup();
std::string nameLink = GetNameLink(target);
if (!grp)
{
PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str());
SetSentErrorMessage(true);
return false;
}
Map* gmMap = m_session->GetPlayer()->GetMap();
bool to_instance = gmMap->Instanceable();
// we are in instance, and can summon only player in our group with us as lead
if (to_instance && (
!m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) ||
(m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())))
// the last check is a bit excessive, but let it be, just in case
{
SendSysMessage(LANG_CANNOT_SUMMON_TO_INST);
SetSentErrorMessage(true);
return false;
}
for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
{
Player *pl = itr->getSource();
if (!pl || pl == m_session->GetPlayer() || !pl->GetSession())
continue;
// check online security
if (HasLowerSecurity(pl, 0))
return false;
std::string plNameLink = GetNameLink(pl);
if (pl->IsBeingTeleported() == true)
{
PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
if (to_instance)
{
Map* plMap = pl->GetMap();
if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId())
{
// cannot summon from instance to instance
PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str());
SetSentErrorMessage(true);
return false;
}
}
PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), "");
if (needReportToTarget(pl))
ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetNameLink().c_str());
// stop flight if need
if (pl->isInFlight())
{
pl->GetMotionMaster()->MovementExpired();
pl->CleanupAfterTaxiFlight();
}
// save only in non-flight case
else
pl->SaveRecallPosition();
// before GM
float x, y, z;
m_session->GetPlayer()->GetClosePoint(x, y, z, pl->GetObjectSize());
pl->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, pl->GetOrientation());
}
return true;
}