diff --git a/sql/mangos.sql b/sql/mangos.sql index 52fe89d5f..e83b8d668 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_10350_02_mangos_command` bit(1) default NULL + `required_10353_02_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -766,7 +766,7 @@ INSERT INTO `command` VALUES ('tele del',3,'Syntax: .tele del $name\r\n\r\nRemove location with name $name for .tele command locations list.'), ('tele group',1,'Syntax: .tele group#location\r\n\r\nTeleport a selected player and his group members to a given location.'), ('tele name',1,'Syntax: .tele name [#playername] #location\r\n\r\nTeleport the given character to a given location. Character can be offline.'), -('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'), +('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n .ticket respond #num $response\r\n .ticket respond $character_name $response\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'), ('titles add',2,'Syntax: .titles add #title\r\nAdd title #title (id or shift-link) to known titles list for selected player.'), ('titles current',2,'Syntax: .titles current #title\r\nSet title #title (id or shift-link) as current selected titl for selected player. If title not in known title list for player then it will be added to list.'), ('titles remove',2,'Syntax: .titles remove #title\r\nRemove title #title (id or shift-link) from known titles list for selected player.'), @@ -3297,6 +3297,9 @@ INSERT INTO `mangos_string` VALUES (370,'Required heroic keys:',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (371,'Required quest (heroic difficulty):',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (372,'No achievement!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(373,'Response:\n%s ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(374,'Tickets count: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(375,'Player %s not have tickets.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), diff --git a/sql/updates/10353_01_mangos_mangos_string.sql b/sql/updates/10353_01_mangos_mangos_string.sql new file mode 100644 index 000000000..570428551 --- /dev/null +++ b/sql/updates/10353_01_mangos_mangos_string.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_10350_02_mangos_command required_10353_01_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry IN (373, 374, 375); + +INSERT INTO mangos_string VALUES +(373,'Response:\n%s ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(374,'Tickets count: %i\n',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(375,'Player %s not have tickets.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/10353_02_mangos_command.sql b/sql/updates/10353_02_mangos_command.sql new file mode 100644 index 000000000..9b595beec --- /dev/null +++ b/sql/updates/10353_02_mangos_command.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_10353_01_mangos_mangos_string required_10353_02_mangos_command bit; + +DELETE FROM command WHERE name IN ('ticket'); +INSERT INTO command (name, security, help) VALUES +('ticket',2,'Syntax: .ticket on\r\n .ticket off\r\n .ticket #num\r\n .ticket $character_name\r\n .ticket respond #num $response\r\n .ticket respond $character_name $response\r\n\r\non/off for GMs to show or not a new ticket directly, $character_name to show ticket of this character, #num to show ticket #num.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 261c957ed..3bffffb88 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -78,6 +78,8 @@ pkgdata_DATA = \ 10342_02_mangos_command.sql \ 10349_01_mangos_spell_proc_event.sql \ 10350_02_mangos_command.sql \ + 10353_01_mangos_mangos_string.sql \ + 10353_02_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -136,4 +138,6 @@ EXTRA_DIST = \ 10342_02_mangos_command.sql \ 10349_01_mangos_spell_proc_event.sql \ 10350_02_mangos_command.sql \ + 10353_01_mangos_mangos_string.sql \ + 10353_02_mangos_command.sql \ README diff --git a/src/game/Chat.h b/src/game/Chat.h index 4bd95af36..f1a6e17eb 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -31,6 +31,7 @@ struct GameTele; class ChatHandler; class WorldSession; +class GMTicket; class Creature; class Player; class Unit; @@ -608,7 +609,7 @@ class ChatHandler void ShowQuestListHelper(uint32 questId, int32 loc_idx, Player* target = NULL); bool ShowPlayerListHelper(QueryResult* result, uint32* limit = NULL, bool title = true, bool error = true); void ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc); - void ShowTicket(uint64 guid, char const* text, char const* time); + void ShowTicket(GMTicket const* ticket); void ShowTriggerListHelper(AreaTriggerEntry const * atEntry); void ShowTriggerTargetListHelper(uint32 id, AreaTrigger const* at, bool subpart = false); bool LookupPlayerSearchCommand(QueryResult* result, uint32* limit = NULL); diff --git a/src/game/GMTicketMgr.cpp b/src/game/GMTicketMgr.cpp index 71d28c21e..925abab33 100644 --- a/src/game/GMTicketMgr.cpp +++ b/src/game/GMTicketMgr.cpp @@ -33,8 +33,8 @@ void GMTicketMgr::LoadGMTickets() m_GMTicketMap.clear(); // For reload case QueryResult *result = CharacterDatabase.Query( - // 0 1 2 3 - "SELECT guid, ticket_text, response_text, UNIX_TIMESTAMP(ticket_lastchange) FROM character_ticket"); + // 0 1 2 3 4 + "SELECT guid, ticket_text, response_text, UNIX_TIMESTAMP(ticket_lastchange), ticket_id FROM character_ticket ORDER BY ticket_id ASC"); if( !result ) { @@ -49,8 +49,6 @@ void GMTicketMgr::LoadGMTickets() barGoLink bar( (int)result->GetRowCount() ); - uint32 count = 0; - do { bar.step(); @@ -58,14 +56,25 @@ void GMTicketMgr::LoadGMTickets() Field* fields = result->Fetch(); uint32 guid = fields[0].GetUInt32(); - m_GMTicketMap[guid] = GMTicket(guid, fields[1].GetCppString(), fields[2].GetCppString(), time_t(fields[3].GetUInt64())); - ++count; + if (!guid) + continue; + + GMTicket& ticket = m_GMTicketMap[guid]; + + if (ticket.GetPlayerLowGuid() != 0) // already exist + { + CharacterDatabase.PExecute("DELETE FROM character_ticket WHERE ticket_id = '%u'", fields[4].GetUInt32()); + continue; + } + + ticket.Init(guid, fields[1].GetCppString(), fields[2].GetCppString(), time_t(fields[3].GetUInt64())); + m_GMTicketListByCreatingOrder.push_back(&ticket); } while (result->NextRow()); delete result; sLog.outString(); - sLog.outString( ">> Loaded %d GM tickets", count ); + sLog.outString(">> Loaded %d GM tickets", GetTicketCount()); } void GMTicketMgr::DeleteAll() @@ -76,5 +85,6 @@ void GMTicketMgr::DeleteAll() owner->GetSession()->SendGMTicketGetTicket(0x0A, 0); } CharacterDatabase.Execute("DELETE FROM character_ticket"); + m_GMTicketListByCreatingOrder.clear(); m_GMTicketMap.clear(); } diff --git a/src/game/GMTicketMgr.h b/src/game/GMTicketMgr.h index b6c0d15e8..c2bf13ef3 100644 --- a/src/game/GMTicketMgr.h +++ b/src/game/GMTicketMgr.h @@ -27,13 +27,21 @@ class GMTicket { public: - explicit GMTicket() + explicit GMTicket() : m_guid(0), m_lastUpdate(0) { } - GMTicket(uint32 guid, const std::string& text, const std::string& responsetext, time_t update) : m_guid(guid), m_text(text), m_responseText(responsetext), m_lastUpdate(update) + void Init(uint32 guid, const std::string& text, const std::string& responsetext, time_t update) { + m_guid = guid; + m_text = text; + m_responseText = responsetext; + m_lastUpdate =update; + } + uint32 GetPlayerLowGuid() const + { + return m_guid; } const char* GetText() const @@ -99,6 +107,7 @@ class GMTicket time_t m_lastUpdate; }; typedef std::map GMTicketMap; +typedef std::list GMTicketList; // for creating order access class GMTicketMgr { @@ -121,12 +130,26 @@ class GMTicketMgr return m_GMTicketMap.size(); } + GMTicket* GetGMTicketByOrderPos(uint32 pos) + { + if (pos >= GetTicketCount()) + return NULL; + + GMTicketList::iterator itr = m_GMTicketListByCreatingOrder.begin(); + std::advance(itr, pos); + if(itr == m_GMTicketListByCreatingOrder.end()) + return NULL; + return *itr; + } + + void Delete(uint32 guid) { GMTicketMap::iterator itr = m_GMTicketMap.find(guid); if(itr == m_GMTicketMap.end()) return; itr->second.DeleteFromDB(); + m_GMTicketListByCreatingOrder.remove(&itr->second); m_GMTicketMap.erase(itr); } @@ -134,12 +157,20 @@ class GMTicketMgr void Create(uint32 guid, const char* text) { - GMTicket t = GMTicket(guid, text, "", time(NULL)); - t.SaveToDB(); - m_GMTicketMap[guid] = t; + GMTicket& ticket = m_GMTicketMap[guid]; + if (ticket.GetPlayerLowGuid() != 0) // overwrite ticket + { + ticket.DeleteFromDB(); + m_GMTicketListByCreatingOrder.remove(&ticket); + } + + ticket.Init(guid, text, "", time(NULL)); + ticket.SaveToDB(); + m_GMTicketListByCreatingOrder.push_back(&ticket); } private: GMTicketMap m_GMTicketMap; + GMTicketList m_GMTicketListByCreatingOrder; }; #define sTicketMgr MaNGOS::Singleton::Instance() diff --git a/src/game/Language.h b/src/game/Language.h index 52971a23f..ae8eb47df 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -361,7 +361,10 @@ enum MangosStrings LANG_TRIGGER_REQ_KEYS_HEROIC = 370, LANG_TRIGGER_REQ_QUEST_HEROIC = 371, LANG_COMMAND_ACHIEVEMENT_NOTFOUND = 372, - // Room for more level 2 373-399 not used + LANG_COMMAND_TICKETRESPONSE = 373, + LANG_COMMAND_TICKETCOUNT_CONSOLE = 374, + LANG_COMMAND_TICKETNOTEXIST_NAME = 375, + // Room for more level 2 376-399 not used // level 3 chat LANG_SCRIPTS_RELOADED = 400, diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index b96be0cf8..482653874 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -2589,15 +2589,21 @@ bool ChatHandler::HandlePInfoCommand(char* args) } //show tickets -void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time) +void ChatHandler::ShowTicket(GMTicket const* ticket) { + std::string lastupdated = TimeToTimestampStr(ticket->GetLastUpdate()); + std::string name; - if (!sObjectMgr.GetPlayerNameByGUID(guid, name)) + if (!sObjectMgr.GetPlayerNameByGUID(MAKE_NEW_GUID(ticket->GetPlayerLowGuid(), 0, HIGHGUID_PLAYER), name)) name = GetMangosString(LANG_UNKNOWN); std::string nameLink = playerLink(name); - PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text); + char const* response = ticket->GetResponse(); + + PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(), lastupdated.c_str(), ticket->GetText()); + if (strlen(response)) + PSendSysMessage(LANG_COMMAND_TICKETRESPONSE, ticket->GetResponse()); } //ticket commands @@ -2608,18 +2614,17 @@ bool ChatHandler::HandleTicketCommand(char* args) // ticket if (!px) { - if (!m_session) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - size_t count = sTicketMgr.GetTicketCount(); - bool accept = m_session->GetPlayer()->isAcceptTickets(); + if (m_session) + { + bool accept = m_session->GetPlayer()->isAcceptTickets(); + + PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF)); + } + else + PSendSysMessage(LANG_COMMAND_TICKETCOUNT_CONSOLE, count); - PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetMangosString(LANG_ON) : GetMangosString(LANG_OFF)); return true; } @@ -2656,42 +2661,50 @@ bool ChatHandler::HandleTicketCommand(char* args) // ticket respond if (strncmp(px, "respond", 8) == 0) { - std::string plName = ExtractPlayerNameFromLink(&args); - if (plName.empty()) + GMTicket* ticket = NULL; + + // ticket respond #num + uint32 num; + if (ExtractUInt32(&args, num)) { - SendSysMessage(LANG_CMD_SYNTAX); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = sObjectMgr.GetPlayerGUIDByName(plName); - - if (!guid) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(guid)); - - if (!ticket) - { - PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, GUID_LOPART(guid)); - SetSentErrorMessage(true); - return false; + if (num == 0) + return false; + + // mgr numbering tickets start from 0 + ticket = sTicketMgr.GetGMTicketByOrderPos(num-1); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + } + else + { + uint64 target_guid; + std::string target_name; + if (!ExtractPlayerTarget(&args, NULL, &target_guid, &target_name)) + return false; + + // ticket respond $char_name + ticket = sTicketMgr.GetGMTicket(GUID_LOPART(target_guid)); + + if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); + SetSentErrorMessage(true); + return false; + } } + // no response text? if (!*args) - { - SendSysMessage(LANG_CMD_SYNTAX); - SetSentErrorMessage(true); return false; - } ticket->SetResponseText(args); - if (Player* pl = sObjectMgr.GetPlayer(guid)) + if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, ticket->GetPlayerLowGuid()))) pl->GetSession()->SendGMResponse(ticket); return true; @@ -2704,38 +2717,34 @@ bool ChatHandler::HandleTicketCommand(char* args) if (num == 0) return false; - QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1); - - if (!result) + // mgr numbering tickets start from 0 + GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(num-1); + if (!ticket) { PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); SetSentErrorMessage(true); return false; } - Field* fields = result->Fetch(); - - uint32 guid = fields[0].GetUInt32(); - char const* text = fields[1].GetString(); - char const* time = fields[2].GetString(); - - ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time); - delete result; + ShowTicket(ticket); return true; } uint64 target_guid; - if (!ExtractPlayerTarget(&px, NULL, &target_guid)) + std::string target_name; + if (!ExtractPlayerTarget(&px, NULL, &target_guid, &target_name)) return false; // ticket $char_name GMTicket* ticket = sTicketMgr.GetGMTicket(GUID_LOPART(target_guid)); if (!ticket) + { + PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST_NAME, target_name.c_str()); + SetSentErrorMessage(true); return false; + } - std::string time = TimeToTimestampStr(ticket->GetLastUpdate()); - - ShowTicket(target_guid, ticket->GetText(), time.c_str()); + ShowTicket(ticket); return true; } @@ -2763,21 +2772,22 @@ bool ChatHandler::HandleDelTicketCommand(char *args) if (num ==0) return false; - QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1); - if (!result) + // mgr numbering tickets start from 0 + GMTicket* ticket = sTicketMgr.GetGMTicketByOrderPos(num-1); + + if (!ticket) { PSendSysMessage(LANG_COMMAND_TICKETNOTEXIST, num); SetSentErrorMessage(true); return false; } - Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - delete result; - sTicketMgr.Delete(guid); + uint32 lowguid = ticket->GetPlayerLowGuid(); + + sTicketMgr.Delete(lowguid); //notify player - if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, guid))) + if (Player* pl = sObjectMgr.GetPlayer(ObjectGuid(HIGHGUID_PLAYER, lowguid))) { pl->GetSession()->SendGMTicketGetTicket(0x0A, 0); PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str()); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 51275a48b..01263e0e8 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 "10352" + #define REVISION_NR "10353" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index a759731f5..0a92ae43d 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_10332_02_characters_pet_aura" - #define REVISION_DB_MANGOS "required_10350_02_mangos_command" + #define REVISION_DB_MANGOS "required_10353_02_mangos_command" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__