Rewrite much of the GM ticket system
* Extract storage and manipulation of tickets to TicketMgr (from ObjectMgr) * Extract ticket commands to TicketCommands.cpp * Adds support for sending GM responses and GM surveys. * Fix structure of several ticket-related packets. * Add support for understanding lag reports. * Thanks Zor for some of the packet structures, and Cyrax for some sniffs * Please report any issues encountered via the tracker. --HG-- branch : trunk
This commit is contained in:
@@ -8816,129 +8816,6 @@ Quest const* GetQuestTemplateStore(uint32 entry)
|
||||
return sObjectMgr.GetQuestTemplate(entry);
|
||||
}
|
||||
|
||||
uint64 ObjectMgr::GenerateGMTicketId()
|
||||
{
|
||||
return ++m_GMticketid;
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadGMTickets()
|
||||
{
|
||||
if (!m_GMTicketList.empty())
|
||||
{
|
||||
for (GmTicketList::const_iterator itr = m_GMTicketList.begin(); itr != m_GMTicketList.end(); ++itr)
|
||||
delete *itr;
|
||||
}
|
||||
m_GMTicketList.clear();
|
||||
m_GMticketid = 0;
|
||||
|
||||
QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment FROM gm_tickets");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
barGoLink bar(1);
|
||||
bar.step();
|
||||
sLog.outString();
|
||||
sLog.outString(">> GM Tickets table is empty, no tickets were loaded.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 count = 0;
|
||||
barGoLink bar ((*result).GetRowCount());
|
||||
GM_Ticket *ticket;
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
ticket = new GM_Ticket;
|
||||
ticket->guid = fields[0].GetUInt64();
|
||||
ticket->playerGuid = fields[1].GetUInt64();
|
||||
ticket->name = fields[2].GetCppString();
|
||||
ticket->message = fields[3].GetCppString();
|
||||
ticket->createtime = fields[4].GetUInt64();
|
||||
ticket->map = fields[5].GetUInt32();
|
||||
ticket->pos_x = fields[6].GetFloat();
|
||||
ticket->pos_y = fields[7].GetFloat();
|
||||
ticket->pos_z = fields[8].GetFloat();
|
||||
ticket->timestamp = fields[9].GetUInt64();
|
||||
ticket->closed = fields[10].GetUInt64();
|
||||
ticket->assignedToGM = fields[11].GetUInt64();
|
||||
ticket->comment = fields[12].GetCppString();
|
||||
++count;
|
||||
bar.step();
|
||||
|
||||
m_GMTicketList.push_back(ticket);
|
||||
|
||||
} while (result->NextRow());
|
||||
|
||||
result = CharacterDatabase.Query("SELECT MAX(guid) from gm_tickets");
|
||||
|
||||
if (result)
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
m_GMticketid = fields[0].GetUInt64();
|
||||
}
|
||||
|
||||
sLog.outString(">> Loaded %u GM Tickets from the database.", count);
|
||||
}
|
||||
|
||||
void ObjectMgr::AddOrUpdateGMTicket(GM_Ticket &ticket, bool create)
|
||||
{
|
||||
if (create)
|
||||
m_GMTicketList.push_back(&ticket);
|
||||
|
||||
_AddOrUpdateGMTicket(ticket);
|
||||
}
|
||||
|
||||
void ObjectMgr::_AddOrUpdateGMTicket(GM_Ticket &ticket)
|
||||
{
|
||||
std::string msg(ticket.message), name(ticket.name), comment(ticket.comment);
|
||||
CharacterDatabase.escape_string(msg);
|
||||
CharacterDatabase.escape_string(name);
|
||||
CharacterDatabase.escape_string(comment);
|
||||
std::ostringstream ss;
|
||||
ss << "REPLACE INTO gm_tickets (guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment) VALUES('";
|
||||
ss << ticket.guid << "', '";
|
||||
ss << ticket.playerGuid << "', '";
|
||||
ss << name << "', '";
|
||||
ss << msg << "', '" ;
|
||||
ss << ticket.createtime << "', '";
|
||||
ss << ticket.map << "', '";
|
||||
ss << ticket.pos_x << "', '";
|
||||
ss << ticket.pos_y << "', '";
|
||||
ss << ticket.pos_z << "', '";
|
||||
ss << ticket.timestamp << "', '";
|
||||
ss << ticket.closed << "', '";
|
||||
ss << ticket.assignedToGM << "', '";
|
||||
ss << comment << "');";
|
||||
|
||||
SQLTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
trans->Append(ss.str().c_str());
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
void ObjectMgr::RemoveGMTicket(GM_Ticket *ticket, int64 source, bool permanently)
|
||||
{
|
||||
for (GmTicketList::iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
|
||||
if ((*i)->guid == ticket->guid)
|
||||
{
|
||||
if (permanently)
|
||||
{
|
||||
CharacterDatabase.PExecute("DELETE FROM gm_tickets WHERE guid = '%u'", ticket->guid);
|
||||
i = m_GMTicketList.erase(i);
|
||||
ticket = NULL;
|
||||
return;
|
||||
}
|
||||
(*i)->closed = source;
|
||||
_AddOrUpdateGMTicket(*(*i));
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::RemoveGMTicket(uint64 ticketGuid, int64 source, bool permanently)
|
||||
{
|
||||
GM_Ticket *ticket = GetGMTicket(ticketGuid);
|
||||
ASSERT(ticket);
|
||||
RemoveGMTicket(ticket, source, permanently);
|
||||
}
|
||||
|
||||
CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unitClass)
|
||||
{
|
||||
CreatureBaseStatsMap::const_iterator it = m_creatureBaseStatsMap.find(MAKE_PAIR16(level,unitClass));
|
||||
|
||||
@@ -337,23 +337,6 @@ enum SkillRangeType
|
||||
SKILL_RANGE_NONE, // 0..0 always
|
||||
};
|
||||
|
||||
struct GM_Ticket
|
||||
{
|
||||
uint64 guid;
|
||||
uint64 playerGuid;
|
||||
std::string name;
|
||||
float pos_x;
|
||||
float pos_y;
|
||||
float pos_z;
|
||||
uint32 map;
|
||||
std::string message;
|
||||
uint64 createtime;
|
||||
uint64 timestamp;
|
||||
int64 closed; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it.
|
||||
uint64 assignedToGM;
|
||||
std::string comment;
|
||||
};
|
||||
typedef std::list<GM_Ticket*> GmTicketList;
|
||||
SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial);
|
||||
|
||||
#define MAX_PLAYER_NAME 12 // max allowed by client name length
|
||||
@@ -713,7 +696,6 @@ class ObjectMgr
|
||||
void LoadTrainerSpell();
|
||||
bool AddSpellToTrainer(uint32 entry, uint32 spell, Field *fields, std::set<uint32> *skip_trainers, std::set<uint32> *talentIds);
|
||||
int LoadReferenceTrainer(uint32 trainer, int32 spell, std::set<uint32> *skip_trainers, std::set<uint32> *talentIds);
|
||||
void LoadGMTickets();
|
||||
|
||||
std::string GeneratePetName(uint32 entry);
|
||||
uint32 GetBaseXP(uint8 level);
|
||||
@@ -950,23 +932,6 @@ class ObjectMgr
|
||||
return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id));
|
||||
}
|
||||
|
||||
GM_Ticket *GetGMTicket(uint64 ticketGuid)
|
||||
{
|
||||
for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
|
||||
if ((*i) && (*i)->guid == ticketGuid)
|
||||
return (*i);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
GM_Ticket *GetGMTicketByPlayer(uint64 playerGuid)
|
||||
{
|
||||
for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
|
||||
if ((*i) && (*i)->playerGuid == playerGuid && (*i)->closed == 0)
|
||||
return (*i);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GossipMenusMapBounds GetGossipMenusMapBounds(uint32 uiMenuId) const
|
||||
{
|
||||
return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId));
|
||||
@@ -986,13 +951,6 @@ class ObjectMgr
|
||||
return GossipMenuItemsMapBoundsNonConst(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId));
|
||||
}
|
||||
|
||||
void AddOrUpdateGMTicket(GM_Ticket &ticket, bool create = false);
|
||||
void _AddOrUpdateGMTicket(GM_Ticket &ticket);
|
||||
void RemoveGMTicket(uint64 ticketGuid, int64 source = -1, bool permanently = false);
|
||||
void RemoveGMTicket(GM_Ticket *ticket, int64 source = -1, bool permanently = false);
|
||||
GmTicketList m_GMTicketList;
|
||||
uint64 GenerateGMTicketId();
|
||||
|
||||
// for wintergrasp only
|
||||
GraveYardMap mGraveYardMap;
|
||||
|
||||
@@ -1013,7 +971,6 @@ class ObjectMgr
|
||||
uint32 m_ItemTextId;
|
||||
uint32 m_mailid;
|
||||
uint32 m_hiPetNumber;
|
||||
uint64 m_GMticketid;
|
||||
|
||||
// first free low guid for seelcted guid type
|
||||
uint32 m_hiCharGuid;
|
||||
|
||||
Reference in New Issue
Block a user