[10041] Use for spell 49145 and ranks for decrease SPELL_DIRECT_DAMAGE damage.
[getmangos.git] / src / game / Chat.cpp
blob97506963b26d5c37312f4b98b2365242ba31138c
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Language.h"
21 #include "Database/DatabaseEnv.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "Opcodes.h"
25 #include "Log.h"
26 #include "World.h"
27 #include "ObjectMgr.h"
28 #include "ObjectGuid.h"
29 #include "Player.h"
30 #include "UpdateMask.h"
31 #include "Chat.h"
32 #include "GridNotifiersImpl.h"
33 #include "CellImpl.h"
34 #include "AccountMgr.h"
35 #include "SpellMgr.h"
37 // Supported shift-links (client generated and server side)
38 // |color|Hachievement:achievement_id:player_guid:0:0:0:0:0:0:0:0|h[name]|h|r
39 // - client, item icon shift click, not used in server currently
40 // |color|Harea:area_id|h[name]|h|r
41 // |color|Hcreature:creature_guid|h[name]|h|r
42 // |color|Hcreature_entry:creature_id|h[name]|h|r
43 // |color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r - client, at shift click in recipes list dialog
44 // |color|Hgameevent:id|h[name]|h|r
45 // |color|Hgameobject:go_guid|h[name]|h|r
46 // |color|Hgameobject_entry:go_id|h[name]|h|r
47 // |color|Hglyph:glyph_slot_id:glyph_prop_id|h[%s]|h|r - client, at shift click in glyphs dialog, GlyphSlot.dbc, GlyphProperties.dbc
48 // |color|Hitem:item_id:perm_ench_id:gem1:gem2:gem3:0:0:0:0:reporter_level|h[name]|h|r
49 // - client, item icon shift click
50 // |color|Hitemset:itemset_id|h[name]|h|r
51 // |color|Hplayer:name|h[name]|h|r - client, in some messages, at click copy only name instead link
52 // |color|Hquest:quest_id:quest_level|h[name]|h|r - client, quest list name shift-click
53 // |color|Hskill:skill_id|h[name]|h|r
54 // |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click
55 // |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click
56 // |color|Htaxinode:id|h[name]|h|r
57 // |color|Htele:id|h[name]|h|r
58 // |color|Htitle:id|h[name]|h|r
59 // |color|Htrade:spell_id,cur_value,max_value,unk3int,unk3str|h[name]|h|r - client, spellbook profession icon shift-click
61 bool ChatHandler::load_command_table = true;
63 ChatCommand * ChatHandler::getCommandTable()
65 static ChatCommand accountSetCommandTable[] =
67 { "addon", SEC_ADMINISTRATOR, true, &ChatHandler::HandleAccountSetAddonCommand, "", NULL },
68 { "gmlevel", SEC_CONSOLE, true, &ChatHandler::HandleAccountSetGmLevelCommand, "", NULL },
69 { "password", SEC_CONSOLE, true, &ChatHandler::HandleAccountSetPasswordCommand, "", NULL },
70 { NULL, 0, false, NULL, "", NULL }
73 static ChatCommand accountCommandTable[] =
75 { "characters", SEC_CONSOLE, true, &ChatHandler::HandleAccountCharactersCommand, "", NULL },
76 { "create", SEC_CONSOLE, true, &ChatHandler::HandleAccountCreateCommand, "", NULL },
77 { "delete", SEC_CONSOLE, true, &ChatHandler::HandleAccountDeleteCommand, "", NULL },
78 { "onlinelist", SEC_CONSOLE, true, &ChatHandler::HandleAccountOnlineListCommand, "", NULL },
79 { "lock", SEC_PLAYER, true, &ChatHandler::HandleAccountLockCommand, "", NULL },
80 { "set", SEC_ADMINISTRATOR, true, NULL, "", accountSetCommandTable },
81 { "password", SEC_PLAYER, true, &ChatHandler::HandleAccountPasswordCommand, "", NULL },
82 { "", SEC_PLAYER, true, &ChatHandler::HandleAccountCommand, "", NULL },
83 { NULL, 0, false, NULL, "", NULL }
86 static ChatCommand banCommandTable[] =
88 { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountCommand, "", NULL },
89 { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanCharacterCommand, "", NULL },
90 { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanIPCommand, "", NULL },
91 { NULL, 0, false, NULL, "", NULL }
94 static ChatCommand baninfoCommandTable[] =
96 { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanInfoAccountCommand, "", NULL },
97 { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanInfoCharacterCommand, "", NULL },
98 { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanInfoIPCommand, "", NULL },
99 { NULL, 0, false, NULL, "", NULL }
102 static ChatCommand banlistCommandTable[] =
104 { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanListAccountCommand, "", NULL },
105 { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanListCharacterCommand, "", NULL },
106 { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanListIPCommand, "", NULL },
107 { NULL, 0, false, NULL, "", NULL }
110 static ChatCommand castCommandTable[] =
112 { "back", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastBackCommand, "", NULL },
113 { "dist", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastDistCommand, "", NULL },
114 { "self", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastSelfCommand, "", NULL },
115 { "target", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastTargetCommand, "", NULL },
116 { "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCastCommand, "", NULL },
117 { NULL, 0, false, NULL, "", NULL }
120 static ChatCommand characterDeletedCommandTable[] =
122 { "delete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeletedDeleteCommand, "", NULL },
123 { "list", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterDeletedListCommand,"", NULL },
124 { "restore", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterDeletedRestoreCommand,"", NULL },
125 { "old", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeletedOldCommand, "", NULL },
126 { NULL, 0, false, NULL, "", NULL }
129 static ChatCommand characterCommandTable[] =
131 { "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterCustomizeCommand, "", NULL },
132 { "deleted", SEC_GAMEMASTER, true, NULL, "", characterDeletedCommandTable},
133 { "erase", SEC_CONSOLE, true, &ChatHandler::HandleCharacterEraseCommand, "", NULL },
134 { "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterLevelCommand, "", NULL },
135 { "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterRenameCommand, "", NULL },
136 { "reputation", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterReputationCommand, "", NULL },
137 { "titles", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterTitlesCommand, "", NULL },
138 { NULL, 0, false, NULL, "", NULL }
141 static ChatCommand debugPlayCommandTable[] =
143 { "cinematic", SEC_MODERATOR, false, &ChatHandler::HandleDebugPlayCinematicCommand, "", NULL },
144 { "movie", SEC_MODERATOR, false, &ChatHandler::HandleDebugPlayMovieCommand, "", NULL },
145 { "sound", SEC_MODERATOR, false, &ChatHandler::HandleDebugPlaySoundCommand, "", NULL },
146 { NULL, 0, false, NULL, "", NULL }
149 static ChatCommand debugSendCommandTable[] =
151 { "buyerror", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendBuyErrorCommand, "", NULL },
152 { "channelnotify", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendChannelNotifyCommand, "", NULL },
153 { "chatmmessage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendChatMsgCommand, "", NULL },
154 { "equiperror", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendEquipErrorCommand, "", NULL },
155 { "largepacket", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendLargePacketCommand, "", NULL },
156 { "opcode", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendOpcodeCommand, "", NULL },
157 { "poi", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendPoiCommand, "", NULL },
158 { "qpartymsg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendQuestPartyMsgCommand, "", NULL },
159 { "qinvalidmsg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendQuestInvalidMsgCommand, "", NULL },
160 { "sellerror", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendSellErrorCommand, "", NULL },
161 { "setphaseshift", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendSetPhaseShiftCommand, "", NULL },
162 { "spellfail", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSendSpellFailCommand, "", NULL },
163 { NULL, 0, false, NULL, "", NULL }
166 static ChatCommand debugCommandTable[] =
168 { "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugAnimCommand, "", NULL },
169 { "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
170 { "bg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugBattlegroundCommand, "", NULL },
171 { "getitemstate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemStateCommand, "", NULL },
172 { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleDebugGetLootRecipientCommand, "", NULL },
173 { "getvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetValueCommand, "", NULL },
174 { "getitemvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugGetItemValueCommand, "", NULL },
175 { "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugMod32ValueCommand, "", NULL },
176 { "play", SEC_MODERATOR, false, NULL, "", debugPlayCommandTable },
177 { "send", SEC_ADMINISTRATOR, false, NULL, "", debugSendCommandTable },
178 { "setaurastate", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetAuraStateCommand, "", NULL },
179 { "setitemvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetItemValueCommand, "", NULL },
180 { "setvalue", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSetValueCommand, "", NULL },
181 { "spellcheck", SEC_CONSOLE, true, &ChatHandler::HandleDebugSpellCheckCommand, "", NULL },
182 { "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugSpawnVehicle, "", NULL },
183 { "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdateWorldStateCommand, "", NULL },
184 { "update", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugUpdateCommand, "", NULL },
185 { NULL, 0, false, NULL, "", NULL }
188 static ChatCommand eventCommandTable[] =
190 { "list", SEC_GAMEMASTER, true, &ChatHandler::HandleEventListCommand, "", NULL },
191 { "start", SEC_GAMEMASTER, true, &ChatHandler::HandleEventStartCommand, "", NULL },
192 { "stop", SEC_GAMEMASTER, true, &ChatHandler::HandleEventStopCommand, "", NULL },
193 { "", SEC_GAMEMASTER, true, &ChatHandler::HandleEventInfoCommand, "", NULL },
194 { NULL, 0, false, NULL, "", NULL }
197 static ChatCommand gmCommandTable[] =
199 { "chat", SEC_MODERATOR, false, &ChatHandler::HandleGMChatCommand, "", NULL },
200 { "fly", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGMFlyCommand, "", NULL },
201 { "ingame", SEC_PLAYER, true, &ChatHandler::HandleGMListIngameCommand, "", NULL },
202 { "list", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMListFullCommand, "", NULL },
203 { "visible", SEC_MODERATOR, false, &ChatHandler::HandleGMVisibleCommand, "", NULL },
204 { "", SEC_MODERATOR, false, &ChatHandler::HandleGMCommand, "", NULL },
205 { NULL, 0, false, NULL, "", NULL }
208 static ChatCommand goCommandTable[] =
210 { "creature", SEC_MODERATOR, false, &ChatHandler::HandleGoCreatureCommand, "", NULL },
211 { "graveyard", SEC_MODERATOR, false, &ChatHandler::HandleGoGraveyardCommand, "", NULL },
212 { "grid", SEC_MODERATOR, false, &ChatHandler::HandleGoGridCommand, "", NULL },
213 { "object", SEC_MODERATOR, false, &ChatHandler::HandleGoObjectCommand, "", NULL },
214 { "taxinode", SEC_MODERATOR, false, &ChatHandler::HandleGoTaxinodeCommand, "", NULL },
215 { "trigger", SEC_MODERATOR, false, &ChatHandler::HandleGoTriggerCommand, "", NULL },
216 { "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL },
217 { "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL },
218 { "xyz", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL },
219 { "", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL },
220 { NULL, 0, false, NULL, "", NULL }
223 static ChatCommand gobjectCommandTable[] =
225 { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectAddCommand, "", NULL },
226 { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectDeleteCommand, "", NULL },
227 { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectMoveCommand, "", NULL },
228 { "near", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectNearCommand, "", NULL },
229 { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectPhaseCommand, "", NULL },
230 { "target", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectTargetCommand, "", NULL },
231 { "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectTurnCommand, "", NULL },
232 { NULL, 0, false, NULL, "", NULL }
235 static ChatCommand guildCommandTable[] =
237 { "create", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildCreateCommand, "", NULL },
238 { "delete", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildDeleteCommand, "", NULL },
239 { "invite", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildInviteCommand, "", NULL },
240 { "uninvite", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildUninviteCommand, "", NULL },
241 { "rank", SEC_GAMEMASTER, true, &ChatHandler::HandleGuildRankCommand, "", NULL },
242 { NULL, 0, false, NULL, "", NULL }
245 static ChatCommand honorCommandTable[] =
247 { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorAddCommand, "", NULL },
248 { "addkill", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorAddKillCommand, "", NULL },
249 { "update", SEC_GAMEMASTER, false, &ChatHandler::HandleHonorUpdateCommand, "", NULL },
250 { NULL, 0, false, NULL, "", NULL }
253 static ChatCommand instanceCommandTable[] =
255 { "listbinds", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceListBindsCommand, "", NULL },
256 { "unbind", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceUnbindCommand, "", NULL },
257 { "stats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleInstanceStatsCommand, "", NULL },
258 { "savedata", SEC_ADMINISTRATOR, false, &ChatHandler::HandleInstanceSaveDataCommand, "", NULL },
259 { NULL, 0, false, NULL, "", NULL }
262 static ChatCommand learnCommandTable[] =
264 { "all", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllCommand, "", NULL },
265 { "all_gm", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllGMCommand, "", NULL },
266 { "all_crafts", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllCraftsCommand, "", NULL },
267 { "all_default", SEC_MODERATOR, false, &ChatHandler::HandleLearnAllDefaultCommand, "", NULL },
268 { "all_lang", SEC_MODERATOR, false, &ChatHandler::HandleLearnAllLangCommand, "", NULL },
269 { "all_myclass", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyClassCommand, "", NULL },
270 { "all_mypettalents",SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyPetTalentsCommand,"", NULL },
271 { "all_myspells", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMySpellsCommand, "", NULL },
272 { "all_mytalents", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnAllMyTalentsCommand, "", NULL },
273 { "all_recipes", SEC_GAMEMASTER, false, &ChatHandler::HandleLearnAllRecipesCommand, "", NULL },
274 { "", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLearnCommand, "", NULL },
275 { NULL, 0, false, NULL, "", NULL }
278 static ChatCommand listCommandTable[] =
280 { "auras", SEC_ADMINISTRATOR, false, &ChatHandler::HandleListAurasCommand, "", NULL },
281 { "creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleListCreatureCommand, "", NULL },
282 { "item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleListItemCommand, "", NULL },
283 { "object", SEC_ADMINISTRATOR, true, &ChatHandler::HandleListObjectCommand, "", NULL },
284 { "talents", SEC_ADMINISTRATOR, false, &ChatHandler::HandleListTalentsCommand, "", NULL },
285 { NULL, 0, false, NULL, "", NULL }
288 static ChatCommand lookupAccountCommandTable[] =
290 { "email", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupAccountEmailCommand, "", NULL },
291 { "ip", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupAccountIpCommand, "", NULL },
292 { "name", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupAccountNameCommand, "", NULL },
293 { NULL, 0, false, NULL, "", NULL }
296 static ChatCommand lookupPlayerCommandTable[] =
298 { "account", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupPlayerAccountCommand, "", NULL },
299 { "email", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupPlayerEmailCommand, "", NULL },
300 { "ip", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupPlayerIpCommand, "", NULL },
301 { NULL, 0, false, NULL, "", NULL }
304 static ChatCommand lookupCommandTable[] =
306 { "account", SEC_GAMEMASTER, true, NULL, "", lookupAccountCommandTable },
307 { "area", SEC_MODERATOR, true, &ChatHandler::HandleLookupAreaCommand, "", NULL },
308 { "creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupCreatureCommand, "", NULL },
309 { "event", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupEventCommand, "", NULL },
310 { "faction", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupFactionCommand, "", NULL },
311 { "item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupItemCommand, "", NULL },
312 { "itemset", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupItemSetCommand, "", NULL },
313 { "object", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupObjectCommand, "", NULL },
314 { "quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupQuestCommand, "", NULL },
315 { "player", SEC_GAMEMASTER, true, NULL, "", lookupPlayerCommandTable },
316 { "skill", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSkillCommand, "", NULL },
317 { "spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupSpellCommand, "", NULL },
318 { "taxinode", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLookupTaxiNodeCommand, "", NULL },
319 { "tele", SEC_MODERATOR, true, &ChatHandler::HandleLookupTeleCommand, "", NULL },
320 { "title", SEC_GAMEMASTER, true, &ChatHandler::HandleLookupTitleCommand, "", NULL },
321 { NULL, 0, false, NULL, "", NULL }
324 static ChatCommand modifyCommandTable[] =
326 { "hp", SEC_MODERATOR, false, &ChatHandler::HandleModifyHPCommand, "", NULL },
327 { "mana", SEC_MODERATOR, false, &ChatHandler::HandleModifyManaCommand, "", NULL },
328 { "rage", SEC_MODERATOR, false, &ChatHandler::HandleModifyRageCommand, "", NULL },
329 { "runicpower", SEC_MODERATOR, false, &ChatHandler::HandleModifyRunicPowerCommand, "", NULL },
330 { "energy", SEC_MODERATOR, false, &ChatHandler::HandleModifyEnergyCommand, "", NULL },
331 { "money", SEC_MODERATOR, false, &ChatHandler::HandleModifyMoneyCommand, "", NULL },
332 { "speed", SEC_MODERATOR, false, &ChatHandler::HandleModifySpeedCommand, "", NULL },
333 { "swim", SEC_MODERATOR, false, &ChatHandler::HandleModifySwimCommand, "", NULL },
334 { "scale", SEC_MODERATOR, false, &ChatHandler::HandleModifyScaleCommand, "", NULL },
335 { "bit", SEC_MODERATOR, false, &ChatHandler::HandleModifyBitCommand, "", NULL },
336 { "bwalk", SEC_MODERATOR, false, &ChatHandler::HandleModifyBWalkCommand, "", NULL },
337 { "fly", SEC_MODERATOR, false, &ChatHandler::HandleModifyFlyCommand, "", NULL },
338 { "aspeed", SEC_MODERATOR, false, &ChatHandler::HandleModifyASpeedCommand, "", NULL },
339 { "faction", SEC_MODERATOR, false, &ChatHandler::HandleModifyFactionCommand, "", NULL },
340 { "spell", SEC_MODERATOR, false, &ChatHandler::HandleModifySpellCommand, "", NULL },
341 { "tp", SEC_MODERATOR, false, &ChatHandler::HandleModifyTalentCommand, "", NULL },
342 { "mount", SEC_MODERATOR, false, &ChatHandler::HandleModifyMountCommand, "", NULL },
343 { "honor", SEC_MODERATOR, false, &ChatHandler::HandleModifyHonorCommand, "", NULL },
344 { "rep", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyRepCommand, "", NULL },
345 { "arena", SEC_MODERATOR, false, &ChatHandler::HandleModifyArenaCommand, "", NULL },
346 { "drunk", SEC_MODERATOR, false, &ChatHandler::HandleModifyDrunkCommand, "", NULL },
347 { "standstate", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyStandStateCommand, "", NULL },
348 { "morph", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyMorphCommand, "", NULL },
349 { "phase", SEC_ADMINISTRATOR, false, &ChatHandler::HandleModifyPhaseCommand, "", NULL },
350 { "gender", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyGenderCommand, "", NULL },
351 { NULL, 0, false, NULL, "", NULL }
354 static ChatCommand npcCommandTable[] =
356 { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddCommand, "", NULL },
357 { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorItemCommand, "", NULL },
358 { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL },
359 { "allowmove", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAllowMovementCommand, "", NULL },
360 { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL },
361 { "changelevel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcChangeLevelCommand, "", NULL },
362 { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDeleteCommand, "", NULL },
363 { "delitem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcDelVendorItemCommand, "", NULL },
364 { "factionid", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFactionIdCommand, "", NULL },
365 { "flag", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFlagCommand, "", NULL },
366 { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL },
367 { "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL },
368 { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcMoveCommand, "", NULL },
369 { "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL },
370 { "setmodel", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetModelCommand, "", NULL },
371 { "setmovetype", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetMoveTypeCommand, "", NULL },
372 { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL },
373 { "spawndist", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnDistCommand, "", NULL },
374 { "spawntime", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSpawnTimeCommand, "", NULL },
375 { "say", SEC_MODERATOR, false, &ChatHandler::HandleNpcSayCommand, "", NULL },
376 { "textemote", SEC_MODERATOR, false, &ChatHandler::HandleNpcTextEmoteCommand, "", NULL },
377 { "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL },
378 { "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL },
379 { "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL },
380 { "tame", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcTameCommand, "", NULL },
381 { "setdeathstate", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetDeathStateCommand, "", NULL },
383 //{ TODO: fix or remove this commands
384 { "addweapon", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAddWeaponCommand, "", NULL },
385 { "name", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcNameCommand, "", NULL },
386 { "subname", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSubNameCommand, "", NULL },
389 { NULL, 0, false, NULL, "", NULL }
392 static ChatCommand pdumpCommandTable[] =
394 { "load", SEC_ADMINISTRATOR, true, &ChatHandler::HandlePDumpLoadCommand, "", NULL },
395 { "write", SEC_ADMINISTRATOR, true, &ChatHandler::HandlePDumpWriteCommand, "", NULL },
396 { NULL, 0, false, NULL, "", NULL }
399 static ChatCommand questCommandTable[] =
401 { "add", SEC_ADMINISTRATOR, false, &ChatHandler::HandleQuestAdd, "", NULL },
402 { "complete", SEC_ADMINISTRATOR, false, &ChatHandler::HandleQuestComplete, "", NULL },
403 { "remove", SEC_ADMINISTRATOR, false, &ChatHandler::HandleQuestRemove, "", NULL },
404 { NULL, 0, false, NULL, "", NULL }
407 static ChatCommand reloadCommandTable[] =
409 { "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllCommand, "", NULL },
410 { "all_achievement",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAchievementCommand,"", NULL },
411 { "all_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllAreaCommand, "", NULL },
412 { "all_eventai", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllEventAICommand, "", NULL },
413 { "all_gossips", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllGossipsCommand, "", NULL },
414 { "all_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllItemCommand, "", NULL },
415 { "all_locales", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLocalesCommand, "", NULL },
416 { "all_loot", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllLootCommand, "", NULL },
417 { "all_npc", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllNpcCommand, "", NULL },
418 { "all_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllQuestCommand, "", NULL },
419 { "all_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllScriptsCommand, "", NULL },
420 { "all_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAllSpellCommand, "", NULL },
422 { "config", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConfigCommand, "", NULL },
424 { "achievement_criteria_requirement",SEC_ADMINISTRATOR,true,&ChatHandler::HandleReloadAchievementCriteriaRequirementCommand,"",NULL },
425 { "achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAchievementRewardCommand, "", NULL },
426 { "areatrigger_involvedrelation",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", NULL },
427 { "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", NULL },
428 { "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL },
429 { "command", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommandCommand, "", NULL },
430 { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL },
431 { "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL },
432 { "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL },
433 { "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
434 { "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand,"",NULL },
435 { "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL },
436 { "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL },
437 { "db_script_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDbScriptStringCommand, "", NULL },
438 { "disenchant_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesDisenchantCommand, "", NULL },
439 { "event_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventScriptsCommand, "", NULL },
440 { "fishing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesFishingCommand, "", NULL },
441 { "game_graveyard_zone", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameGraveyardZoneCommand, "", NULL },
442 { "game_tele", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameTeleCommand, "", NULL },
443 { "gameobject_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestInvRelationsCommand, "", NULL },
444 { "gameobject_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesGameobjectCommand, "", NULL },
445 { "gameobject_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGOQuestRelationsCommand, "", NULL },
446 { "gameobject_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGameObjectScriptsCommand, "", NULL },
447 { "gameobject_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL },
448 { "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
449 { "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL },
450 { "gossip_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipScriptsCommand, "", NULL },
451 { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
452 { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
453 { "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL },
454 { "locales_achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesAchievementRewardCommand,"", NULL },
455 { "locales_creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesCreatureCommand, "", NULL },
456 { "locales_gameobject", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGameobjectCommand, "", NULL },
457 { "locales_gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGossipMenuOptionCommand, "", NULL },
458 { "locales_item", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesItemCommand, "", NULL },
459 { "locales_npc_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesNpcTextCommand, "", NULL },
460 { "locales_page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPageTextCommand, "", NULL },
461 { "locales_points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPointsOfInterestCommand, "", NULL },
462 { "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL },
463 { "mail_level_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMailLevelRewardCommand, "", NULL },
464 { "mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMailCommand, "", NULL },
465 { "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL },
466 { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL },
467 { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL },
468 { "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL},
469 { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL },
470 { "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL },
471 { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL },
472 { "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL},
473 { "points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPointsOfInterestCommand, "",NULL},
474 { "prospecting_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesProspectingCommand,"", NULL },
475 { "quest_end_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestEndScriptsCommand, "", NULL },
476 { "quest_poi", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestPOICommand, "", NULL },
477 { "quest_start_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestStartScriptsCommand, "", NULL },
478 { "quest_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestTemplateCommand, "", NULL },
479 { "reference_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesReferenceCommand, "", NULL },
480 { "reserved_name", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadReservedNameCommand, "", NULL },
481 { "skill_discovery_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillDiscoveryTemplateCommand, "", NULL },
482 { "skill_extra_item_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillExtraItemTemplateCommand, "", NULL },
483 { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL },
484 { "skinning_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSkinningCommand, "", NULL },
485 { "spell_area", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellAreaCommand, "", NULL },
486 { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL },
487 { "spell_chain", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellChainCommand, "", NULL },
488 { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL },
489 { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL },
490 { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL },
491 { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL },
492 { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL },
493 { "spell_proc_item_enchant", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcItemEnchantCommand, "", NULL },
494 { "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL },
495 { "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL },
496 { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL },
497 { "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL },
499 { NULL, 0, false, NULL, "", NULL }
502 static ChatCommand resetCommandTable[] =
504 { "achievements", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetAchievementsCommand, "", NULL },
505 { "honor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetHonorCommand, "", NULL },
506 { "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetLevelCommand, "", NULL },
507 { "specs", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetSpecsCommand, "", NULL },
508 { "spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetSpellsCommand, "", NULL },
509 { "stats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetStatsCommand, "", NULL },
510 { "talents", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetTalentsCommand, "", NULL },
511 { "all", SEC_ADMINISTRATOR, true, &ChatHandler::HandleResetAllCommand, "", NULL },
512 { NULL, 0, false, NULL, "", NULL }
515 static ChatCommand sendCommandTable[] =
517 { "items", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendItemsCommand, "", NULL },
518 { "mail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL },
519 { "message", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL },
520 { "money", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMoneyCommand, "", NULL },
521 { NULL, 0, false, NULL, "", NULL }
524 static ChatCommand serverIdleRestartCommandTable[] =
526 { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
527 { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleRestartCommand, "", NULL },
528 { NULL, 0, false, NULL, "", NULL }
531 static ChatCommand serverIdleShutdownCommandTable[] =
533 { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
534 { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerIdleShutDownCommand, "", NULL },
535 { NULL, 0, false, NULL, "", NULL }
538 static ChatCommand serverRestartCommandTable[] =
540 { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
541 { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerRestartCommand, "", NULL },
542 { NULL, 0, false, NULL, "", NULL }
545 static ChatCommand serverShutdownCommandTable[] =
547 { "cancel", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCancelCommand,"", NULL },
548 { "" , SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerShutDownCommand, "", NULL },
549 { NULL, 0, false, NULL, "", NULL }
552 static ChatCommand serverLogCommandTable[] =
554 { "filter", SEC_CONSOLE, true, &ChatHandler::HandleServerLogFilterCommand, "", NULL },
555 { "level", SEC_CONSOLE, true, &ChatHandler::HandleServerLogLevelCommand, "", NULL },
556 { NULL, 0, false, NULL, "", NULL }
559 static ChatCommand serverSetCommandTable[] =
561 { "motd", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerSetMotdCommand, "", NULL },
562 { NULL, 0, false, NULL, "", NULL }
565 static ChatCommand serverCommandTable[] =
567 { "corpses", SEC_GAMEMASTER, true, &ChatHandler::HandleServerCorpsesCommand, "", NULL },
568 { "exit", SEC_CONSOLE, true, &ChatHandler::HandleServerExitCommand, "", NULL },
569 { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable },
570 { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable },
571 { "info", SEC_PLAYER, true, &ChatHandler::HandleServerInfoCommand, "", NULL },
572 { "log", SEC_CONSOLE, true, NULL, "", serverLogCommandTable },
573 { "motd", SEC_PLAYER, true, &ChatHandler::HandleServerMotdCommand, "", NULL },
574 { "plimit", SEC_ADMINISTRATOR, true, &ChatHandler::HandleServerPLimitCommand, "", NULL },
575 { "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable },
576 { "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable },
577 { "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable },
578 { NULL, 0, false, NULL, "", NULL }
581 static ChatCommand teleCommandTable[] =
583 { "add", SEC_ADMINISTRATOR, false, &ChatHandler::HandleTeleAddCommand, "", NULL },
584 { "del", SEC_ADMINISTRATOR, true, &ChatHandler::HandleTeleDelCommand, "", NULL },
585 { "name", SEC_MODERATOR, true, &ChatHandler::HandleTeleNameCommand, "", NULL },
586 { "group", SEC_MODERATOR, false, &ChatHandler::HandleTeleGroupCommand, "", NULL },
587 { "", SEC_MODERATOR, false, &ChatHandler::HandleTeleCommand, "", NULL },
588 { NULL, 0, false, NULL, "", NULL }
591 static ChatCommand titlesCommandTable[] =
593 { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesAddCommand, "", NULL },
594 { "current", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesCurrentCommand, "", NULL },
595 { "remove", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesRemoveCommand, "", NULL },
596 { "setmask", SEC_GAMEMASTER, false, &ChatHandler::HandleTitlesSetMaskCommand, "", NULL },
597 { NULL, 0, false, NULL, "", NULL }
600 static ChatCommand unbanCommandTable[] =
602 { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanAccountCommand, "", NULL },
603 { "character", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanCharacterCommand, "", NULL },
604 { "ip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleUnBanIPCommand, "", NULL },
605 { NULL, 0, false, NULL, "", NULL }
608 static ChatCommand wpCommandTable[] =
610 { "show", SEC_GAMEMASTER, false, &ChatHandler::HandleWpShowCommand, "", NULL },
611 { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL },
612 { "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL },
613 { "export", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpExportCommand, "", NULL },
614 { "import", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpImportCommand, "", NULL },
615 { NULL, 0, false, NULL, "", NULL }
618 static ChatCommand commandTable[] =
620 { "account", SEC_PLAYER, true, NULL, "", accountCommandTable },
621 { "cast", SEC_ADMINISTRATOR, false, NULL, "", castCommandTable },
622 { "character", SEC_GAMEMASTER, true, NULL, "", characterCommandTable},
623 { "debug", SEC_MODERATOR, true, NULL, "", debugCommandTable },
624 { "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable },
625 { "gm", SEC_MODERATOR, true, NULL, "", gmCommandTable },
626 { "honor", SEC_GAMEMASTER, false, NULL, "", honorCommandTable },
627 { "go", SEC_MODERATOR, false, NULL, "", goCommandTable },
628 { "gobject", SEC_GAMEMASTER, false, NULL, "", gobjectCommandTable },
629 { "guild", SEC_ADMINISTRATOR, true, NULL, "", guildCommandTable },
630 { "instance", SEC_ADMINISTRATOR, true, NULL, "", instanceCommandTable },
631 { "learn", SEC_MODERATOR, false, NULL, "", learnCommandTable },
632 { "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable },
633 { "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable },
634 { "modify", SEC_MODERATOR, false, NULL, "", modifyCommandTable },
635 { "npc", SEC_MODERATOR, false, NULL, "", npcCommandTable },
636 { "pdump", SEC_ADMINISTRATOR, true, NULL, "", pdumpCommandTable },
637 { "quest", SEC_ADMINISTRATOR, false, NULL, "", questCommandTable },
638 { "reload", SEC_ADMINISTRATOR, true, NULL, "", reloadCommandTable },
639 { "reset", SEC_ADMINISTRATOR, true, NULL, "", resetCommandTable },
640 { "server", SEC_ADMINISTRATOR, true, NULL, "", serverCommandTable },
641 { "tele", SEC_MODERATOR, true, NULL, "", teleCommandTable },
642 { "titles", SEC_GAMEMASTER, false, NULL, "", titlesCommandTable },
643 { "wp", SEC_GAMEMASTER, false, NULL, "", wpCommandTable },
645 { "aura", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAuraCommand, "", NULL },
646 { "unaura", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnAuraCommand, "", NULL },
647 { "announce", SEC_MODERATOR, true, &ChatHandler::HandleAnnounceCommand, "", NULL },
648 { "notify", SEC_MODERATOR, true, &ChatHandler::HandleNotifyCommand, "", NULL },
649 { "goname", SEC_MODERATOR, false, &ChatHandler::HandleGonameCommand, "", NULL },
650 { "namego", SEC_MODERATOR, false, &ChatHandler::HandleNamegoCommand, "", NULL },
651 { "groupgo", SEC_MODERATOR, false, &ChatHandler::HandleGroupgoCommand, "", NULL },
652 { "commands", SEC_PLAYER, true, &ChatHandler::HandleCommandsCommand, "", NULL },
653 { "demorph", SEC_GAMEMASTER, false, &ChatHandler::HandleDeMorphCommand, "", NULL },
654 { "die", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDieCommand, "", NULL },
655 { "revive", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReviveCommand, "", NULL },
656 { "dismount", SEC_PLAYER, false, &ChatHandler::HandleDismountCommand, "", NULL },
657 { "gps", SEC_MODERATOR, false, &ChatHandler::HandleGPSCommand, "", NULL },
658 { "guid", SEC_GAMEMASTER, false, &ChatHandler::HandleGUIDCommand, "", NULL },
659 { "help", SEC_PLAYER, true, &ChatHandler::HandleHelpCommand, "", NULL },
660 { "itemmove", SEC_GAMEMASTER, false, &ChatHandler::HandleItemMoveCommand, "", NULL },
661 { "cooldown", SEC_ADMINISTRATOR, false, &ChatHandler::HandleCooldownCommand, "", NULL },
662 { "unlearn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnLearnCommand, "", NULL },
663 { "distance", SEC_ADMINISTRATOR, false, &ChatHandler::HandleGetDistanceCommand, "", NULL },
664 { "recall", SEC_MODERATOR, false, &ChatHandler::HandleRecallCommand, "", NULL },
665 { "save", SEC_PLAYER, false, &ChatHandler::HandleSaveCommand, "", NULL },
666 { "saveall", SEC_MODERATOR, true, &ChatHandler::HandleSaveAllCommand, "", NULL },
667 { "kick", SEC_GAMEMASTER, true, &ChatHandler::HandleKickPlayerCommand, "", NULL },
668 { "ban", SEC_ADMINISTRATOR, true, NULL, "", banCommandTable },
669 { "unban", SEC_ADMINISTRATOR, true, NULL, "", unbanCommandTable },
670 { "baninfo", SEC_ADMINISTRATOR, false, NULL, "", baninfoCommandTable },
671 { "banlist", SEC_ADMINISTRATOR, true, NULL, "", banlistCommandTable },
672 { "start", SEC_PLAYER, false, &ChatHandler::HandleStartCommand, "", NULL },
673 { "taxicheat", SEC_MODERATOR, false, &ChatHandler::HandleTaxiCheatCommand, "", NULL },
674 { "linkgrave", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLinkGraveCommand, "", NULL },
675 { "neargrave", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNearGraveCommand, "", NULL },
676 { "explorecheat", SEC_ADMINISTRATOR, false, &ChatHandler::HandleExploreCheatCommand, "", NULL },
677 { "hover", SEC_ADMINISTRATOR, false, &ChatHandler::HandleHoverCommand, "", NULL },
678 { "levelup", SEC_ADMINISTRATOR, false, &ChatHandler::HandleLevelUpCommand, "", NULL },
679 { "showarea", SEC_ADMINISTRATOR, false, &ChatHandler::HandleShowAreaCommand, "", NULL },
680 { "hidearea", SEC_ADMINISTRATOR, false, &ChatHandler::HandleHideAreaCommand, "", NULL },
681 { "additem", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddItemCommand, "", NULL },
682 { "additemset", SEC_ADMINISTRATOR, false, &ChatHandler::HandleAddItemSetCommand, "", NULL },
683 { "bank", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBankCommand, "", NULL },
684 { "wchange", SEC_ADMINISTRATOR, false, &ChatHandler::HandleChangeWeather, "", NULL },
685 { "ticket", SEC_GAMEMASTER, true, &ChatHandler::HandleTicketCommand, "", NULL },
686 { "delticket", SEC_GAMEMASTER, true, &ChatHandler::HandleDelTicketCommand, "", NULL },
687 { "maxskill", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMaxSkillCommand, "", NULL },
688 { "setskill", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSetSkillCommand, "", NULL },
689 { "whispers", SEC_MODERATOR, false, &ChatHandler::HandleWhispersCommand, "", NULL },
690 { "pinfo", SEC_GAMEMASTER, true, &ChatHandler::HandlePInfoCommand, "", NULL },
691 { "respawn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleRespawnCommand, "", NULL },
692 { "send", SEC_MODERATOR, true, NULL, "", sendCommandTable },
693 { "loadscripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLoadScriptsCommand, "", NULL },
694 { "mute", SEC_MODERATOR, true, &ChatHandler::HandleMuteCommand, "", NULL },
695 { "unmute", SEC_MODERATOR, true, &ChatHandler::HandleUnmuteCommand, "", NULL },
696 { "movegens", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMovegensCommand, "", NULL },
697 { "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL },
698 { "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL },
699 { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL },
700 { "flusharenapoints",SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
701 { "repairitems", SEC_GAMEMASTER, true, &ChatHandler::HandleRepairitemsCommand, "", NULL },
702 { "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL },
703 { "quit", SEC_CONSOLE, true, &ChatHandler::HandleQuitCommand, "", NULL },
705 { NULL, 0, false, NULL, "", NULL }
708 if(load_command_table)
710 load_command_table = false;
712 QueryResult *result = WorldDatabase.Query("SELECT name,security,help FROM command");
713 if (result)
717 Field *fields = result->Fetch();
718 std::string name = fields[0].GetCppString();
720 SetDataForCommandInTable(commandTable, name.c_str(), fields[1].GetUInt16(), fields[2].GetCppString(), name);
722 } while(result->NextRow());
723 delete result;
727 return commandTable;
730 const char *ChatHandler::GetMangosString(int32 entry) const
732 return m_session->GetMangosString(entry);
735 uint32 ChatHandler::GetAccountId() const
737 return m_session->GetAccountId();
740 AccountTypes ChatHandler::GetAccessLevel() const
742 return m_session->GetSecurity();
745 bool ChatHandler::isAvailable(ChatCommand const& cmd) const
747 // check security level only for simple command (without child commands)
748 return GetAccessLevel() >= (AccountTypes)cmd.SecurityLevel;
751 bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong)
753 WorldSession* target_session = NULL;
754 uint32 target_account = 0;
756 if (target)
757 target_session = target->GetSession();
758 else if (guid)
759 target_account = sObjectMgr.GetPlayerAccountIdByGUID(guid);
761 if(!target_session && !target_account)
763 SendSysMessage(LANG_PLAYER_NOT_FOUND);
764 SetSentErrorMessage(true);
765 return true;
768 return HasLowerSecurityAccount(target_session,target_account,strong);
771 bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_account, bool strong)
773 AccountTypes target_sec;
775 // ignore only for non-players for non strong checks (when allow apply command at least to same sec level)
776 if (GetAccessLevel() > SEC_PLAYER && !strong && !sWorld.getConfig(CONFIG_BOOL_GM_LOWER_SECURITY))
777 return false;
779 if (target)
780 target_sec = target->GetSecurity();
781 else if (target_account)
782 target_sec = sAccountMgr.GetSecurity(target_account);
783 else
784 return true; // caller must report error for (target==NULL && target_account==0)
786 if (GetAccessLevel() < target_sec || (strong && GetAccessLevel() <= target_sec))
788 SendSysMessage(LANG_YOURS_SECURITY_IS_LOW);
789 SetSentErrorMessage(true);
790 return true;
793 return false;
796 bool ChatHandler::hasStringAbbr(const char* name, const char* part)
798 // non "" command
799 if( *name )
801 // "" part from non-"" command
802 if( !*part )
803 return false;
805 for(;;)
807 if( !*part )
808 return true;
809 else if( !*name )
810 return false;
811 else if( tolower( *name ) != tolower( *part ) )
812 return false;
813 ++name; ++part;
816 // allow with any for ""
818 return true;
821 void ChatHandler::SendSysMessage(const char *str)
823 WorldPacket data;
825 // need copy to prevent corruption by strtok call in LineFromMessage original string
826 char* buf = mangos_strdup(str);
827 char* pos = buf;
829 while(char* line = LineFromMessage(pos))
831 FillSystemMessageData(&data, line);
832 m_session->SendPacket(&data);
835 delete [] buf;
838 void ChatHandler::SendGlobalSysMessage(const char *str)
840 // Chat output
841 WorldPacket data;
843 // need copy to prevent corruption by strtok call in LineFromMessage original string
844 char* buf = mangos_strdup(str);
845 char* pos = buf;
847 while(char* line = LineFromMessage(pos))
849 FillSystemMessageData(&data, line);
850 sWorld.SendGlobalMessage(&data);
853 delete [] buf;
856 void ChatHandler::SendSysMessage(int32 entry)
858 SendSysMessage(GetMangosString(entry));
861 void ChatHandler::PSendSysMessage(int32 entry, ...)
863 const char *format = GetMangosString(entry);
864 va_list ap;
865 char str [2048];
866 va_start(ap, entry);
867 vsnprintf(str,2048,format, ap );
868 va_end(ap);
869 SendSysMessage(str);
872 void ChatHandler::PSendSysMessage(const char *format, ...)
874 va_list ap;
875 char str [2048];
876 va_start(ap, format);
877 vsnprintf(str,2048,format, ap );
878 va_end(ap);
879 SendSysMessage(str);
882 bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcmd)
884 char const* oldtext = text;
885 std::string cmd = "";
887 while (*text != ' ' && *text != '\0')
889 cmd += *text;
890 ++text;
893 while (*text == ' ') ++text;
895 for(uint32 i = 0; table[i].Name != NULL; ++i)
897 if( !hasStringAbbr(table[i].Name, cmd.c_str()) )
898 continue;
900 // select subcommand from child commands list
901 if(table[i].ChildCommands != NULL)
903 if(!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd))
905 if(text && text[0] != '\0')
906 SendSysMessage(LANG_NO_SUBCMD);
907 else
908 SendSysMessage(LANG_CMD_SYNTAX);
910 ShowHelpForCommand(table[i].ChildCommands,text);
911 SetSentErrorMessage(true);
914 return true;
917 // must be available and have handler
918 if(!table[i].Handler || !isAvailable(table[i]))
919 continue;
921 SetSentErrorMessage(false);
922 // table[i].Name == "" is special case: send original command to handler
923 if((this->*(table[i].Handler))(strlen(table[i].Name)!=0 ? text : oldtext))
925 if(table[i].SecurityLevel > SEC_PLAYER)
927 // chat case
928 if (m_session)
930 Player* p = m_session->GetPlayer();
931 ObjectGuid sel_guid = p->GetSelection();
932 sLog.outCommand(GetAccountId(),"Command: %s [Player: %s (Account: %u) X: %f Y: %f Z: %f Map: %u Selected: %s]",
933 fullcmd.c_str(),p->GetName(),GetAccountId(),p->GetPositionX(),p->GetPositionY(),p->GetPositionZ(),p->GetMapId(),
934 sel_guid.GetString().c_str());
936 else // 0 account -> console
938 sLog.outCommand(GetAccountId(),"Command: %s [Account: %u from %s]",
939 fullcmd.c_str(),GetAccountId(),GetAccountId() ? "RA-connection" : "Console");
943 // some commands have custom error messages. Don't send the default one in these cases.
944 else if(!HasSentErrorMessage())
946 if(!table[i].Help.empty())
947 SendSysMessage(table[i].Help.c_str());
948 else
949 SendSysMessage(LANG_CMD_SYNTAX);
950 SetSentErrorMessage(true);
953 return true;
956 return false;
959 bool ChatHandler::SetDataForCommandInTable(ChatCommand *table, const char* text, uint32 security, std::string const& help, std::string const& fullcommand )
961 std::string cmd = "";
963 while (*text != ' ' && *text != '\0')
965 cmd += *text;
966 ++text;
969 while (*text == ' ') ++text;
971 for(uint32 i = 0; table[i].Name != NULL; i++)
973 // for data fill use full explicit command names
974 if( table[i].Name != cmd )
975 continue;
977 // select subcommand from child commands list (including "")
978 if(table[i].ChildCommands != NULL)
980 if(SetDataForCommandInTable(table[i].ChildCommands, text, security, help, fullcommand))
981 return true;
982 else if(*text)
983 return false;
985 // fail with "" subcommands, then use normal level up command instead
987 // expected subcommand by full name DB content
988 else if(*text)
990 sLog.outErrorDb("Table `command` have unexpected subcommand '%s' in command '%s', skip.",text,fullcommand.c_str());
991 return false;
994 if(table[i].SecurityLevel != security)
995 DETAIL_LOG("Table `command` overwrite for command '%s' default security (%u) by %u",fullcommand.c_str(),table[i].SecurityLevel,security);
997 table[i].SecurityLevel = security;
998 table[i].Help = help;
999 return true;
1002 // in case "" command let process by caller
1003 if(!cmd.empty())
1005 if(table==getCommandTable())
1006 sLog.outErrorDb("Table `command` have not existed command '%s', skip.",cmd.c_str());
1007 else
1008 sLog.outErrorDb("Table `command` have not existed subcommand '%s' in command '%s', skip.",cmd.c_str(),fullcommand.c_str());
1011 return false;
1014 int ChatHandler::ParseCommands(const char* text)
1016 ASSERT(text);
1017 ASSERT(*text);
1019 //if(m_session->GetSecurity() == 0)
1020 // return 0;
1022 /// chat case (.command or !command format)
1023 if (m_session)
1025 if(text[0] != '!' && text[0] != '.')
1026 return 0;
1029 /// ignore single . and ! in line
1030 if (strlen(text) < 2)
1031 return 0;
1033 /// ignore messages staring from many dots.
1034 if ((text[0] == '.' && text[1] == '.') || (text[0] == '!' && text[1] == '!'))
1035 return 0;
1037 /// skip first . or ! (in console allowed use command with . and ! and without its)
1038 if (text[0] == '!' || text[0] == '.')
1039 ++text;
1041 std::string fullcmd = text; // original `text` can't be used. It content destroyed in command code processing.
1043 if (!ExecuteCommandInTable(getCommandTable(), text, fullcmd))
1045 SendSysMessage(LANG_NO_CMD);
1046 SetSentErrorMessage(true);
1049 return 1;
1052 bool ChatHandler::isValidChatMessage(const char* message)
1056 valid examples:
1057 |cffa335ee|Hitem:812:0:0:0:0:0:0:0:70|h[Glowing Brightwood Staff]|h|r
1058 |cff808080|Hquest:2278:47|h[The Platinum Discs]|h|r
1059 |cffffd000|Htrade:4037:1:150:1:6AAAAAAAAAAAAAAAAAAAAAAOAADAAAAAAAAAAAAAAAAIAAAAAAAAA|h[Engineering]|h|r
1060 |cff4e96f7|Htalent:2232:-1|h[Taste for Blood]|h|r
1061 |cff71d5ff|Hspell:21563|h[Command]|h|r
1062 |cffffd000|Henchant:3919|h[Engineering: Rough Dynamite]|h|r
1063 |cffffff00|Hachievement:546:0000000000000001:0:0:0:-1:0:0:0:0|h[Safe Deposit]|h|r
1064 |cff66bbff|Hglyph:21:762|h[Glyph of Bladestorm]|h|r
1066 | will be escaped to ||
1069 if(strlen(message) > 255)
1070 return false;
1072 const char validSequence[6] = "cHhhr";
1073 const char* validSequenceIterator = validSequence;
1075 // more simple checks
1076 if (sWorld.getConfig(CONFIG_UINT32_CHAT_STRICT_LINK_CHECKING_SEVERITY) < 3)
1078 const std::string validCommands = "cHhr|";
1080 while(*message)
1082 // find next pipe command
1083 message = strchr(message, '|');
1085 if(!message)
1086 return true;
1088 ++message;
1089 char commandChar = *message;
1090 if(validCommands.find(commandChar) == std::string::npos)
1091 return false;
1093 ++message;
1094 // validate sequence
1095 if(sWorld.getConfig(CONFIG_UINT32_CHAT_STRICT_LINK_CHECKING_SEVERITY) == 2)
1097 if(commandChar == *validSequenceIterator)
1099 if (validSequenceIterator == validSequence+4)
1100 validSequenceIterator = validSequence;
1101 else
1102 ++validSequenceIterator;
1104 else if(commandChar != '|')
1105 return false;
1108 return true;
1111 std::istringstream reader(message);
1112 char buffer[256];
1114 uint32 color;
1116 ItemPrototype const* linkedItem;
1117 Quest const* linkedQuest;
1118 SpellEntry const *linkedSpell;
1119 AchievementEntry const* linkedAchievement;
1120 ItemRandomPropertiesEntry const* itemProperty;
1121 ItemRandomSuffixEntry const* itemSuffix;
1123 while(!reader.eof())
1125 if (validSequence == validSequenceIterator)
1127 linkedItem = NULL;
1128 linkedQuest = NULL;
1129 linkedSpell = NULL;
1130 linkedAchievement = NULL;
1131 itemProperty = NULL;
1132 itemSuffix = NULL;
1134 reader.ignore(255, '|');
1136 else if(reader.get() != '|')
1138 DEBUG_LOG("ChatHandler::isValidChatMessage sequence aborted unexpectedly");
1139 return false;
1142 // pipe has always to be followed by at least one char
1143 if ( reader.peek() == '\0')
1145 DEBUG_LOG("ChatHandler::isValidChatMessage pipe followed by \\0");
1146 return false;
1149 // no further pipe commands
1150 if (reader.eof())
1151 break;
1153 char commandChar;
1154 reader >> commandChar;
1156 // | in normal messages is escaped by ||
1157 if (commandChar != '|')
1159 if(commandChar == *validSequenceIterator)
1161 if (validSequenceIterator == validSequence+4)
1162 validSequenceIterator = validSequence;
1163 else
1164 ++validSequenceIterator;
1166 else
1168 DEBUG_LOG("ChatHandler::isValidChatMessage invalid sequence, expected %c but got %c", *validSequenceIterator, commandChar);
1169 return false;
1172 else if(validSequence != validSequenceIterator)
1174 // no escaped pipes in sequences
1175 DEBUG_LOG("ChatHandler::isValidChatMessage got escaped pipe in sequence");
1176 return false;
1179 switch (commandChar)
1181 case 'c':
1182 color = 0;
1183 // validate color, expect 8 hex chars
1184 for(int i=0; i<8; i++)
1186 char c;
1187 reader >> c;
1188 if(!c)
1190 DEBUG_LOG("ChatHandler::isValidChatMessage got \\0 while reading color in |c command");
1191 return false;
1194 color <<= 4;
1195 // check for hex char
1196 if(c >= '0' && c <='9')
1198 color |= c-'0';
1199 continue;
1201 if(c >= 'a' && c <='f')
1203 color |= 10+c-'a';
1204 continue;
1206 DEBUG_LOG("ChatHandler::isValidChatMessage got non hex char '%c' while reading color", c);
1207 return false;
1209 break;
1210 case 'H':
1211 // read chars up to colon = link type
1212 reader.getline(buffer, 256, ':');
1214 if (strcmp(buffer, "item") == 0)
1216 // read item entry
1217 reader.getline(buffer, 256, ':');
1219 linkedItem = ObjectMgr::GetItemPrototype(atoi(buffer));
1220 if(!linkedItem)
1222 DEBUG_LOG("ChatHandler::isValidChatMessage got invalid itemID %u in |item command", atoi(buffer));
1223 return false;
1226 if (color != ItemQualityColors[linkedItem->Quality])
1228 DEBUG_LOG("ChatHandler::isValidChatMessage linked item has color %u, but user claims %u", ItemQualityColors[linkedItem->Quality],
1229 color);
1230 return false;
1233 // the itementry is followed by several integers which describe an instance of this item
1235 // position relative after itemEntry
1236 const uint8 randomPropertyPosition = 6;
1238 int32 propertyId = 0;
1239 bool negativeNumber = false;
1240 char c;
1241 for(uint8 i=0; i<randomPropertyPosition; ++i)
1243 propertyId = 0;
1244 negativeNumber = false;
1245 while((c = reader.get())!=':')
1247 if(c >='0' && c<='9')
1249 propertyId*=10;
1250 propertyId += c-'0';
1251 } else if(c == '-')
1252 negativeNumber = true;
1253 else
1254 return false;
1257 if (negativeNumber)
1258 propertyId *= -1;
1260 if (propertyId > 0)
1262 itemProperty = sItemRandomPropertiesStore.LookupEntry(propertyId);
1263 if (!itemProperty)
1264 return false;
1266 else if(propertyId < 0)
1268 itemSuffix = sItemRandomSuffixStore.LookupEntry(-propertyId);
1269 if (!itemSuffix)
1270 return false;
1273 // ignore other integers
1274 while ((c >= '0' && c <= '9') || c== ':')
1276 reader.ignore(1);
1277 c = reader.peek();
1280 else if(strcmp(buffer, "quest") == 0)
1282 // no color check for questlinks, each client will adapt it anyway
1283 uint32 questid= 0;
1284 // read questid
1285 char c = reader.peek();
1286 while(c >='0' && c<='9')
1288 reader.ignore(1);
1289 questid *= 10;
1290 questid += c-'0';
1291 c = reader.peek();
1294 linkedQuest = sObjectMgr.GetQuestTemplate(questid);
1296 if(!linkedQuest)
1298 DEBUG_LOG("ChatHandler::isValidChatMessage Questtemplate %u not found", questid);
1299 return false;
1301 c = reader.peek();
1302 // level
1303 while(c !='|' && c!='\0')
1305 reader.ignore(1);
1306 c = reader.peek();
1309 else if(strcmp(buffer, "trade") == 0)
1311 if(color != CHAT_LINK_COLOR_TRADE)
1312 return false;
1314 // read spell entry
1315 reader.getline(buffer, 256, ':');
1316 linkedSpell = sSpellStore.LookupEntry(atoi(buffer));
1317 if(!linkedSpell)
1318 return false;
1320 char c = reader.peek();
1321 // base64 encoded stuff
1322 while(c !='|' && c!='\0')
1324 reader.ignore(1);
1325 c = reader.peek();
1328 else if(strcmp(buffer, "talent") == 0)
1330 // talent links are always supposed to be blue
1331 if(color != CHAT_LINK_COLOR_TALENT)
1332 return false;
1334 // read talent entry
1335 reader.getline(buffer, 256, ':');
1336 TalentEntry const *talentInfo = sTalentStore.LookupEntry(atoi(buffer));
1337 if(!talentInfo)
1338 return false;
1340 linkedSpell = sSpellStore.LookupEntry(talentInfo->RankID[0]);
1341 if(!linkedSpell)
1342 return false;
1344 char c = reader.peek();
1345 // skillpoints? whatever, drop it
1346 while(c !='|' && c!='\0')
1348 reader.ignore(1);
1349 c = reader.peek();
1352 else if(strcmp(buffer, "spell") == 0)
1354 if(color != CHAT_LINK_COLOR_SPELL)
1355 return false;
1357 uint32 spellid = 0;
1358 // read spell entry
1359 char c = reader.peek();
1360 while(c >='0' && c<='9')
1362 reader.ignore(1);
1363 spellid *= 10;
1364 spellid += c-'0';
1365 c = reader.peek();
1367 linkedSpell = sSpellStore.LookupEntry(spellid);
1368 if(!linkedSpell)
1369 return false;
1371 else if(strcmp(buffer, "enchant") == 0)
1373 if(color != CHAT_LINK_COLOR_ENCHANT)
1374 return false;
1376 uint32 spellid = 0;
1377 // read spell entry
1378 char c = reader.peek();
1379 while(c >='0' && c<='9')
1381 reader.ignore(1);
1382 spellid *= 10;
1383 spellid += c-'0';
1384 c = reader.peek();
1386 linkedSpell = sSpellStore.LookupEntry(spellid);
1387 if(!linkedSpell)
1388 return false;
1390 else if(strcmp(buffer, "achievement") == 0)
1392 if(color != CHAT_LINK_COLOR_ACHIEVEMENT)
1393 return false;
1394 reader.getline(buffer, 256, ':');
1395 uint32 achievementId = atoi(buffer);
1396 linkedAchievement = sAchievementStore.LookupEntry(achievementId);
1398 if(!linkedAchievement)
1399 return false;
1401 char c = reader.peek();
1402 // skip progress
1403 while(c !='|' && c!='\0')
1405 reader.ignore(1);
1406 c = reader.peek();
1409 else if(strcmp(buffer, "glyph") == 0)
1411 if(color != CHAT_LINK_COLOR_GLYPH)
1412 return false;
1414 // first id is slot, drop it
1415 reader.getline(buffer, 256, ':');
1416 uint32 glyphId = 0;
1417 char c = reader.peek();
1418 while(c>='0' && c <='9')
1420 glyphId *= 10;
1421 glyphId += c-'0';
1422 reader.ignore(1);
1423 c = reader.peek();
1425 GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId);
1426 if (!glyph)
1427 return false;
1429 linkedSpell = sSpellStore.LookupEntry(glyph->SpellId);
1431 if (!linkedSpell)
1432 return false;
1434 else
1436 DEBUG_LOG("ChatHandler::isValidChatMessage user sent unsupported link type '%s'", buffer);
1437 return false;
1439 break;
1440 case 'h':
1441 // if h is next element in sequence, this one must contain the linked text :)
1442 if (*validSequenceIterator == 'h')
1444 // links start with '['
1445 if (reader.get() != '[')
1447 DEBUG_LOG("ChatHandler::isValidChatMessage link caption doesn't start with '['");
1448 return false;
1450 reader.getline(buffer, 256, ']');
1452 // verify the link name
1453 if (linkedSpell)
1455 // spells with that flag have a prefix of "$PROFESSION: "
1456 if (linkedSpell->Attributes & SPELL_ATTR_TRADESPELL)
1458 // lookup skillid
1459 SkillLineAbilityMapBounds bounds = sSpellMgr.GetSkillLineAbilityMapBounds(linkedSpell->Id);
1460 if (bounds.first == bounds.second)
1462 return false;
1465 SkillLineAbilityEntry const *skillInfo = bounds.first->second;
1467 if (!skillInfo)
1469 return false;
1472 SkillLineEntry const *skillLine = sSkillLineStore.LookupEntry(skillInfo->skillId);
1473 if (!skillLine)
1475 return false;
1478 for(uint8 i=0; i<MAX_LOCALE; ++i)
1480 uint32 skillLineNameLength = strlen(skillLine->name[i]);
1481 if (skillLineNameLength > 0 && strncmp(skillLine->name[i], buffer, skillLineNameLength) == 0)
1483 // found the prefix, remove it to perform spellname validation below
1484 // -2 = strlen(": ")
1485 uint32 spellNameLength = strlen(buffer)-skillLineNameLength-2;
1486 memmove(buffer, buffer+skillLineNameLength+2, spellNameLength+1);
1490 bool foundName = false;
1491 for(uint8 i=0; i<MAX_LOCALE; ++i)
1493 if (*linkedSpell->SpellName[i] && strcmp(linkedSpell->SpellName[i], buffer) == 0)
1495 foundName = true;
1496 break;
1499 if (!foundName)
1500 return false;
1502 else if (linkedQuest)
1504 if (linkedQuest->GetTitle() != buffer)
1506 QuestLocale const *ql = sObjectMgr.GetQuestLocale(linkedQuest->GetQuestId());
1508 if (!ql)
1510 DEBUG_LOG("ChatHandler::isValidChatMessage default questname didn't match and there is no locale");
1511 return false;
1514 bool foundName = false;
1515 for(uint8 i=0; i<ql->Title.size(); i++)
1517 if (ql->Title[i] == buffer)
1519 foundName = true;
1520 break;
1523 if (!foundName)
1525 DEBUG_LOG("ChatHandler::isValidChatMessage no quest locale title matched");
1526 return false;
1530 else if(linkedItem)
1532 char* const* suffix = itemSuffix?itemSuffix->nameSuffix:(itemProperty?itemProperty->nameSuffix:NULL);
1534 std::string expectedName = std::string(linkedItem->Name1);
1535 if (suffix)
1537 expectedName += " ";
1538 expectedName += suffix[LOCALE_enUS];
1541 if (expectedName != buffer)
1543 ItemLocale const *il = sObjectMgr.GetItemLocale(linkedItem->ItemId);
1545 bool foundName = false;
1546 for(uint8 i=LOCALE_koKR; i<MAX_LOCALE; ++i)
1548 int8 dbIndex = sObjectMgr.GetIndexForLocale(LocaleConstant(i));
1549 if (dbIndex == -1 || il == NULL || (size_t)dbIndex >= il->Name.size())
1550 // using strange database/client combinations can lead to this case
1551 expectedName = linkedItem->Name1;
1552 else
1553 expectedName = il->Name[dbIndex];
1554 if (suffix)
1556 expectedName += " ";
1557 expectedName += suffix[i];
1559 if ( expectedName == buffer)
1561 foundName = true;
1562 break;
1565 if (!foundName)
1567 DEBUG_LOG("ChatHandler::isValidChatMessage linked item name wasn't found in any localization");
1568 return false;
1572 else if (linkedAchievement)
1574 bool foundName = false;
1575 for(uint8 i=0; i<MAX_LOCALE; ++i)
1577 if (*linkedAchievement->name[i] && strcmp(linkedAchievement->name[i], buffer) == 0)
1579 foundName = true;
1580 break;
1583 if (!foundName)
1584 return false;
1586 // that place should never be reached - if nothing linked has been set in |H
1587 // it will return false before
1588 else
1589 return false;
1591 break;
1592 case 'r':
1593 case '|':
1594 // no further payload
1595 break;
1596 default:
1597 DEBUG_LOG("ChatHandler::isValidChatMessage got invalid command |%c", commandChar);
1598 return false;
1602 // check if every opened sequence was also closed properly
1603 if(validSequence != validSequenceIterator)
1604 DEBUG_LOG("ChatHandler::isValidChatMessage EOF in active sequence");
1606 return validSequence == validSequenceIterator;
1609 bool ChatHandler::ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd)
1611 std::string list;
1612 for(uint32 i = 0; table[i].Name != NULL; ++i)
1614 // must be available (ignore handler existence for show command with possibe avalable subcomands
1615 if(!isAvailable(table[i]))
1616 continue;
1618 /// for empty subcmd show all available
1619 if( *subcmd && !hasStringAbbr(table[i].Name, subcmd))
1620 continue;
1622 if(m_session)
1623 list += "\n ";
1624 else
1625 list += "\n\r ";
1627 list += table[i].Name;
1629 if(table[i].ChildCommands)
1630 list += " ...";
1633 if(list.empty())
1634 return false;
1636 if(table==getCommandTable())
1638 SendSysMessage(LANG_AVIABLE_CMD);
1639 PSendSysMessage("%s",list.c_str());
1641 else
1642 PSendSysMessage(LANG_SUBCMDS_LIST,cmd,list.c_str());
1644 return true;
1647 bool ChatHandler::ShowHelpForCommand(ChatCommand *table, const char* cmd)
1649 if(*cmd)
1651 for(uint32 i = 0; table[i].Name != NULL; ++i)
1653 // must be available (ignore handler existence for show command with possibe avalable subcomands
1654 if(!isAvailable(table[i]))
1655 continue;
1657 if( !hasStringAbbr(table[i].Name, cmd) )
1658 continue;
1660 // have subcommand
1661 char const* subcmd = (*cmd) ? strtok(NULL, " ") : "";
1663 if(table[i].ChildCommands && subcmd && *subcmd)
1665 if(ShowHelpForCommand(table[i].ChildCommands, subcmd))
1666 return true;
1669 if(!table[i].Help.empty())
1670 SendSysMessage(table[i].Help.c_str());
1672 if(table[i].ChildCommands)
1673 if(ShowHelpForSubCommands(table[i].ChildCommands,table[i].Name,subcmd ? subcmd : ""))
1674 return true;
1676 return !table[i].Help.empty();
1679 else
1681 for(uint32 i = 0; table[i].Name != NULL; ++i)
1683 // must be available (ignore handler existence for show command with possibe avalable subcomands
1684 if(!isAvailable(table[i]))
1685 continue;
1687 if(strlen(table[i].Name))
1688 continue;
1690 if(!table[i].Help.empty())
1691 SendSysMessage(table[i].Help.c_str());
1693 if(table[i].ChildCommands)
1694 if(ShowHelpForSubCommands(table[i].ChildCommands,"",""))
1695 return true;
1697 return !table[i].Help.empty();
1701 return ShowHelpForSubCommands(table,"",cmd);
1704 //Note: target_guid used only in CHAT_MSG_WHISPER_INFORM mode (in this case channelName ignored)
1705 void ChatHandler::FillMessageData( WorldPacket *data, WorldSession* session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker)
1707 uint32 messageLength = (message ? strlen(message) : 0) + 1;
1709 data->Initialize(SMSG_MESSAGECHAT, 100); // guess size
1710 *data << uint8(type);
1711 if ((type != CHAT_MSG_CHANNEL && type != CHAT_MSG_WHISPER) || language == LANG_ADDON)
1712 *data << uint32(language);
1713 else
1714 *data << uint32(LANG_UNIVERSAL);
1716 switch(type)
1718 case CHAT_MSG_SAY:
1719 case CHAT_MSG_PARTY:
1720 case CHAT_MSG_PARTY_LEADER:
1721 case CHAT_MSG_RAID:
1722 case CHAT_MSG_GUILD:
1723 case CHAT_MSG_OFFICER:
1724 case CHAT_MSG_YELL:
1725 case CHAT_MSG_WHISPER:
1726 case CHAT_MSG_CHANNEL:
1727 case CHAT_MSG_RAID_LEADER:
1728 case CHAT_MSG_RAID_WARNING:
1729 case CHAT_MSG_BG_SYSTEM_NEUTRAL:
1730 case CHAT_MSG_BG_SYSTEM_ALLIANCE:
1731 case CHAT_MSG_BG_SYSTEM_HORDE:
1732 case CHAT_MSG_BATTLEGROUND:
1733 case CHAT_MSG_BATTLEGROUND_LEADER:
1734 target_guid = session ? session->GetPlayer()->GetGUID() : 0;
1735 break;
1736 case CHAT_MSG_MONSTER_SAY:
1737 case CHAT_MSG_MONSTER_PARTY:
1738 case CHAT_MSG_MONSTER_YELL:
1739 case CHAT_MSG_MONSTER_WHISPER:
1740 case CHAT_MSG_MONSTER_EMOTE:
1741 case CHAT_MSG_RAID_BOSS_WHISPER:
1742 case CHAT_MSG_RAID_BOSS_EMOTE:
1743 case CHAT_MSG_BATTLENET:
1745 *data << uint64(speaker->GetGUID());
1746 *data << uint32(0); // 2.1.0
1747 *data << uint32(strlen(speaker->GetName()) + 1);
1748 *data << speaker->GetName();
1749 ObjectGuid listener_guid;
1750 *data << listener_guid;
1751 if (!listener_guid.IsEmpty() && !listener_guid.IsPlayer())
1753 *data << uint32(1); // string listener_name_length
1754 *data << uint8(0); // string listener_name
1756 *data << uint32(messageLength);
1757 *data << message;
1758 *data << uint8(0);
1759 return;
1761 default:
1762 if (type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_IGNORED && type != CHAT_MSG_DND && type != CHAT_MSG_AFK)
1763 target_guid = 0; // only for CHAT_MSG_WHISPER_INFORM used original value target_guid
1764 break;
1767 *data << uint64(target_guid); // there 0 for BG messages
1768 *data << uint32(0); // can be chat msg group or something
1770 if (type == CHAT_MSG_CHANNEL)
1772 ASSERT(channelName);
1773 *data << channelName;
1776 *data << uint64(target_guid);
1777 *data << uint32(messageLength);
1778 *data << message;
1779 if(session != 0 && type != CHAT_MSG_WHISPER_INFORM && type != CHAT_MSG_DND && type != CHAT_MSG_AFK)
1780 *data << uint8(session->GetPlayer()->chatTag());
1781 else
1782 *data << uint8(0);
1785 Player * ChatHandler::getSelectedPlayer()
1787 if(!m_session)
1788 return NULL;
1790 uint64 guid = m_session->GetPlayer()->GetSelection();
1792 if (guid == 0)
1793 return m_session->GetPlayer();
1795 return sObjectMgr.GetPlayer(guid);
1798 Unit* ChatHandler::getSelectedUnit()
1800 if(!m_session)
1801 return NULL;
1803 uint64 guid = m_session->GetPlayer()->GetSelection();
1805 if (guid == 0)
1806 return m_session->GetPlayer();
1808 return ObjectAccessor::GetUnit(*m_session->GetPlayer(),guid);
1811 Creature* ChatHandler::getSelectedCreature()
1813 if(!m_session)
1814 return NULL;
1816 return m_session->GetPlayer()->GetMap()->GetCreatureOrPetOrVehicle(m_session->GetPlayer()->GetSelection());
1819 char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1)
1821 // skip empty
1822 if(!text)
1823 return NULL;
1825 // skip speces
1826 while(*text==' '||*text=='\t'||*text=='\b')
1827 ++text;
1829 if(!*text)
1830 return NULL;
1832 // return non link case
1833 if(text[0]!='|')
1834 return strtok(text, " ");
1836 // [name] Shift-click form |color|linkType:key|h[name]|h|r
1837 // or
1838 // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r
1840 char* check = strtok(text, "|"); // skip color
1841 if(!check)
1842 return NULL; // end of data
1844 char* cLinkType = strtok(NULL, ":"); // linktype
1845 if(!cLinkType)
1846 return NULL; // end of data
1848 if(strcmp(cLinkType,linkType) != 0)
1850 strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after retturn from function
1851 SendSysMessage(LANG_WRONG_LINK_TYPE);
1852 return NULL;
1855 char* cKeys = strtok(NULL, "|"); // extract keys and values
1856 char* cKeysTail = strtok(NULL, "");
1858 char* cKey = strtok(cKeys, ":|"); // extract key
1859 if(something1)
1860 *something1 = strtok(NULL, ":|"); // extract something
1862 strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces
1863 strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function
1864 return cKey;
1867 char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1)
1869 // skip empty
1870 if(!text)
1871 return NULL;
1873 // skip speces
1874 while(*text==' '||*text=='\t'||*text=='\b')
1875 ++text;
1877 if(!*text)
1878 return NULL;
1880 // return non link case
1881 if(text[0]!='|')
1882 return strtok(text, " ");
1884 // [name] Shift-click form |color|linkType:key|h[name]|h|r
1885 // or
1886 // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r
1887 // or
1888 // [name] Shift-click form |linkType:key|h[name]|h|r
1890 char* tail;
1892 if(text[1]=='c')
1894 char* check = strtok(text, "|"); // skip color
1895 if(!check)
1896 return NULL; // end of data
1898 tail = strtok(NULL, ""); // tail
1900 else
1901 tail = text+1; // skip first |
1903 char* cLinkType = strtok(tail, ":"); // linktype
1904 if(!cLinkType)
1905 return NULL; // end of data
1907 for(int i = 0; linkTypes[i]; ++i)
1909 if(strcmp(cLinkType,linkTypes[i]) == 0)
1911 char* cKeys = strtok(NULL, "|"); // extract keys and values
1912 char* cKeysTail = strtok(NULL, "");
1914 char* cKey = strtok(cKeys, ":|"); // extract key
1915 if(something1)
1916 *something1 = strtok(NULL, ":|"); // extract something
1918 strtok(cKeysTail, "]"); // restart scan tail and skip name with possible spaces
1919 strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function
1920 if(found_idx)
1921 *found_idx = i;
1922 return cKey;
1926 strtok(NULL, " "); // skip link tail (to allow continue strtok(NULL,s) use after return from function
1927 SendSysMessage(LANG_WRONG_LINK_TYPE);
1928 return NULL;
1931 char const *fmtstring( char const *format, ... )
1933 va_list argptr;
1934 #define MAX_FMT_STRING 32000
1935 static char temp_buffer[MAX_FMT_STRING];
1936 static char string[MAX_FMT_STRING];
1937 static int index = 0;
1938 char *buf;
1939 int len;
1941 va_start(argptr, format);
1942 vsnprintf(temp_buffer,MAX_FMT_STRING, format, argptr);
1943 va_end(argptr);
1945 len = strlen(temp_buffer);
1947 if( len >= MAX_FMT_STRING )
1948 return "ERROR";
1950 if (len + index >= MAX_FMT_STRING-1)
1952 index = 0;
1955 buf = &string[index];
1956 memcpy( buf, temp_buffer, len+1 );
1958 index += len + 1;
1960 return buf;
1963 GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry)
1965 if(!m_session)
1966 return NULL;
1968 Player* pl = m_session->GetPlayer();
1970 GameObject* obj = pl->GetMap()->GetGameObject(MAKE_NEW_GUID(lowguid, entry, HIGHGUID_GAMEOBJECT));
1972 if(!obj && sObjectMgr.GetGOData(lowguid)) // guid is DB guid of object
1974 MaNGOS::GameObjectWithDbGUIDCheck go_check(*pl,lowguid);
1975 MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(pl,obj,go_check);
1976 Cell::VisitGridObjects(pl,checker, pl->GetMap()->GetVisibilityDistance());
1979 return obj;
1982 enum SpellLinkType
1984 SPELL_LINK_SPELL = 0,
1985 SPELL_LINK_TALENT = 1,
1986 SPELL_LINK_ENCHANT = 2,
1987 SPELL_LINK_TRADE = 3,
1988 SPELL_LINK_GLYPH = 4
1991 static char const* const spellKeys[] =
1993 "Hspell", // normal spell
1994 "Htalent", // talent spell
1995 "Henchant", // enchanting recipe spell
1996 "Htrade", // profession/skill spell
1997 "Hglyph", // glyph
2001 uint32 ChatHandler::extractSpellIdFromLink(char* text)
2003 // number or [name] Shift-click form |color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r
2004 // number or [name] Shift-click form |color|Hglyph:glyph_slot_id:glyph_prop_id|h[%s]|h|r
2005 // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r
2006 // number or [name] Shift-click form |color|Htalent:talent_id,rank|h[name]|h|r
2007 // number or [name] Shift-click form |color|Htrade:spell_id,skill_id,max_value,cur_value|h[name]|h|r
2008 int type = 0;
2009 char* param1_str = NULL;
2010 char* idS = extractKeyFromLink(text,spellKeys,&type,&param1_str);
2011 if(!idS)
2012 return 0;
2014 uint32 id = (uint32)atol(idS);
2016 switch(type)
2018 case SPELL_LINK_SPELL:
2019 return id;
2020 case SPELL_LINK_TALENT:
2022 // talent
2023 TalentEntry const* talentEntry = sTalentStore.LookupEntry(id);
2024 if(!talentEntry)
2025 return 0;
2027 int32 rank = param1_str ? (uint32)atol(param1_str) : 0;
2028 if(rank >= MAX_TALENT_RANK)
2029 return 0;
2031 if(rank < 0)
2032 rank = 0;
2034 return talentEntry->RankID[rank];
2036 case SPELL_LINK_ENCHANT:
2037 case SPELL_LINK_TRADE:
2038 return id;
2039 case SPELL_LINK_GLYPH:
2041 uint32 glyph_prop_id = param1_str ? (uint32)atol(param1_str) : 0;
2043 GlyphPropertiesEntry const* glyphPropEntry = sGlyphPropertiesStore.LookupEntry(glyph_prop_id);
2044 if(!glyphPropEntry)
2045 return 0;
2047 return glyphPropEntry->SpellId;
2051 // unknown type?
2052 return 0;
2055 GameTele const* ChatHandler::extractGameTeleFromLink(char* text)
2057 // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
2058 char* cId = extractKeyFromLink(text,"Htele");
2059 if(!cId)
2060 return false;
2062 // id case (explicit or from shift link)
2063 if(cId[0] >= '0' || cId[0] >= '9')
2064 if(uint32 id = atoi(cId))
2065 return sObjectMgr.GetGameTele(id);
2067 return sObjectMgr.GetGameTele(cId);
2070 enum GuidLinkType
2072 SPELL_LINK_PLAYER = 0, // must be first for selection in not link case
2073 SPELL_LINK_CREATURE = 1,
2074 SPELL_LINK_GAMEOBJECT = 2
2077 static char const* const guidKeys[] =
2079 "Hplayer",
2080 "Hcreature",
2081 "Hgameobject",
2085 uint64 ChatHandler::extractGuidFromLink(char* text)
2087 int type = 0;
2089 // |color|Hcreature:creature_guid|h[name]|h|r
2090 // |color|Hgameobject:go_guid|h[name]|h|r
2091 // |color|Hplayer:name|h[name]|h|r
2092 char* idS = extractKeyFromLink(text,guidKeys,&type);
2093 if(!idS)
2094 return 0;
2096 switch(type)
2098 case SPELL_LINK_PLAYER:
2100 std::string name = idS;
2101 if(!normalizePlayerName(name))
2102 return 0;
2104 if(Player* player = sObjectMgr.GetPlayer(name.c_str()))
2105 return player->GetGUID();
2107 if(uint64 guid = sObjectMgr.GetPlayerGUIDByName(name))
2108 return guid;
2110 return 0;
2112 case SPELL_LINK_CREATURE:
2114 uint32 lowguid = (uint32)atol(idS);
2116 if(CreatureData const* data = sObjectMgr.GetCreatureData(lowguid) )
2117 return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT);
2118 else
2119 return 0;
2121 case SPELL_LINK_GAMEOBJECT:
2123 uint32 lowguid = (uint32)atol(idS);
2125 if(GameObjectData const* data = sObjectMgr.GetGOData(lowguid) )
2126 return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_GAMEOBJECT);
2127 else
2128 return 0;
2132 // unknown type?
2133 return 0;
2136 std::string ChatHandler::extractPlayerNameFromLink(char* text)
2138 // |color|Hplayer:name|h[name]|h|r
2139 char* name_str = extractKeyFromLink(text,"Hplayer");
2140 if(!name_str)
2141 return "";
2143 std::string name = name_str;
2144 if(!normalizePlayerName(name))
2145 return "";
2147 return name;
2150 bool ChatHandler::extractPlayerTarget(char* args, Player** player, uint64* player_guid /*=NULL*/,std::string* player_name /*= NULL*/)
2152 if (args && *args)
2154 std::string name = extractPlayerNameFromLink(args);
2155 if (name.empty())
2157 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2158 SetSentErrorMessage(true);
2159 return false;
2162 Player* pl = sObjectMgr.GetPlayer(name.c_str());
2164 // if allowed player pointer
2165 if(player)
2166 *player = pl;
2168 // if need guid value from DB (in name case for check player existence)
2169 uint64 guid = !pl && (player_guid || player_name) ? sObjectMgr.GetPlayerGUIDByName(name) : 0;
2171 // if allowed player guid (if no then only online players allowed)
2172 if(player_guid)
2173 *player_guid = pl ? pl->GetGUID() : guid;
2175 if(player_name)
2176 *player_name = pl || guid ? name : "";
2178 else
2180 Player* pl = getSelectedPlayer();
2181 // if allowed player pointer
2182 if(player)
2183 *player = pl;
2184 // if allowed player guid (if no then only online players allowed)
2185 if(player_guid)
2186 *player_guid = pl ? pl->GetGUID() : 0;
2188 if(player_name)
2189 *player_name = pl ? pl->GetName() : "";
2192 // some from req. data must be provided (note: name is empty if player not exist)
2193 if((!player || !*player) && (!player_guid || !*player_guid) && (!player_name || player_name->empty()))
2195 SendSysMessage(LANG_PLAYER_NOT_FOUND);
2196 SetSentErrorMessage(true);
2197 return false;
2200 return true;
2203 void ChatHandler::extractOptFirstArg(char* args, char** arg1, char** arg2)
2205 char* p1 = strtok(args, " ");
2206 char* p2 = strtok(NULL, " ");
2208 if(!p2)
2210 p2 = p1;
2211 p1 = NULL;
2214 if(arg1)
2215 *arg1 = p1;
2217 if(arg2)
2218 *arg2 = p2;
2221 char* ChatHandler::extractQuotedArg( char* args )
2223 if(!*args)
2224 return NULL;
2226 if(*args=='"')
2227 return strtok(args+1, "\"");
2228 else
2230 char* space = strtok(args, "\"");
2231 if(!space)
2232 return false;
2233 return strtok(NULL, "\"");
2237 uint32 ChatHandler::extractAccountId(char* args, std::string* accountName /*= NULL*/, Player** targetIfNullArg /*= NULL*/)
2239 uint32 account_id = 0;
2241 ///- Get the account name from the command line
2242 char* account_str = args ? strtok (args," ") : NULL;
2244 if (!account_str)
2246 if (!targetIfNullArg)
2247 return 0;
2249 /// only target player different from self allowed (if targetPlayer!=NULL then not console)
2250 Player* targetPlayer = getSelectedPlayer();
2251 if (!targetPlayer)
2252 return 0;
2254 account_id = targetPlayer->GetSession()->GetAccountId();
2256 if (accountName)
2257 sAccountMgr.GetName(account_id, *accountName);
2259 if (targetIfNullArg)
2260 *targetIfNullArg = targetPlayer;
2262 return account_id;
2265 std::string account_name;
2267 if (isNumeric(account_str))
2269 long id = atol(account_str);
2270 if (id <= 0 || ((unsigned long)id) >= std::numeric_limits<uint32>::max())
2272 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_str);
2273 SetSentErrorMessage(true);
2274 return 0;
2277 account_id = uint32(id);
2279 if (!sAccountMgr.GetName(account_id, account_name))
2281 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_str);
2282 SetSentErrorMessage(true);
2283 return 0;
2286 else
2288 account_name = account_str;
2289 if (!AccountMgr::normalizeString(account_name))
2291 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
2292 SetSentErrorMessage(true);
2293 return 0;
2296 account_id = sAccountMgr.GetId(account_name);
2297 if (!account_id)
2299 PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str());
2300 SetSentErrorMessage(true);
2301 return 0;
2305 if (accountName)
2306 *accountName = account_name;
2308 if (targetIfNullArg)
2309 *targetIfNullArg = NULL;
2311 return account_id;
2314 bool ChatHandler::needReportToTarget(Player* chr) const
2316 Player* pl = m_session->GetPlayer();
2317 return pl != chr && pl->IsVisibleGloballyFor(chr);
2320 LocaleConstant ChatHandler::GetSessionDbcLocale() const
2322 return m_session->GetSessionDbcLocale();
2325 int ChatHandler::GetSessionDbLocaleIndex() const
2327 return m_session->GetSessionDbLocaleIndex();
2330 const char *CliHandler::GetMangosString(int32 entry) const
2332 return sObjectMgr.GetMangosStringForDBCLocale(entry);
2335 uint32 CliHandler::GetAccountId() const
2337 return m_accountId;
2340 AccountTypes CliHandler::GetAccessLevel() const
2342 return m_loginAccessLevel;
2345 bool CliHandler::isAvailable(ChatCommand const& cmd) const
2347 // skip non-console commands in console case
2348 if (!cmd.AllowConsole)
2349 return false;
2351 // normal case
2352 return GetAccessLevel() >= (AccountTypes)cmd.SecurityLevel;
2355 void CliHandler::SendSysMessage(const char *str)
2357 m_print(m_callbackArg, str);
2358 m_print(m_callbackArg, "\r\n");
2361 std::string CliHandler::GetNameLink() const
2363 return GetMangosString(LANG_CONSOLE_COMMAND);
2366 bool CliHandler::needReportToTarget(Player* /*chr*/) const
2368 return true;
2371 LocaleConstant CliHandler::GetSessionDbcLocale() const
2373 return sWorld.GetDefaultDbcLocale();
2376 int CliHandler::GetSessionDbLocaleIndex() const
2378 return sObjectMgr.GetDBCLocaleIndex();