Core/Ticket improved ticket system
- Safely close ticket before character deletion - Allow to keep trace of delete characters tickets (configurable) - Closes #15655 Closes #15699
This commit is contained in:
1 parent
700b5dcb49
commit
7ab1d1b7d0
11 files changed
+68
-18
No files matched your search
@@ -1541,6 +1541,7 @@ DROP TABLE IF EXISTS `gm_ticket`;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `gm_ticket` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`type` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0 open, 1 closed, 2 character deleted',
|
||||
`playerGuid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier of ticket creator',
|
||||
`name` varchar(12) NOT NULL COMMENT 'Name of ticket creator',
|
||||
`description` text NOT NULL,
|
||||
@@ -2529,7 +2530,7 @@ CREATE TABLE `updates` (
|
||||
|
||||
LOCK TABLES `updates` WRITE;
|
||||
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
|
||||
INSERT INTO `updates` VALUES ('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_01_characters.sql','894F08B70449A5481FFAF394EE5571D7FC4D8A3A','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_02_characters.sql','97D7BE0CAADC79F3F11B9FD296B8C6CD40FE593B','ARCHIVED','2015-03-21 21:44:51',0),('2015_06_26_00_characters_335.sql','C2CC6E50AFA1ACCBEBF77CC519AAEB09F3BBAEBC','ARCHIVED','2015-07-13 23:49:22',0),('2015_09_28_00_characters_335.sql','F8682A431D50E54BDC4AC0E7DBED21AE8AAB6AD4','ARCHIVED','2015-09-28 21:00:00',0),('2015_08_26_00_characters_335.sql','C7D6A3A00FECA3EBFF1E71744CA40D3076582374','ARCHIVED','2015-08-26 21:00:00',0),('2015_10_06_00_characters.sql','16842FDD7E8547F2260D3312F53EFF8761EFAB35','ARCHIVED','2015-10-06 16:06:38',0),('2015_10_07_00_characters.sql','E15AB463CEBE321001D7BFDEA4B662FF618728FD','ARCHIVED','2015-10-07 23:32:00',0),('2015_10_12_00_characters.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-10-12 15:35:47',0),('2015_10_28_00_characters.sql','622A9CA8FCE690429EBE23BA071A37C7A007BF8B','ARCHIVED','2015-10-19 14:32:22',0),('2015_10_29_00_characters_335.sql','4555A7F35C107E54C13D74D20F141039ED42943E','RELEASED','2015-10-29 17:05:43',0);
|
||||
INSERT INTO `updates` VALUES ('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_01_characters.sql','894F08B70449A5481FFAF394EE5571D7FC4D8A3A','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_02_characters.sql','97D7BE0CAADC79F3F11B9FD296B8C6CD40FE593B','ARCHIVED','2015-03-21 21:44:51',0),('2015_06_26_00_characters_335.sql','C2CC6E50AFA1ACCBEBF77CC519AAEB09F3BBAEBC','ARCHIVED','2015-07-13 23:49:22',0),('2015_09_28_00_characters_335.sql','F8682A431D50E54BDC4AC0E7DBED21AE8AAB6AD4','ARCHIVED','2015-09-28 21:00:00',0),('2015_08_26_00_characters_335.sql','C7D6A3A00FECA3EBFF1E71744CA40D3076582374','ARCHIVED','2015-08-26 21:00:00',0),('2015_10_06_00_characters.sql','16842FDD7E8547F2260D3312F53EFF8761EFAB35','ARCHIVED','2015-10-06 16:06:38',0),('2015_10_07_00_characters.sql','E15AB463CEBE321001D7BFDEA4B662FF618728FD','ARCHIVED','2015-10-07 23:32:00',0),('2015_10_12_00_characters.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-10-12 15:35:47',0),('2015_10_28_00_characters.sql','622A9CA8FCE690429EBE23BA071A37C7A007BF8B','ARCHIVED','2015-10-19 14:32:22',0),('2015_10_29_00_characters_335.sql','4555A7F35C107E54C13D74D20F141039ED42943E','RELEASED','2015-10-29 17:05:43',0),('2015_11_03_00_characters.sql','CC045717B8FDD9733351E52A5302560CD08AAD57','RELEASED','2015-10-12 15:23:33',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
ALTER TABLE `gm_ticket`
|
||||
ADD COLUMN `type` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0 open, 1 closed, 2 character deleted' AFTER `id`;
|
||||
|
||||
UPDATE `gm_ticket` SET `type` = 1 WHERE `closedBy` != 0 OR `completed` != 0 OR `resolvedBy` != 0;
|
||||
UPDATE `gm_ticket` SET `closedBy` = 0 WHERE `closedBy` < 0;
|
||||
UPDATE `gm_ticket` SET `resolvedBy` = 0 WHERE `resolvedBy` < 0;
|
||||
|
||||
ALTER TABLE `gm_ticket`
|
||||
CHANGE COLUMN `closedBy` `closedBy` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `lastModifiedTime`,
|
||||
CHANGE COLUMN `resolvedBy` `resolvedBy` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'GUID of GM who resolved the ticket' AFTER `needMoreHelp`;
|
||||
@@ -335,10 +335,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// GM Tickets
|
||||
PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT id, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp FROM gm_ticket", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_ticket (id, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp FROM gm_ticket", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_ticket (id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GM_TICKET, "DELETE FROM gm_ticket WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_ticket WHERE playerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION, "UPDATE gm_ticket SET type = 2 WHERE playerGuid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// GM Survey/subsurvey/lag report
|
||||
PrepareStatement(CHAR_INS_GM_SURVEY, "INSERT INTO gm_survey (guid, surveyId, mainSurvey, comment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC);
|
||||
|
||||
@@ -286,6 +286,7 @@ enum CharacterDatabaseStatements
|
||||
CHAR_DEL_GM_TICKET,
|
||||
CHAR_DEL_ALL_GM_TICKETS,
|
||||
CHAR_DEL_PLAYER_GM_TICKETS,
|
||||
CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION,
|
||||
|
||||
CHAR_INS_GM_SURVEY,
|
||||
CHAR_INS_GM_SUBSURVEY,
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellHistory.h"
|
||||
#include "Transport.h"
|
||||
#include "TicketMgr.h"
|
||||
#include "UpdateData.h"
|
||||
#include "UpdateFieldFlags.h"
|
||||
#include "UpdateMask.h"
|
||||
@@ -4546,6 +4547,11 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
|
||||
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
|
||||
guild->DeleteMember(playerguid, false, false, true);
|
||||
|
||||
// close player ticket if any
|
||||
GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid);
|
||||
if (ticket)
|
||||
ticket->SetClosedBy(playerguid);
|
||||
|
||||
// remove from arena teams
|
||||
LeaveAllArenaTeams(playerguid);
|
||||
|
||||
@@ -4757,9 +4763,18 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
if (sWorld->getBoolConfig(CONFIG_DELETE_CHARACTER_TICKET_TRACE))
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION);
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS);
|
||||
stmt->setUInt32(0, guid);
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER);
|
||||
stmt->setUInt32(0, guid);
|
||||
|
||||
@@ -32,11 +32,11 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GM ticket
|
||||
GmTicket::GmTicket() : _id(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0),
|
||||
GmTicket::GmTicket() : _id(0), _type(TICKET_TYPE_OPEN), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0),
|
||||
_completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
|
||||
_needResponse(false), _needMoreHelp(false) { }
|
||||
|
||||
GmTicket::GmTicket(Player* player) : _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)),
|
||||
GmTicket::GmTicket(Player* player) : _type(TICKET_TYPE_OPEN), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(time(NULL)), _lastModifiedTime(time(NULL)),
|
||||
_completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false),
|
||||
_needResponse(false), _needMoreHelp(false)
|
||||
{
|
||||
@@ -49,10 +49,11 @@ GmTicket::~GmTicket() { }
|
||||
|
||||
bool GmTicket::LoadFromDB(Field* fields)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
||||
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
||||
// id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp
|
||||
uint8 index = 0;
|
||||
_id = fields[ index].GetUInt32();
|
||||
_type = TicketType(fields[++index].GetUInt8());
|
||||
_playerGuid = ObjectGuid(HighGuid::Player, fields[++index].GetUInt32());
|
||||
_playerName = fields[++index].GetString();
|
||||
_message = fields[++index].GetString();
|
||||
@@ -75,11 +76,12 @@ bool GmTicket::LoadFromDB(Field* fields)
|
||||
|
||||
void GmTicket::SaveToDB(SQLTransaction& trans) const
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
||||
// id, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
||||
// id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy
|
||||
uint8 index = 0;
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GM_TICKET);
|
||||
stmt->setUInt32( index, _id);
|
||||
stmt->setUInt8 (++index, uint8(_type));
|
||||
stmt->setUInt32(++index, _playerGuid.GetCounter());
|
||||
stmt->setString(++index, _playerName);
|
||||
stmt->setString(++index, _message);
|
||||
|
||||
@@ -77,6 +77,13 @@ enum LagReportType
|
||||
LAG_REPORT_TYPE_SPELL = 6
|
||||
};
|
||||
|
||||
enum TicketType
|
||||
{
|
||||
TICKET_TYPE_OPEN = 0,
|
||||
TICKET_TYPE_CLOSED = 1,
|
||||
TICKET_TYPE_CHARACTER_DELETED = 2,
|
||||
};
|
||||
|
||||
class GmTicket
|
||||
{
|
||||
public:
|
||||
@@ -84,7 +91,7 @@ public:
|
||||
GmTicket(Player* player);
|
||||
~GmTicket();
|
||||
|
||||
bool IsClosed() const { return !_closedBy.IsEmpty(); }
|
||||
bool IsClosed() const { return _type != TICKET_TYPE_OPEN; }
|
||||
bool IsCompleted() const { return _completed; }
|
||||
bool IsFromPlayer(ObjectGuid guid) const { return guid == _playerGuid; }
|
||||
bool IsAssigned() const { return !_assignedTo.IsEmpty(); }
|
||||
@@ -118,7 +125,7 @@ public:
|
||||
else if (_escalatedStatus == TICKET_UNASSIGNED)
|
||||
_escalatedStatus = TICKET_ASSIGNED;
|
||||
}
|
||||
void SetClosedBy(ObjectGuid value) { _closedBy = value; }
|
||||
void SetClosedBy(ObjectGuid value) { _closedBy = value; _type = TICKET_TYPE_CLOSED; }
|
||||
void SetResolvedBy(ObjectGuid value) { _resolvedBy = value; }
|
||||
void SetCompleted() { _completed = true; }
|
||||
void SetMessage(std::string const& message)
|
||||
@@ -150,6 +157,7 @@ public:
|
||||
|
||||
private:
|
||||
uint32 _id;
|
||||
TicketType _type; // 0 = Open, 1 = Closed, 2 = Character deleted
|
||||
ObjectGuid _playerGuid;
|
||||
std::string _playerName;
|
||||
float _posX;
|
||||
@@ -159,8 +167,8 @@ private:
|
||||
std::string _message;
|
||||
uint64 _createTime;
|
||||
uint64 _lastModifiedTime;
|
||||
ObjectGuid _closedBy; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket or read the GM response message, other = GM who closed it.
|
||||
ObjectGuid _resolvedBy; // 0 = Open, -1 = Resolved by Console, GM who resolved it by closing or completing the ticket.
|
||||
ObjectGuid _closedBy; // 0 = Open or Closed by Console (if type = 1), playerGuid = GM who closed it or player abandoned ticket or read the GM response message.
|
||||
ObjectGuid _resolvedBy; // 0 = Open or Resolved by Console (if type = 1), playerGuid = GM who resolved it by closing or completing the ticket.
|
||||
ObjectGuid _assignedTo;
|
||||
std::string _comment;
|
||||
bool _completed;
|
||||
|
||||
@@ -395,6 +395,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
|
||||
///- Read ticket system setting from the config file
|
||||
m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetBoolDefault("AllowTickets", true);
|
||||
m_bool_configs[CONFIG_DELETE_CHARACTER_TICKET_TRACE] = sConfigMgr->GetBoolDefault("DeletedCharacterTicketTrace", false);
|
||||
|
||||
///- Get string for new logins (newly created characters)
|
||||
SetNewCharString(sConfigMgr->GetStringDefault("PlayerStart.String", ""));
|
||||
|
||||
@@ -144,6 +144,7 @@ enum WorldBoolConfigs
|
||||
CONFIG_SHOW_BAN_IN_WORLD,
|
||||
CONFIG_AUTOBROADCAST,
|
||||
CONFIG_ALLOW_TICKETS,
|
||||
CONFIG_DELETE_CHARACTER_TICKET_TRACE,
|
||||
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
|
||||
CONFIG_PRESERVE_CUSTOM_CHANNELS,
|
||||
CONFIG_PDUMP_NO_PATHS,
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid(uint64(-1)));
|
||||
sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid(uint64(0)));
|
||||
sTicketMgr->UpdateLastChange();
|
||||
|
||||
std::string msg = ticket->FormatMessageString(*handler, player ? player->GetName().c_str() : "Console", NULL, NULL, NULL, NULL);
|
||||
@@ -248,7 +248,7 @@ public:
|
||||
Player* gm = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr;
|
||||
|
||||
SQLTransaction trans = SQLTransaction(NULL);
|
||||
ticket->SetResolvedBy(gm ? gm->GetGUID() : ObjectGuid(uint64(-1)));
|
||||
ticket->SetResolvedBy(gm ? gm->GetGUID() : ObjectGuid(uint64(0)));
|
||||
ticket->SetCompleted();
|
||||
ticket->SaveToDB(trans);
|
||||
|
||||
|
||||
@@ -1073,6 +1073,16 @@ Command.LookupMaxResults = 0
|
||||
|
||||
AllowTickets = 1
|
||||
|
||||
#
|
||||
# DeletedCharacterTicketTrace
|
||||
# Description: Keep trace of tickets opened by deleted characters
|
||||
# gm_ticket.playerGuid will be 0, old GUID and character name
|
||||
# will be included in gm_ticket.comment
|
||||
# Default: 0 - (Disabled)
|
||||
# 1 - (Enabled)
|
||||
|
||||
DeletedCharacterTicketTrace = 0
|
||||
|
||||
#
|
||||
# DungeonFinder.OptionsMask
|
||||
# Description: Dungeon and raid finder system.
|
||||
|
||||
Reference in new issue
Block a user