[10972] Implement mass mail gm commands.

* New comamnds mirror related normal sedn commands:
   - send mass items
   - send mass mail
   - send mass money

* Instead player name it expect or numeric racemask or textual race/team name or 'all'.
This commit is contained in:
VladimirMangos 2011-01-06 06:52:39 +03:00
parent f347f4bc00
commit da228b707d
10 changed files with 261 additions and 32 deletions

View file

@ -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_10951_01_mangos_spell_proc_event` bit(1) default NULL
`required_10972_01_mangos_command` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -738,6 +738,9 @@ INSERT INTO `command` VALUES
('saveall',1,'Syntax: .saveall\r\n\r\nSave all characters in game.'),
('send items',3,'Syntax: .send items #playername "#subject" "#text" itemid1[:count1] itemid2[:count2] ... itemidN[:countN]\r\n\r\nSend a mail to a player. Subject and mail text must be in "". If for itemid not provided related count values then expected 1, if count > max items in stack then items will be send in required amount stacks. All stacks amount in mail limited to 12.'),
('send mail',1,'Syntax: .send mail #playername "#subject" "#text"\r\n\r\nSend a mail to a player. Subject and mail text must be in "".'),
('send mass items',3,'Syntax: .send mass items #racemask|$racename|alliance|horde|all "#subject" "#text" itemid1[:count1] itemid2[:count2] ... itemidN[:countN]\r\n\r\nSend a mail to players. Subject and mail text must be in "". If for itemid not provided related count values then expected 1, if count > max items in stack then items will be send in required amount stacks. All stacks amount in mail limited to 12.'),
('send mass mail',1,'Syntax: .send mass mail #racemask|$racename|alliance|horde|all "#subject" "#text"\r\n\r\nSend a mail to players. Subject and mail text must be in "".'),
('send mass money','3','Syntax: .send mass money #racemask|$racename|alliance|horde|all "#subject" "#text" #money\r\n\r\nSend mail with money to players. Subject and mail text must be in "".'),
('send message',3,'Syntax: .send message $playername $message\r\n\r\nSend screen message to player from ADMINISTRATOR.'),
('send money','3','Syntax: .send money #playername "#subject" "#text" #money\r\n\r\nSend mail with money to a player. Subject and mail text must be in "".'),
('server corpses',2,'Syntax: .server corpses\r\n\r\nTriggering corpses expire check in world.'),

View file

@ -0,0 +1,9 @@
ALTER TABLE db_version CHANGE COLUMN required_10951_01_mangos_spell_proc_event required_10972_01_mangos_command bit;
DELETE FROM command WHERE name IN ('send mass items','send mass mail','send mass money');
INSERT INTO command (name, security, help) VALUES
('send mass items',3,'Syntax: .send mass items #racemask|$racename|alliance|horde|all "#subject" "#text" itemid1[:count1] itemid2[:count2] ... itemidN[:countN]\r\n\r\nSend a mail to players. Subject and mail text must be in "". If for itemid not provided related count values then expected 1, if count > max items in stack then items will be send in required amount stacks. All stacks amount in mail limited to 12.'),
('send mass mail',1,'Syntax: .send mass mail #racemask|$racename|alliance|horde|all "#subject" "#text"\r\n\r\nSend a mail to players. Subject and mail text must be in "".'),
('send mass money','3','Syntax: .send mass money #racemask|$racename|alliance|horde|all "#subject" "#text" #money\r\n\r\nSend mail with money to players. Subject and mail text must be in "".');

View file

@ -144,6 +144,7 @@ pkgdata_DATA = \
10949_01_mangos_mangos_string.sql \
10950_01_mangos_mangos_string.sql \
10951_01_mangos_spell_proc_event.sql \
10972_01_mangos_command.sql \
README
## Additional files to include when running 'make dist'
@ -268,4 +269,5 @@ EXTRA_DIST = \
10949_01_mangos_mangos_string.sql \
10950_01_mangos_mangos_string.sql \
10951_01_mangos_spell_proc_event.sql \
10972_01_mangos_command.sql \
README

View file

@ -546,8 +546,18 @@ ChatCommand * ChatHandler::getCommandTable()
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand sendMassCommandTable[] =
{
{ "items", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMassItemsCommand, "", NULL },
{ "mail", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMassMailCommand, "", NULL },
{ "money", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMassMoneyCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand sendCommandTable[] =
{
{ "mass", SEC_ADMINISTRATOR, true, NULL, "", sendMassCommandTable },
{ "items", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendItemsCommand, "", NULL },
{ "mail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL },
{ "message", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL },
@ -3264,6 +3274,63 @@ uint32 ChatHandler::ExtractAccountId(char** args, std::string* accountName /*= N
return account_id;
}
struct RaceMaskName
{
char const* literal;
uint32 raceMask;
};
static RaceMaskName const raceMaskNames[] =
{
// races
{ "human", (1<<(RACE_HUMAN-1)) },
{ "orc", (1<<(RACE_ORC-1)) },
{ "dwarf", (1<<(RACE_DWARF-1)) },
{ "nightelf", (1<<(RACE_NIGHTELF-1))},
{ "undead", (1<<(RACE_UNDEAD-1)) },
{ "tauren", (1<<(RACE_TAUREN-1)) },
{ "gnome", (1<<(RACE_GNOME-1)) },
{ "troll", (1<<(RACE_TROLL-1)) },
{ "bloodelf", (1<<(RACE_BLOODELF-1))},
{ "draenei", (1<<(RACE_DRAENEI-1)) },
// masks
{ "alliance", RACEMASK_ALLIANCE },
{ "horde", RACEMASK_HORDE },
{ "all", RACEMASK_ALL_PLAYABLE },
// terminator
{ NULL, 0 }
};
bool ChatHandler::ExtractRaceMask(char** text, uint32& raceMask, char const** maskName /*=NULL*/)
{
if (ExtractUInt32(text, raceMask))
{
if (maskName)
*maskName = "custom mask";
}
else
{
for (RaceMaskName const* itr = raceMaskNames; itr->literal; ++itr)
{
if (ExtractLiteralArg(text, itr->literal))
{
raceMask = itr->raceMask;
if (maskName)
*maskName = itr->literal;
break;
}
}
if (!raceMask)
return false;
}
return true;
}
std::string ChatHandler::GetNameLink(Player* chr) const
{
return playerLink(chr->GetName());

View file

@ -37,6 +37,7 @@ class ChatHandler;
class WorldSession;
class WorldPacket;
class GMTicket;
class MailDraft;
class Object;
class GameObject;
class Creature;
@ -462,6 +463,10 @@ class ChatHandler
bool HandleSendMessageCommand(char* args);
bool HandleSendMoneyCommand(char* args);
bool HandleSendMassItemsCommand(char* args);
bool HandleSendMassMailCommand(char* args);
bool HandleSendMassMoneyCommand(char* args);
bool HandleServerCorpsesCommand(char* args);
bool HandleServerExitCommand(char* args);
bool HandleServerIdleRestartCommand(char* args);
@ -601,6 +606,7 @@ class ChatHandler
ObjectGuid ExtractGuidFromLink(char** text);
GameTele const* ExtractGameTeleFromLink(char** text);
bool ExtractLocationFromLink(char** text, uint32& mapid, float& x, float& y, float& z);
bool ExtractRaceMask(char** text, uint32& raceMask, char const** maskName = NULL);
std::string ExtractPlayerNameFromLink(char** text);
bool ExtractPlayerTarget(char** args, Player** player, ObjectGuid* player_guid = NULL, std::string* player_name = NULL);
// select by arg (name/link) or in-game selection online/offline player
@ -633,6 +639,11 @@ class ChatHandler
bool HandleGetValueHelper(Object* target, uint32 field, char* typeStr);
bool HandlerDebugModValueHelper(Object* target, uint32 field, char* typeStr, char* valStr);
bool HandleSetValueHelper(Object* target, uint32 field, char* typeStr, char* valStr);
bool HandleSendItemsHelper(MailDraft& draft, char* args);
bool HandleSendMailHelper(MailDraft& draft, char* args);
bool HandleSendMoneyHelper(MailDraft& draft, char* args);
template<typename T>
void ShowNpcOrGoSpawnInformation(uint32 guid);
template <typename T>

View file

@ -1755,19 +1755,16 @@ bool ChatHandler::HandleSendMailCommand(char* args)
if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name))
return false;
char* msgSubject = ExtractQuotedArg(&args);
if (!msgSubject)
return false;
MailDraft draft;
char* msgText = ExtractQuotedArg(&args);
if (!msgText)
// fill draft
if (!HandleSendMailHelper(draft, args))
return false;
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
MailDraft(msgSubject, msgText)
.SendMailTo(MailReceiver(target, target_guid),sender);
draft.SendMailTo(MailReceiver(target, target_guid),sender);
std::string nameLink = playerLink(target_name);
PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());

View file

@ -33,6 +33,7 @@
#include "Guild.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
#include "MassMailMgr.h"
#include "ScriptMgr.h"
#include "Language.h"
#include "GridNotifiersImpl.h"
@ -6496,16 +6497,56 @@ bool ChatHandler::HandleAccountSetAddonCommand(char* args)
return true;
}
//Send items by mail
bool ChatHandler::HandleSendItemsCommand(char* args)
bool ChatHandler::HandleSendMailHelper(MailDraft& draft, char* args)
{
// format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
Player* receiver;
ObjectGuid receiver_guid;
std::string receiver_name;
if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name))
// format: "subject text" "mail text"
char* msgSubject = ExtractQuotedArg(&args);
if (!msgSubject)
return false;
char* msgText = ExtractQuotedArg(&args);
if (!msgText)
return false;
// msgSubject, msgText isn't NUL after prev. check
draft.SetSubjectAndBody(msgSubject, msgText);
return true;
}
bool ChatHandler::HandleSendMassMailCommand(char* args)
{
// format: raceMask "subject text" "mail text"
uint32 raceMask = 0;
char const* name = NULL;
if (!ExtractRaceMask(&args, raceMask, &name))
return false;
// need dynamic object because it trasfered to mass mailer
MailDraft* draft = new MailDraft;
// fill mail
if (!HandleSendMailHelper(*draft, args))
{
delete draft;
return false;
}
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
sMassMailMgr.AddMassMailTask(draft, sender, raceMask);
PSendSysMessage(LANG_MAIL_SENT, name);
return true;
}
bool ChatHandler::HandleSendItemsHelper(MailDraft& draft, char* args)
{
// format: "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
char* msgSubject = ExtractQuotedArg(&args);
if (!msgSubject)
return false;
@ -6567,11 +6608,8 @@ bool ChatHandler::HandleSendItemsCommand(char* args)
}
}
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
// fill mail
MailDraft draft(msgSubject, msgText);
draft.SetSubjectAndBody(msgSubject, msgText);
for(ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr)
{
@ -6582,6 +6620,27 @@ bool ChatHandler::HandleSendItemsCommand(char* args)
}
}
return true;
}
bool ChatHandler::HandleSendItemsCommand(char* args)
{
// format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
Player* receiver;
ObjectGuid receiver_guid;
std::string receiver_name;
if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name))
return false;
MailDraft draft;
// fill mail
if (!HandleSendItemsHelper(draft, args))
return false;
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
draft.SendMailTo(MailReceiver(receiver, receiver_guid), sender);
std::string nameLink = playerLink(receiver_name);
@ -6589,17 +6648,40 @@ bool ChatHandler::HandleSendItemsCommand(char* args)
return true;
}
///Send money by mail
bool ChatHandler::HandleSendMoneyCommand(char* args)
bool ChatHandler::HandleSendMassItemsCommand(char* args)
{
/// format: name "subject text" "mail text" money
// format: racemask "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12]
Player* receiver;
ObjectGuid receiver_guid;
std::string receiver_name;
if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name))
uint32 raceMask = 0;
char const* name = NULL;
if (!ExtractRaceMask(&args, raceMask, &name))
return false;
// need dynamic object because it trasfered to mass mailer
MailDraft* draft = new MailDraft;
// fill mail
if (!HandleSendItemsHelper(*draft, args))
{
delete draft;
return false;
}
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
sMassMailMgr.AddMassMailTask(draft, sender, raceMask);
PSendSysMessage(LANG_MAIL_SENT, name);
return true;
}
bool ChatHandler::HandleSendMoneyHelper(MailDraft& draft, char* args)
{
/// format: "subject text" "mail text" money
char* msgSubject = ExtractQuotedArg(&args);
if (!msgSubject)
return false;
@ -6615,18 +6697,67 @@ bool ChatHandler::HandleSendMoneyCommand(char* args)
if (money <= 0)
return false;
// msgSubject, msgText isn't NUL after prev. check
draft.SetSubjectAndBody(msgSubject, msgText).SetMoney(money);
return true;
}
bool ChatHandler::HandleSendMoneyCommand(char* args)
{
/// format: name "subject text" "mail text" money
Player* receiver;
ObjectGuid receiver_guid;
std::string receiver_name;
if (!ExtractPlayerTarget(&args, &receiver, &receiver_guid, &receiver_name))
return false;
MailDraft draft;
// fill mail
if (!HandleSendMoneyHelper(draft, args))
return false;
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
MailDraft(msgSubject, msgText)
.SetMoney(money)
.SendMailTo(MailReceiver(receiver, receiver_guid),sender);
draft.SendMailTo(MailReceiver(receiver, receiver_guid),sender);
std::string nameLink = playerLink(receiver_name);
PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str());
return true;
}
bool ChatHandler::HandleSendMassMoneyCommand(char* args)
{
/// format: raceMask "subject text" "mail text" money
uint32 raceMask = 0;
char const* name = NULL;
if (!ExtractRaceMask(&args, raceMask, &name))
return false;
// need dynamic object because it trasfered to mass mailer
MailDraft* draft = new MailDraft;
// fill mail
if (!HandleSendMoneyHelper(*draft, args))
{
delete draft;
return false;
}
// from console show nonexistent sender
MailSender sender(MAIL_NORMAL, m_session ? m_session->GetPlayer()->GetObjectGuid().GetCounter() : 0, MAIL_STATIONERY_GM);
sMassMailMgr.AddMassMailTask(draft, sender, raceMask);
PSendSysMessage(LANG_MAIL_SENT, name);
return true;
}
/// Send a message to a player in game
bool ChatHandler::HandleSendMessageCommand(char* args)
{

View file

@ -64,7 +64,16 @@ enum Races
((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \
(1<<(RACE_NIGHTELF-1)) |(1<<(RACE_UNDEAD-1)) |(1<<(RACE_TAUREN-1)) | \
(1<<(RACE_GNOME-1)) |(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1))| \
(1<<(RACE_DRAENEI-1)) )
(1<<(RACE_DRAENEI-1)))
// for most cases batter use ChrRace data for team check as more safe, but when need full mask of team can be use this defines.
#define RACEMASK_ALLIANCE \
((1<<(RACE_HUMAN-1)) |(1<<(RACE_DWARF-1)) |(1<<(RACE_NIGHTELF-1))| \
(1<<(RACE_GNOME-1)) |(1<<(RACE_DRAENEI-1)))
#define RACEMASK_HORDE \
((1<<(RACE_ORC-1)) |(1<<(RACE_UNDEAD-1)) |(1<<(RACE_TAUREN-1)) | \
(1<<(RACE_TROLL-1)) |(1<<(RACE_BLOODELF-1)))
// Class value is index in ChrClasses.dbc
enum Classes

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10971"
#define REVISION_NR "10972"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10862_01_characters_mail"
#define REVISION_DB_MANGOS "required_10951_01_mangos_spell_proc_event"
#define REVISION_DB_MANGOS "required_10972_01_mangos_command"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__