· 8 years ago · Jun 02, 2018, 12:04 AM
1diff --git a/sql/updates/10205_a_mangos_mail_template.sql b/sql/updates/10205_a_mangos_mail_template.sql
2new file mode 100644
3index 0000000..06f302e
4--- /dev/null
5+++ b/sql/updates/10205_a_mangos_mail_template.sql
6@@ -0,0 +1,16 @@
7+CREATE TABLE IF NOT EXISTS `mail_template` (
8+ `id` mediumint(8) NOT NULL,
9+ `title` text character set utf8 NOT NULL,
10+ `text` text character set utf8 NOT NULL,
11+ `item1` mediumint(8) NOT NULL default '0',
12+ `item1_count` mediumint(8) NOT NULL default '0',
13+ `item2` mediumint(8) NOT NULL default '0',
14+ `item2_count` mediumint(8) NOT NULL default '0',
15+ `item3` mediumint(8) NOT NULL default '0',
16+ `item3_count` mediumint(8) NOT NULL default '0',
17+ `item4` mediumint(8) NOT NULL default '0',
18+ `item4_count` mediumint(8) NOT NULL default '0',
19+ `item5` mediumint(8) NOT NULL default '0',
20+ `item5_count` mediumint(8) NOT NULL default '0',
21+ PRIMARY KEY (`id`)
22+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
23\ No newline at end of file
24diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp
25index eb6ba1b..a52b257 100644
26--- a/src/game/BattleGround.cpp
27+++ b/src/game/BattleGround.cpp
28@@ -951,7 +951,7 @@ void BattleGround::SendRewardMarkByMail(Player *plr,uint32 mark, uint32 count)
29 std::string textFormat = plr->GetSession()->GetMangosString(LANG_BG_MARK_BY_MAIL);
30 char textBuf[300];
31 snprintf(textBuf, 300, textFormat.c_str(), GetName(), GetName());
32-
33+
34 MailDraft(subject, textBuf)
35 .AddItem(markItem)
36 .SendMailTo(plr, MailSender(MAIL_CREATURE, bmEntry));
37diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
38index 8dc9148..f736448 100644
39--- a/src/game/Chat.cpp
40+++ b/src/game/Chat.cpp
41@@ -464,6 +464,7 @@ ChatCommand * ChatHandler::getCommandTable()
42 { "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL },
43 { "mail_level_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMailLevelRewardCommand, "", NULL },
44 { "mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMailCommand, "", NULL },
45+ { "mail_template" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMailTemplateCommand, "", NULL },
46 { "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL },
47 { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL },
48 { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL },
49diff --git a/src/game/Chat.h b/src/game/Chat.h
50index b82899e..6574103 100644
51--- a/src/game/Chat.h
52+++ b/src/game/Chat.h
53@@ -377,6 +377,7 @@ class ChatHandler
54 bool HandleReloadLootTemplatesSkinningCommand(const char* args);
55 bool HandleReloadLootTemplatesSpellCommand(const char* args);
56 bool HandleReloadMailLevelRewardCommand(const char* args);
57+ bool HandleReloadMailTemplateCommand(const char* args);
58 bool HandleReloadMangosStringCommand(const char* args);
59 bool HandleReloadNpcGossipCommand(const char* args);
60 bool HandleReloadNpcTrainerCommand(const char* args);
61diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
62index d3bcbb8..5e74a12 100644
63--- a/src/game/Level3.cpp
64+++ b/src/game/Level3.cpp
65@@ -197,6 +197,7 @@ bool ChatHandler::HandleReloadAllLocalesCommand(const char* /*args*/)
66 HandleReloadLocalesGameobjectCommand("a");
67 HandleReloadLocalesGossipMenuOptionCommand("a");
68 HandleReloadLocalesItemCommand("a");
69+ HandleReloadMailTemplateCommand("a");
70 HandleReloadLocalesNpcTextCommand("a");
71 HandleReloadLocalesPageTextCommand("a");
72 HandleReloadLocalesPointsOfInterestCommand("a");
73@@ -851,6 +852,14 @@ bool ChatHandler::HandleReloadLocalesItemCommand(const char* /*arg*/)
74 return true;
75 }
76
77+bool ChatHandler::HandleReloadMailTemplateCommand(const char* /*args*/)
78+{
79+ sLog.outString(" Re-Loading Mail Template ...");
80+ sObjectMgr.LoadMailTemplate();
81+ SendGlobalSysMessage("DB table `mail_template` reloaded.");
82+ return true;
83+}
84+
85 bool ChatHandler::HandleReloadLocalesNpcTextCommand(const char* /*arg*/)
86 {
87 sLog.outString( "Re-Loading Locales NPC Text ... ");
88diff --git a/src/game/Map.cpp b/src/game/Map.cpp
89index decc5bc..12a5fc2 100644
90--- a/src/game/Map.cpp
91+++ b/src/game/Map.cpp
92@@ -25,6 +25,7 @@
93 #include "CellImpl.h"
94 #include "InstanceData.h"
95 #include "Map.h"
96+#include "Mail.h"
97 #include "GridNotifiersImpl.h"
98 #include "Transports.h"
99 #include "ObjectAccessor.h"
100@@ -2870,6 +2871,83 @@ void Map::ScriptsProcess()
101
102 break;
103 }
104+ case SCRIPT_COMMAND_SEND_MAIL:
105+ {
106+ if (!target && !source)
107+ {
108+ sLog.outError("SCRIPT_COMMAND_SEND_MAIL (script id %u) call for NULL object.", step.script->id);
109+ break;
110+ }
111+
112+ // only Player
113+ if ((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER))
114+ {
115+ sLog.outError("SCRIPT_COMMAND_SEND_MAIL (script id %u) call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", step.script->id, source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0);
116+ break;
117+ }
118+
119+ Player* pReceiver = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source;
120+ if(!pReceiver)
121+ break;
122+
123+ if(MailTemplate const *mail_template = sObjectMgr.GetMailTemplate(step.script->datalong))
124+ {
125+ MailDraft draft(mail_template->title, mail_template->text);
126+
127+ if(ItemPrototype const* item1 = ObjectMgr::GetItemPrototype(mail_template->item1))
128+ if (Item* cItem1 = Item::CreateItem(mail_template->item1,mail_template->item1_c,pReceiver))
129+ {
130+ cItem1->SaveToDB();
131+ draft.AddItem(cItem1);
132+ }
133+
134+ if(ItemPrototype const* item2 = ObjectMgr::GetItemPrototype(mail_template->item2))
135+ if (Item* cItem2 = Item::CreateItem(mail_template->item2,mail_template->item2_c,pReceiver))
136+ {
137+ cItem2->SaveToDB();
138+ draft.AddItem(cItem2);
139+ }
140+
141+ if(ItemPrototype const* item3 = ObjectMgr::GetItemPrototype(mail_template->item3))
142+ if (Item* cItem3 = Item::CreateItem(mail_template->item3,mail_template->item3_c,pReceiver))
143+ {
144+ cItem3->SaveToDB();
145+ draft.AddItem(cItem3);
146+ }
147+
148+ if(ItemPrototype const* item4 = ObjectMgr::GetItemPrototype(mail_template->item4))
149+ if (Item* cItem4 = Item::CreateItem(mail_template->item4,mail_template->item4_c,pReceiver))
150+ {
151+ cItem4->SaveToDB();
152+ draft.AddItem(cItem4);
153+ }
154+
155+ if(ItemPrototype const* item5 = ObjectMgr::GetItemPrototype(mail_template->item5))
156+ if (Item* cItem5 = Item::CreateItem(mail_template->item5,mail_template->item5_c,pReceiver))
157+ {
158+ cItem5->SaveToDB();
159+ draft.AddItem(cItem5);
160+ }
161+
162+ switch(step.script->datalong2)
163+ {
164+ case 3: // creature
165+ draft.SendMailTo(pReceiver, MailSender(MAIL_CREATURE, step.script->datalong3));
166+ break;
167+ case 4: // object
168+ draft.SendMailTo(pReceiver, MailSender(MAIL_GAMEOBJECT, step.script->datalong3));
169+ break;
170+ default:
171+ break;
172+ }
173+ }else{
174+ sLog.outError("SCRIPT_COMMAND_SEND_MAIL (script id %u) can't find mail_template (mail_id: %u) ", step.script->id, step.script->datalong);
175+ break;
176+ }
177+
178+ break;
179+ }
180+
181 default:
182 sLog.outError("Unknown SCRIPT_COMMAND_ %u called for script id %u.",step.script->command, step.script->id);
183 break;
184diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
185index facd70b..7583cb9 100644
186--- a/src/game/ObjectMgr.cpp
187+++ b/src/game/ObjectMgr.cpp
188@@ -4576,6 +4576,31 @@ void ObjectMgr::LoadScripts(ScriptMapMap& scripts, char const* tablename)
189 }
190 break;
191 }
192+ case SCRIPT_COMMAND_SEND_MAIL:
193+ {
194+ if (!sObjectMgr.GetMailTemplate(tmp.datalong))
195+ {
196+ sLog.outErrorDb("Table `%s` column datalong(mail_id) is not valid (mail_id: %u) for record id %u",
197+ tablename, tmp.datalong, tmp.id);
198+ continue;
199+ }
200+
201+ if( tmp.datalong2 != 3 && tmp.datalong2 != 4)
202+ {
203+ sLog.outErrorDb("Table '%s' Invalid value datalong2 in record id %u (only 3 or 4)",
204+ tablename, tmp.id);
205+ continue;
206+ }
207+
208+ if (!tmp.datalong3)
209+ {
210+ sLog.outErrorDb("Table '%s' empty value datalong3 in record id %u (only 3 or 4)",
211+ tablename, tmp.id);
212+ continue;
213+ }
214+
215+ break;
216+ }
217 }
218
219 if (scripts.find(tmp.id) == scripts.end())
220@@ -4955,6 +4980,56 @@ void ObjectMgr::LoadGossipText()
221 delete result;
222 }
223
224+void ObjectMgr::LoadMailTemplate()
225+{
226+ mMailTemplateMap.clear();
227+
228+ QueryResult *result = WorldDatabase.Query("SELECT id, title, text, item1, item1_count, item2, item2_count, item3, item3_count, item4, item4_count, item5, item5_count FROM mail_template");
229+
230+ if(!result)
231+ {
232+ barGoLink bar(1);
233+
234+ bar.step();
235+
236+ sLog.outString();
237+ sLog.outString(">> Loaded 0 Mail template. DB table 'mail_template' is empty.");
238+ return;
239+ }
240+
241+ barGoLink bar((int)result->GetRowCount());
242+
243+ do
244+ {
245+ Field *fields = result->Fetch();
246+ bar.step();
247+
248+ uint32 id = fields[0].GetUInt32();
249+
250+ MailTemplate& data = mMailTemplateMap[id];
251+
252+ data.title = fields[1].GetString();
253+ data.text = fields[2].GetString();
254+ data.item1 = fields[3].GetUInt32(); // item 1
255+ data.item1_c = fields[4].GetUInt32();
256+ data.item2 = fields[5].GetUInt32(); // item 2
257+ data.item2_c = fields[6].GetUInt32();
258+ data.item3 = fields[7].GetUInt32(); // item 3
259+ data.item3_c = fields[8].GetUInt32();
260+ data.item4 = fields[9].GetUInt32(); // item 4
261+ data.item4_c = fields[10].GetUInt32();
262+ data.item5 = fields[11].GetUInt32(); // item 5
263+ data.item5_c = fields[12].GetUInt32();
264+
265+
266+ }while(result->NextRow());
267+
268+ delete result;
269+
270+ sLog.outString();
271+ sLog.outString( ">> Loaded %lu Mail template", (unsigned long)mMailTemplateMap.size() );
272+}
273+
274 void ObjectMgr::LoadNpcTextLocales()
275 {
276 mNpcTextLocaleMap.clear(); // need for reload case
277diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
278index 78b79b9..e91027f 100644
279--- a/src/game/ObjectMgr.h
280+++ b/src/game/ObjectMgr.h
281@@ -237,6 +237,26 @@ struct MailLevelReward
282 typedef std::list<MailLevelReward> MailLevelRewardList;
283 typedef UNORDERED_MAP<uint8,MailLevelRewardList> MailLevelRewardMap;
284
285+struct MailTemplate
286+{
287+ std::string title;
288+ std::string text;
289+
290+ uint32 item1; // item 1
291+ uint32 item1_c;
292+ uint32 item2; // item 2
293+ uint32 item2_c;
294+ uint32 item3; // item 3
295+ uint32 item3_c;
296+ uint32 item4; // item 4
297+ uint32 item4_c;
298+ uint32 item5; // item 5
299+ uint32 item5_c;
300+};
301+
302+typedef UNORDERED_MAP<uint8, MailTemplate> MailTemplateMap;
303+
304+
305 struct ReputationOnKillEntry
306 {
307 uint32 repfaction1;
308@@ -660,6 +680,7 @@ class ObjectMgr
309 void LoadItemRequiredTarget();
310 void LoadItemLocales();
311 void LoadQuestLocales();
312+ void LoadMailTemplate();
313 void LoadNpcTextLocales();
314 void LoadPageTextLocales();
315 void LoadGossipMenuItemsLocales();
316@@ -742,6 +763,15 @@ class ObjectMgr
317 return NULL;
318 }
319
320+ MailTemplate const* GetMailTemplate(uint32 id) const
321+ {
322+ MailTemplateMap::const_iterator map_itr = mMailTemplateMap.find(id);
323+ if(map_itr != mMailTemplateMap.end())
324+ return &map_itr->second;
325+
326+ return NULL;
327+ }
328+
329 WeatherZoneChances const* GetWeatherChances(uint32 zone_id) const
330 {
331 WeatherZoneMap::const_iterator itr = mWeatherZoneMap.find(zone_id);
332@@ -1073,6 +1103,7 @@ class ObjectMgr
333 GameObjectLocaleMap mGameObjectLocaleMap;
334 ItemLocaleMap mItemLocaleMap;
335 QuestLocaleMap mQuestLocaleMap;
336+ MailTemplateMap mMailTemplateMap;
337 NpcTextLocaleMap mNpcTextLocaleMap;
338 PageTextLocaleMap mPageTextLocaleMap;
339 MangosStringLocaleMap mMangosStringLocaleMap;
340diff --git a/src/game/World.cpp b/src/game/World.cpp
341index 5c87bcc..e9352fc 100644
342--- a/src/game/World.cpp
343+++ b/src/game/World.cpp
344@@ -947,6 +947,7 @@ void World::SetInitialWorldSettings()
345 sObjectMgr.LoadGameObjectLocales();
346 sObjectMgr.LoadItemLocales();
347 sObjectMgr.LoadQuestLocales();
348+ sObjectMgr.LoadMailTemplate();
349 sObjectMgr.LoadNpcTextLocales();
350 sObjectMgr.LoadPageTextLocales();
351 sObjectMgr.LoadGossipMenuItemsLocales();
352diff --git a/src/game/World.h b/src/game/World.h
353index f7826cb..1a8c36a 100644
354--- a/src/game/World.h
355+++ b/src/game/World.h
356@@ -415,6 +415,7 @@ enum RealmZone
357 #define SCRIPT_COMMAND_CREATE_ITEM 17 // source or target must be player, datalong = item entry, datalong2 = amount
358 #define SCRIPT_COMMAND_DESPAWN_SELF 18 // source or target must be creature, datalong = despawn delay
359 #define SCRIPT_COMMAND_PLAY_MOVIE 19 // target can only be a player, datalog = movie id
360+#define SCRIPT_COMMAND_SEND_MAIL 20 //
361
362 /// Storage class for commands issued for delayed execution
363 struct CliCommandHolder