PageRenderTime 40ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 1ms

/FrameXML/ChatFrame.lua

https://bitbucket.org/Shenton/world-of-warcraft-user-interface-source
Lua | 4879 lines | 4228 code | 518 blank | 133 comment | 837 complexity | d9363641afb215a2b682230b8fec8f1d MD5 | raw file
  1. MESSAGE_SCROLLBUTTON_INITIAL_DELAY = 0;
  2. MESSAGE_SCROLLBUTTON_SCROLL_DELAY = 0.05;
  3. CHAT_BUTTON_FLASH_TIME = 0.5;
  4. CHAT_TELL_ALERT_TIME = 300;
  5. NUM_CHAT_WINDOWS = 10;
  6. DEFAULT_CHAT_FRAME = ChatFrame1;
  7. NUM_REMEMBERED_TELLS = 10;
  8. MAX_WOW_CHAT_CHANNELS = 10;
  9. CHAT_TIMESTAMP_FORMAT = nil; -- gets set from Interface Options
  10. CHAT_SHOW_IME = false;
  11. MAX_CHARACTER_NAME_BYTES = 48;
  12. --DEBUG FIXME FOR TESTING
  13. CHAT_OPTIONS = {
  14. ONE_EDIT_AT_A_TIME = "old"
  15. };
  16. -- Table for event indexed chatFilters.
  17. -- Format ["CHAT_MSG_SYSTEM"] = { function1, function2, function3 }
  18. -- filter, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11 = function1 (self, event, ...) if filter then return true end return false, ... end
  19. local chatFilters = {};
  20. -- These hash tables are to improve performance of common lookups
  21. -- if you change what these tables point to (ie slash command, emote, chat)
  22. -- then you need to invalidate the entry in the hash table
  23. local hash_SecureCmdList = {}
  24. --Note: These need to remain global for AddOns
  25. hash_SlashCmdList = {} --[localizedCommand] -> function
  26. hash_EmoteTokenList = {}
  27. hash_ChatTypeInfoList = {} --[localizedCommand] -> identifier (Stores all slash commands)
  28. ChatTypeInfo = { };
  29. ChatTypeInfo["SYSTEM"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  30. ChatTypeInfo["SAY"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  31. ChatTypeInfo["PARTY"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  32. ChatTypeInfo["RAID"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  33. ChatTypeInfo["GUILD"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  34. ChatTypeInfo["OFFICER"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  35. ChatTypeInfo["YELL"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  36. ChatTypeInfo["WHISPER"] = { sticky = 1, flashTab = true, flashTabOnGeneral = true };
  37. ChatTypeInfo["SMART_WHISPER"] = ChatTypeInfo["WHISPER"];
  38. ChatTypeInfo["WHISPER_INFORM"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  39. ChatTypeInfo["REPLY"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  40. ChatTypeInfo["EMOTE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  41. ChatTypeInfo["TEXT_EMOTE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  42. ChatTypeInfo["MONSTER_SAY"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  43. ChatTypeInfo["MONSTER_PARTY"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  44. ChatTypeInfo["MONSTER_YELL"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  45. ChatTypeInfo["MONSTER_WHISPER"] = { sticky = 0, flashTab = true, flashTabOnGeneral = true };
  46. ChatTypeInfo["MONSTER_EMOTE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  47. ChatTypeInfo["CHANNEL"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  48. ChatTypeInfo["CHANNEL_JOIN"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  49. ChatTypeInfo["CHANNEL_LEAVE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  50. ChatTypeInfo["CHANNEL_LIST"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  51. ChatTypeInfo["CHANNEL_NOTICE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  52. ChatTypeInfo["CHANNEL_NOTICE_USER"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  53. ChatTypeInfo["TARGETICONS"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  54. ChatTypeInfo["AFK"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  55. ChatTypeInfo["DND"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  56. ChatTypeInfo["IGNORED"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  57. ChatTypeInfo["SKILL"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  58. ChatTypeInfo["LOOT"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  59. ChatTypeInfo["CURRENCY"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  60. ChatTypeInfo["MONEY"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  61. ChatTypeInfo["OPENING"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  62. ChatTypeInfo["TRADESKILLS"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  63. ChatTypeInfo["PET_INFO"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  64. ChatTypeInfo["COMBAT_MISC_INFO"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  65. ChatTypeInfo["COMBAT_XP_GAIN"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  66. ChatTypeInfo["COMBAT_HONOR_GAIN"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  67. ChatTypeInfo["COMBAT_FACTION_CHANGE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  68. ChatTypeInfo["BG_SYSTEM_NEUTRAL"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  69. ChatTypeInfo["BG_SYSTEM_ALLIANCE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  70. ChatTypeInfo["BG_SYSTEM_HORDE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  71. ChatTypeInfo["RAID_LEADER"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  72. ChatTypeInfo["RAID_WARNING"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  73. ChatTypeInfo["RAID_BOSS_WHISPER"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  74. ChatTypeInfo["RAID_BOSS_EMOTE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  75. ChatTypeInfo["QUEST_BOSS_EMOTE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  76. ChatTypeInfo["FILTERED"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  77. ChatTypeInfo["INSTANCE_CHAT"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  78. ChatTypeInfo["INSTANCE_CHAT_LEADER"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  79. ChatTypeInfo["RESTRICTED"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  80. ChatTypeInfo["CHANNEL1"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  81. ChatTypeInfo["CHANNEL2"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  82. ChatTypeInfo["CHANNEL3"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  83. ChatTypeInfo["CHANNEL4"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  84. ChatTypeInfo["CHANNEL5"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  85. ChatTypeInfo["CHANNEL6"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  86. ChatTypeInfo["CHANNEL7"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  87. ChatTypeInfo["CHANNEL8"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  88. ChatTypeInfo["CHANNEL9"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  89. ChatTypeInfo["CHANNEL10"] = { sticky = 1, flashTab = false, flashTabOnGeneral = false };
  90. ChatTypeInfo["ACHIEVEMENT"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  91. ChatTypeInfo["GUILD_ACHIEVEMENT"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  92. ChatTypeInfo["PARTY_LEADER"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  93. ChatTypeInfo["BN_WHISPER"] = { sticky = 1, flashTab = true, flashTabOnGeneral = true };
  94. ChatTypeInfo["BN_WHISPER_INFORM"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  95. ChatTypeInfo["BN_CONVERSATION"] = { sticky = 1, flashTab = true, flashTabOnGeneral = false };
  96. ChatTypeInfo["BN_CONVERSATION_NOTICE"] = { sticky = 0, flashTab = true, flashTabOnGeneral = false };
  97. ChatTypeInfo["BN_CONVERSATION_LIST"] = { sticky = 0, flashTab = true, flashTabOnGeneral = false };
  98. ChatTypeInfo["BN_ALERT"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  99. ChatTypeInfo["BN_BROADCAST"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  100. ChatTypeInfo["BN_BROADCAST_INFORM"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  101. ChatTypeInfo["BN_INLINE_TOAST_ALERT"] = { sticky = 0, flashTab = true, flashTabOnGeneral = false };
  102. ChatTypeInfo["BN_INLINE_TOAST_BROADCAST"] = { sticky = 0, flashTab = true, flashTabOnGeneral = false };
  103. ChatTypeInfo["BN_INLINE_TOAST_BROADCAST_INFORM"] = { sticky = 0, flashTab = true, flashTabOnGeneral = false };
  104. ChatTypeInfo["BN_INLINE_TOAST_CONVERSATION"] = { sticky = 0, flashTab = true, flashTabOnGeneral = false };
  105. ChatTypeInfo["BN_WHISPER_PLAYER_OFFLINE"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  106. ChatTypeInfo["COMBAT_GUILD_XP_GAIN"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  107. ChatTypeInfo["PET_BATTLE_COMBAT_LOG"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  108. ChatTypeInfo["PET_BATTLE_INFO"] = { sticky = 0, flashTab = false, flashTabOnGeneral = false };
  109. --NEW_CHAT_TYPE -Add the info here.
  110. ChatTypeGroup = {};
  111. ChatTypeGroup["SYSTEM"] = {
  112. "CHAT_MSG_SYSTEM",
  113. "TIME_PLAYED_MSG",
  114. "PLAYER_LEVEL_UP",
  115. "UNIT_LEVEL",
  116. "CHARACTER_POINTS_CHANGED",
  117. "CHAT_MSG_BN_WHISPER_PLAYER_OFFLINE",
  118. };
  119. ChatTypeGroup["SAY"] = {
  120. "CHAT_MSG_SAY",
  121. };
  122. ChatTypeGroup["EMOTE"] = {
  123. "CHAT_MSG_EMOTE",
  124. "CHAT_MSG_TEXT_EMOTE",
  125. };
  126. ChatTypeGroup["YELL"] = {
  127. "CHAT_MSG_YELL",
  128. };
  129. ChatTypeGroup["WHISPER"] = {
  130. "CHAT_MSG_WHISPER",
  131. "CHAT_MSG_WHISPER_INFORM",
  132. "CHAT_MSG_AFK",
  133. "CHAT_MSG_DND",
  134. };
  135. ChatTypeGroup["PARTY"] = {
  136. "CHAT_MSG_PARTY",
  137. "CHAT_MSG_MONSTER_PARTY",
  138. };
  139. ChatTypeGroup["PARTY_LEADER"] = {
  140. "CHAT_MSG_PARTY_LEADER",
  141. };
  142. ChatTypeGroup["RAID"] = {
  143. "CHAT_MSG_RAID",
  144. };
  145. ChatTypeGroup["RAID_LEADER"] = {
  146. "CHAT_MSG_RAID_LEADER",
  147. };
  148. ChatTypeGroup["RAID_WARNING"] = {
  149. "CHAT_MSG_RAID_WARNING",
  150. };
  151. ChatTypeGroup["INSTANCE_CHAT"] = {
  152. "CHAT_MSG_INSTANCE_CHAT",
  153. };
  154. ChatTypeGroup["INSTANCE_CHAT_LEADER"] = {
  155. "CHAT_MSG_INSTANCE_CHAT_LEADER",
  156. };
  157. ChatTypeGroup["GUILD"] = {
  158. "CHAT_MSG_GUILD",
  159. "GUILD_MOTD",
  160. "UNIT_GUILD_LEVEL",
  161. };
  162. ChatTypeGroup["OFFICER"] = {
  163. "CHAT_MSG_OFFICER",
  164. };
  165. ChatTypeGroup["MONSTER_SAY"] = {
  166. "CHAT_MSG_MONSTER_SAY",
  167. };
  168. ChatTypeGroup["MONSTER_YELL"] = {
  169. "CHAT_MSG_MONSTER_YELL",
  170. };
  171. ChatTypeGroup["MONSTER_EMOTE"] = {
  172. "CHAT_MSG_MONSTER_EMOTE",
  173. };
  174. ChatTypeGroup["MONSTER_WHISPER"] = {
  175. "CHAT_MSG_MONSTER_WHISPER",
  176. };
  177. ChatTypeGroup["MONSTER_BOSS_EMOTE"] = {
  178. "CHAT_MSG_RAID_BOSS_EMOTE",
  179. };
  180. ChatTypeGroup["MONSTER_BOSS_WHISPER"] = {
  181. "CHAT_MSG_RAID_BOSS_WHISPER",
  182. };
  183. ChatTypeGroup["ERRORS"] = {
  184. "CHAT_MSG_RESTRICTED",
  185. "CHAT_MSG_FILTERED",
  186. };
  187. ChatTypeGroup["AFK"] = {
  188. "CHAT_MSG_AFK",
  189. };
  190. ChatTypeGroup["DND"] = {
  191. "CHAT_MSG_DND",
  192. };
  193. ChatTypeGroup["IGNORED"] = {
  194. "CHAT_MSG_IGNORED",
  195. };
  196. ChatTypeGroup["BG_HORDE"] = {
  197. "CHAT_MSG_BG_SYSTEM_HORDE",
  198. };
  199. ChatTypeGroup["BG_ALLIANCE"] = {
  200. "CHAT_MSG_BG_SYSTEM_ALLIANCE",
  201. };
  202. ChatTypeGroup["BG_NEUTRAL"] = {
  203. "CHAT_MSG_BG_SYSTEM_NEUTRAL",
  204. };
  205. ChatTypeGroup["COMBAT_XP_GAIN"] = {
  206. "CHAT_MSG_COMBAT_XP_GAIN";
  207. }
  208. ChatTypeGroup["COMBAT_HONOR_GAIN"] = {
  209. "CHAT_MSG_COMBAT_HONOR_GAIN";
  210. }
  211. ChatTypeGroup["COMBAT_FACTION_CHANGE"] = {
  212. "CHAT_MSG_COMBAT_FACTION_CHANGE";
  213. };
  214. ChatTypeGroup["SKILL"] = {
  215. "CHAT_MSG_SKILL",
  216. };
  217. ChatTypeGroup["LOOT"] = {
  218. "CHAT_MSG_LOOT",
  219. };
  220. ChatTypeGroup["CURRENCY"] = {
  221. "CHAT_MSG_CURRENCY",
  222. };
  223. ChatTypeGroup["MONEY"] = {
  224. "CHAT_MSG_MONEY",
  225. };
  226. ChatTypeGroup["OPENING"] = {
  227. "CHAT_MSG_OPENING";
  228. };
  229. ChatTypeGroup["TRADESKILLS"] = {
  230. "CHAT_MSG_TRADESKILLS";
  231. };
  232. ChatTypeGroup["PET_INFO"] = {
  233. "CHAT_MSG_PET_INFO";
  234. };
  235. ChatTypeGroup["COMBAT_MISC_INFO"] = {
  236. "CHAT_MSG_COMBAT_MISC_INFO";
  237. };
  238. ChatTypeGroup["ACHIEVEMENT"] = {
  239. "CHAT_MSG_ACHIEVEMENT";
  240. };
  241. ChatTypeGroup["GUILD_ACHIEVEMENT"] = {
  242. "CHAT_MSG_GUILD_ACHIEVEMENT";
  243. };
  244. ChatTypeGroup["CHANNEL"] = {
  245. "CHAT_MSG_CHANNEL_JOIN",
  246. "CHAT_MSG_CHANNEL_LEAVE",
  247. "CHAT_MSG_CHANNEL_NOTICE",
  248. "CHAT_MSG_CHANNEL_NOTICE_USER",
  249. "CHAT_MSG_CHANNEL_LIST",
  250. };
  251. ChatTypeGroup["TARGETICONS"] = {
  252. "CHAT_MSG_TARGETICONS"
  253. };
  254. ChatTypeGroup["BN_WHISPER"] = {
  255. "CHAT_MSG_BN_WHISPER",
  256. "CHAT_MSG_BN_WHISPER_INFORM",
  257. };
  258. ChatTypeGroup["BN_CONVERSATION"] = {
  259. "CHAT_MSG_BN_CONVERSATION",
  260. "CHAT_MSG_BN_CONVERSATION_NOTICE",
  261. "CHAT_MSG_BN_CONVERSATION_LIST",
  262. };
  263. ChatTypeGroup["BN_INLINE_TOAST_ALERT"] = {
  264. "CHAT_MSG_BN_INLINE_TOAST_ALERT",
  265. "CHAT_MSG_BN_INLINE_TOAST_BROADCAST",
  266. "CHAT_MSG_BN_INLINE_TOAST_BROADCAST_INFORM",
  267. "CHAT_MSG_BN_INLINE_TOAST_CONVERSATION",
  268. };
  269. ChatTypeGroup["COMBAT_GUILD_XP_GAIN"] = {
  270. "CHAT_MSG_COMBAT_GUILD_XP_GAIN",
  271. };
  272. ChatTypeGroup["PET_BATTLE_COMBAT_LOG"] = {
  273. "CHAT_MSG_PET_BATTLE_COMBAT_LOG",
  274. };
  275. ChatTypeGroup["PET_BATTLE_INFO"] = {
  276. "CHAT_MSG_PET_BATTLE_INFO",
  277. };
  278. --NEW_CHAT_TYPE - Add the chat type above.
  279. ChatTypeGroupInverted = {};
  280. for group, values in pairs(ChatTypeGroup) do
  281. for _, value in pairs(values) do
  282. ChatTypeGroupInverted[value] = group;
  283. end
  284. end
  285. CHAT_CATEGORY_LIST = {
  286. PARTY = { "PARTY_LEADER", "PARTY_GUIDE", "MONSTER_PARTY" },
  287. RAID = { "RAID_LEADER", "RAID_WARNING" },
  288. GUILD = { "GUILD_ACHIEVEMENT" },
  289. WHISPER = { "WHISPER_INFORM", "AFK", "DND" },
  290. CHANNEL = { "CHANNEL_JOIN", "CHANNEL_LEAVE", "CHANNEL_NOTICE", "CHANNEL_USER" },
  291. INSTANCE_CHAT = { "INSTANCE_CHAT_LEADER" },
  292. BN_WHISPER = { "BN_WHISPER_INFORM" },
  293. BN_CONVERSATION = { "BN_CONVERSATION_NOTICE", "BN_CONVERSATION_LIST" },
  294. };
  295. CHAT_INVERTED_CATEGORY_LIST = {};
  296. for category, sublist in pairs(CHAT_CATEGORY_LIST) do
  297. for _, item in pairs(sublist) do
  298. CHAT_INVERTED_CATEGORY_LIST[item] = category;
  299. end
  300. end
  301. function Chat_GetChatCategory(chatType)
  302. return CHAT_INVERTED_CATEGORY_LIST[chatType] or chatType;
  303. end
  304. -- list of text emotes that we want to show on the Emote submenu (these have anims)
  305. EmoteList = {
  306. "WAVE",
  307. "BOW",
  308. "DANCE",
  309. "APPLAUD",
  310. "BEG",
  311. "CHICKEN",
  312. "CRY",
  313. "EAT",
  314. "FLEX",
  315. "KISS",
  316. "LAUGH",
  317. "POINT",
  318. "ROAR",
  319. "RUDE",
  320. "SALUTE",
  321. "SHY",
  322. "TALK",
  323. "STAND",
  324. "SIT",
  325. "SLEEP",
  326. "KNEEL",
  327. };
  328. -- list of text emotes that we want to show on the Speech submenu (these have sounds)
  329. TextEmoteSpeechList = {
  330. "HELPME",
  331. "INCOMING",
  332. "CHARGE",
  333. "FLEE",
  334. "ATTACKMYTARGET",
  335. "OOM",
  336. "FOLLOW",
  337. "WAIT",
  338. "HEALME",
  339. "CHEER",
  340. "OPENFIRE",
  341. "RASP",
  342. "HELLO",
  343. "BYE",
  344. "NOD",
  345. "NO",
  346. "THANK",
  347. "WELCOME",
  348. "CONGRATULATE",
  349. "FLIRT",
  350. "JOKE",
  351. "TRAIN",
  352. };
  353. -- These are text emote tokens - add new ones at the bottom of the list!
  354. EMOTE1_TOKEN = "AGREE";
  355. EMOTE2_TOKEN = "AMAZE";
  356. EMOTE3_TOKEN = "ANGRY";
  357. EMOTE4_TOKEN = "APOLOGIZE";
  358. EMOTE5_TOKEN = "APPLAUD";
  359. EMOTE6_TOKEN = "BASHFUL";
  360. EMOTE7_TOKEN = "BECKON";
  361. EMOTE8_TOKEN = "BEG";
  362. EMOTE9_TOKEN = "BITE";
  363. EMOTE10_TOKEN = "BLEED";
  364. EMOTE11_TOKEN = "BLINK";
  365. EMOTE12_TOKEN = "BLUSH";
  366. EMOTE13_TOKEN = "BONK";
  367. EMOTE14_TOKEN = "BORED";
  368. EMOTE15_TOKEN = "BOUNCE";
  369. EMOTE16_TOKEN = "BRB";
  370. EMOTE17_TOKEN = "BOW";
  371. EMOTE18_TOKEN = "BURP";
  372. EMOTE19_TOKEN = "BYE";
  373. EMOTE20_TOKEN = "CACKLE";
  374. EMOTE21_TOKEN = "CHEER";
  375. EMOTE22_TOKEN = "CHICKEN";
  376. EMOTE23_TOKEN = "CHUCKLE";
  377. EMOTE24_TOKEN = "CLAP";
  378. EMOTE25_TOKEN = "CONFUSED";
  379. EMOTE26_TOKEN = "CONGRATULATE";
  380. EMOTE27_TOKEN = "UNUSED";
  381. EMOTE28_TOKEN = "COUGH";
  382. EMOTE29_TOKEN = "COWER";
  383. EMOTE30_TOKEN = "CRACK";
  384. EMOTE31_TOKEN = "CRINGE";
  385. EMOTE32_TOKEN = "CRY";
  386. EMOTE33_TOKEN = "CURIOUS";
  387. EMOTE34_TOKEN = "CURTSEY";
  388. EMOTE35_TOKEN = "DANCE";
  389. EMOTE36_TOKEN = "DRINK";
  390. EMOTE37_TOKEN = "DROOL";
  391. EMOTE38_TOKEN = "EAT";
  392. EMOTE39_TOKEN = "EYE";
  393. EMOTE40_TOKEN = "FART";
  394. EMOTE41_TOKEN = "FIDGET";
  395. EMOTE42_TOKEN = "FLEX";
  396. EMOTE43_TOKEN = "FROWN";
  397. EMOTE44_TOKEN = "GASP";
  398. EMOTE45_TOKEN = "GAZE";
  399. EMOTE46_TOKEN = "GIGGLE";
  400. EMOTE47_TOKEN = "GLARE";
  401. EMOTE48_TOKEN = "GLOAT";
  402. EMOTE49_TOKEN = "GREET";
  403. EMOTE50_TOKEN = "GRIN";
  404. EMOTE51_TOKEN = "GROAN";
  405. EMOTE52_TOKEN = "GROVEL";
  406. EMOTE53_TOKEN = "GUFFAW";
  407. EMOTE54_TOKEN = "HAIL";
  408. EMOTE55_TOKEN = "HAPPY";
  409. EMOTE56_TOKEN = "HELLO";
  410. EMOTE57_TOKEN = "HUG";
  411. EMOTE58_TOKEN = "HUNGRY";
  412. EMOTE59_TOKEN = "KISS";
  413. EMOTE60_TOKEN = "KNEEL";
  414. EMOTE61_TOKEN = "LAUGH";
  415. EMOTE62_TOKEN = "LAYDOWN";
  416. EMOTE63_TOKEN = "MASSAGE";
  417. EMOTE64_TOKEN = "MOAN";
  418. EMOTE65_TOKEN = "MOON";
  419. EMOTE66_TOKEN = "MOURN";
  420. EMOTE67_TOKEN = "NO";
  421. EMOTE68_TOKEN = "NOD";
  422. EMOTE69_TOKEN = "NOSEPICK";
  423. EMOTE70_TOKEN = "PANIC";
  424. EMOTE71_TOKEN = "PEER";
  425. EMOTE72_TOKEN = "PLEAD";
  426. EMOTE73_TOKEN = "POINT";
  427. EMOTE74_TOKEN = "POKE";
  428. EMOTE75_TOKEN = "PRAY";
  429. EMOTE76_TOKEN = "ROAR";
  430. EMOTE77_TOKEN = "ROFL";
  431. EMOTE78_TOKEN = "RUDE";
  432. EMOTE79_TOKEN = "SALUTE";
  433. EMOTE80_TOKEN = "SCRATCH";
  434. EMOTE81_TOKEN = "SEXY";
  435. EMOTE82_TOKEN = "SHAKE";
  436. EMOTE83_TOKEN = "SHOUT";
  437. EMOTE84_TOKEN = "SHRUG";
  438. EMOTE85_TOKEN = "SHY";
  439. EMOTE86_TOKEN = "SIGH";
  440. EMOTE87_TOKEN = "SIT";
  441. EMOTE88_TOKEN = "SLEEP";
  442. EMOTE89_TOKEN = "SNARL";
  443. EMOTE90_TOKEN = "SPIT";
  444. EMOTE91_TOKEN = "STARE";
  445. EMOTE92_TOKEN = "SURPRISED";
  446. EMOTE93_TOKEN = "SURRENDER";
  447. EMOTE94_TOKEN = "TALK";
  448. EMOTE95_TOKEN = "TALKEX";
  449. EMOTE96_TOKEN = "TALKQ";
  450. EMOTE97_TOKEN = "TAP";
  451. EMOTE98_TOKEN = "THANK";
  452. EMOTE99_TOKEN = "THREATEN";
  453. EMOTE100_TOKEN = "TIRED";
  454. EMOTE101_TOKEN = "VICTORY";
  455. EMOTE102_TOKEN = "WAVE";
  456. EMOTE103_TOKEN = "WELCOME";
  457. EMOTE104_TOKEN = "WHINE";
  458. EMOTE105_TOKEN = "WHISTLE";
  459. EMOTE106_TOKEN = "WORK";
  460. EMOTE107_TOKEN = "YAWN";
  461. EMOTE108_TOKEN = "BOGGLE";
  462. EMOTE109_TOKEN = "CALM";
  463. EMOTE110_TOKEN = "COLD";
  464. EMOTE111_TOKEN = "COMFORT";
  465. EMOTE112_TOKEN = "CUDDLE";
  466. EMOTE113_TOKEN = "DUCK";
  467. EMOTE114_TOKEN = "INSULT";
  468. EMOTE115_TOKEN = "INTRODUCE";
  469. EMOTE116_TOKEN = "JK";
  470. EMOTE117_TOKEN = "LICK";
  471. EMOTE118_TOKEN = "LISTEN";
  472. EMOTE119_TOKEN = "LOST";
  473. EMOTE120_TOKEN = "MOCK";
  474. EMOTE121_TOKEN = "PONDER";
  475. EMOTE122_TOKEN = "POUNCE";
  476. EMOTE123_TOKEN = "PRAISE";
  477. EMOTE124_TOKEN = "PURR";
  478. EMOTE125_TOKEN = "PUZZLE";
  479. EMOTE126_TOKEN = "RAISE";
  480. EMOTE127_TOKEN = "READY";
  481. EMOTE128_TOKEN = "SHIMMY";
  482. EMOTE129_TOKEN = "SHIVER";
  483. EMOTE130_TOKEN = "SHOO";
  484. EMOTE131_TOKEN = "SLAP";
  485. EMOTE132_TOKEN = "SMIRK";
  486. EMOTE133_TOKEN = "SNIFF";
  487. EMOTE134_TOKEN = "SNUB";
  488. EMOTE135_TOKEN = "SOOTHE";
  489. EMOTE136_TOKEN = "STINK";
  490. EMOTE137_TOKEN = "TAUNT";
  491. EMOTE138_TOKEN = "TEASE";
  492. EMOTE139_TOKEN = "THIRSTY";
  493. EMOTE140_TOKEN = "VETO";
  494. EMOTE141_TOKEN = "SNICKER";
  495. EMOTE142_TOKEN = "TICKLE";
  496. EMOTE143_TOKEN = "STAND";
  497. EMOTE144_TOKEN = "VIOLIN";
  498. EMOTE145_TOKEN = "SMILE";
  499. EMOTE146_TOKEN = "RASP";
  500. EMOTE147_TOKEN = "GROWL";
  501. EMOTE148_TOKEN = "BARK";
  502. EMOTE149_TOKEN = "PITY";
  503. EMOTE150_TOKEN = "SCARED";
  504. EMOTE151_TOKEN = "FLOP";
  505. EMOTE152_TOKEN = "LOVE";
  506. EMOTE153_TOKEN = "MOO";
  507. EMOTE154_TOKEN = "COMMEND";
  508. EMOTE155_TOKEN = "TRAIN";
  509. EMOTE156_TOKEN = "HELPME";
  510. EMOTE157_TOKEN = "INCOMING";
  511. EMOTE158_TOKEN = "OPENFIRE";
  512. EMOTE159_TOKEN = "CHARGE";
  513. EMOTE160_TOKEN = "FLEE";
  514. EMOTE161_TOKEN = "ATTACKMYTARGET";
  515. EMOTE162_TOKEN = "OOM";
  516. EMOTE163_TOKEN = "FOLLOW";
  517. EMOTE164_TOKEN = "WAIT";
  518. EMOTE165_TOKEN = "FLIRT";
  519. EMOTE166_TOKEN = "HEALME";
  520. EMOTE167_TOKEN = "JOKE";
  521. EMOTE168_TOKEN = "WINK";
  522. EMOTE169_TOKEN = "PAT";
  523. EMOTE170_TOKEN = "GOLFCLAP";
  524. EMOTE171_TOKEN = "MOUNTSPECIAL";
  525. EMOTE304_TOKEN = "INCOMING";
  526. EMOTE306_TOKEN = "FLEE";
  527. EMOTE368_TOKEN = "BLAME"
  528. EMOTE369_TOKEN = "BLANK"
  529. EMOTE370_TOKEN = "BRANDISH"
  530. EMOTE371_TOKEN = "BREATH"
  531. EMOTE372_TOKEN = "DISAGREE"
  532. EMOTE373_TOKEN = "DOUBT"
  533. EMOTE374_TOKEN = "EMBARRASS"
  534. EMOTE375_TOKEN = "ENCOURAGE"
  535. EMOTE376_TOKEN = "ENEMY"
  536. EMOTE377_TOKEN = "EYEBROW"
  537. EMOTE380_TOKEN = "HIGHFIVE"
  538. EMOTE381_TOKEN = "ABSENT"
  539. EMOTE382_TOKEN = "ARM"
  540. EMOTE383_TOKEN = "AWE"
  541. EMOTE384_TOKEN = "BACKPACK"
  542. EMOTE385_TOKEN = "BADFEELING"
  543. EMOTE386_TOKEN = "CHALLENGE"
  544. EMOTE387_TOKEN = "CHUG"
  545. EMOTE389_TOKEN = "DING"
  546. EMOTE390_TOKEN = "FACEPALM"
  547. EMOTE391_TOKEN = "FAINT"
  548. EMOTE392_TOKEN = "GO"
  549. EMOTE393_TOKEN = "GOING"
  550. EMOTE394_TOKEN = "GLOWER"
  551. EMOTE395_TOKEN = "HEADACHE"
  552. EMOTE396_TOKEN = "HICCUP"
  553. EMOTE398_TOKEN = "HISS"
  554. EMOTE399_TOKEN = "HOLDHAND"
  555. EMOTE401_TOKEN = "HURRY"
  556. EMOTE402_TOKEN = "IDEA"
  557. EMOTE403_TOKEN = "JEALOUS"
  558. EMOTE404_TOKEN = "LUCK"
  559. EMOTE405_TOKEN = "MAP"
  560. EMOTE406_TOKEN = "MERCY"
  561. EMOTE407_TOKEN = "MUTTER"
  562. EMOTE408_TOKEN = "NERVOUS"
  563. EMOTE409_TOKEN = "OFFER"
  564. EMOTE410_TOKEN = "PET"
  565. EMOTE411_TOKEN = "PINCH"
  566. EMOTE413_TOKEN = "PROUD"
  567. EMOTE414_TOKEN = "PROMISE"
  568. EMOTE415_TOKEN = "PULSE"
  569. EMOTE416_TOKEN = "PUNCH"
  570. EMOTE417_TOKEN = "POUT"
  571. EMOTE418_TOKEN = "REGRET"
  572. EMOTE420_TOKEN = "REVENGE"
  573. EMOTE421_TOKEN = "ROLLEYES"
  574. EMOTE422_TOKEN = "RUFFLE"
  575. EMOTE423_TOKEN = "SAD"
  576. EMOTE424_TOKEN = "SCOFF"
  577. EMOTE425_TOKEN = "SCOLD"
  578. EMOTE426_TOKEN = "SCOWL"
  579. EMOTE427_TOKEN = "SEARCH"
  580. EMOTE428_TOKEN = "SHAKEFIST"
  581. EMOTE429_TOKEN = "SHIFTY"
  582. EMOTE430_TOKEN = "SHUDDER"
  583. EMOTE431_TOKEN = "SIGNAL"
  584. EMOTE432_TOKEN = "SILENCE"
  585. EMOTE433_TOKEN = "SING"
  586. EMOTE434_TOKEN = "SMACK"
  587. EMOTE435_TOKEN = "SNEAK"
  588. EMOTE436_TOKEN = "SNEEZE"
  589. EMOTE437_TOKEN = "SNORT"
  590. EMOTE438_TOKEN = "SQUEAL"
  591. EMOTE440_TOKEN = "SUSPICIOUS"
  592. EMOTE441_TOKEN = "THINK"
  593. EMOTE442_TOKEN = "TRUCE"
  594. EMOTE443_TOKEN = "TWIDDLE"
  595. EMOTE444_TOKEN = "WARN"
  596. EMOTE445_TOKEN = "SNAP"
  597. EMOTE446_TOKEN = "CHARM"
  598. EMOTE447_TOKEN = "COVEREARS"
  599. EMOTE448_TOKEN = "CROSSARMS"
  600. EMOTE449_TOKEN = "LOOK"
  601. EMOTE450_TOKEN = "OBJECT"
  602. EMOTE451_TOKEN = "SWEAT"
  603. EMOTE452_TOKEN = "YW"
  604. EMOTE453_TOKEN = "READ"
  605. local MAXEMOTEINDEX = 453;
  606. ICON_LIST = {
  607. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_1:",
  608. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_2:",
  609. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_3:",
  610. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_4:",
  611. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_5:",
  612. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_6:",
  613. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_7:",
  614. "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_8:",
  615. }
  616. --Links tags from Global Strings to indicies for entries in ICON_LIST. This way addons can easily replace icons
  617. ICON_TAG_LIST =
  618. {
  619. [strlower(ICON_TAG_RAID_TARGET_STAR1)] = 1,
  620. [strlower(ICON_TAG_RAID_TARGET_STAR2)] = 1,
  621. [strlower(ICON_TAG_RAID_TARGET_CIRCLE1)] = 2,
  622. [strlower(ICON_TAG_RAID_TARGET_CIRCLE2)] = 2,
  623. [strlower(ICON_TAG_RAID_TARGET_DIAMOND1)] = 3,
  624. [strlower(ICON_TAG_RAID_TARGET_DIAMOND2)] = 3,
  625. [strlower(ICON_TAG_RAID_TARGET_TRIANGLE1)] = 4,
  626. [strlower(ICON_TAG_RAID_TARGET_TRIANGLE2)] = 4,
  627. [strlower(ICON_TAG_RAID_TARGET_MOON1)] = 5,
  628. [strlower(ICON_TAG_RAID_TARGET_MOON2)] = 5,
  629. [strlower(ICON_TAG_RAID_TARGET_SQUARE1)] = 6,
  630. [strlower(ICON_TAG_RAID_TARGET_SQUARE2)] = 6,
  631. [strlower(ICON_TAG_RAID_TARGET_CROSS1)] = 7,
  632. [strlower(ICON_TAG_RAID_TARGET_CROSS2)] = 7,
  633. [strlower(ICON_TAG_RAID_TARGET_SKULL1)] = 8,
  634. [strlower(ICON_TAG_RAID_TARGET_SKULL2)] = 8,
  635. [strlower(RAID_TARGET_1)] = 1,
  636. [strlower(RAID_TARGET_2)] = 2,
  637. [strlower(RAID_TARGET_3)] = 3,
  638. [strlower(RAID_TARGET_4)] = 4,
  639. [strlower(RAID_TARGET_5)] = 5,
  640. [strlower(RAID_TARGET_6)] = 6,
  641. [strlower(RAID_TARGET_7)] = 7,
  642. [strlower(RAID_TARGET_8)] = 8,
  643. }
  644. GROUP_TAG_LIST =
  645. {
  646. [strlower(GROUP1_CHAT_TAG1)] = 1,
  647. [strlower(GROUP1_CHAT_TAG2)] = 1,
  648. [strlower(GROUP2_CHAT_TAG1)] = 2,
  649. [strlower(GROUP2_CHAT_TAG2)] = 2,
  650. [strlower(GROUP3_CHAT_TAG1)] = 3,
  651. [strlower(GROUP3_CHAT_TAG2)] = 3,
  652. [strlower(GROUP4_CHAT_TAG1)] = 4,
  653. [strlower(GROUP4_CHAT_TAG2)] = 4,
  654. [strlower(GROUP5_CHAT_TAG1)] = 5,
  655. [strlower(GROUP5_CHAT_TAG2)] = 5,
  656. [strlower(GROUP6_CHAT_TAG1)] = 6,
  657. [strlower(GROUP6_CHAT_TAG2)] = 6,
  658. [strlower(GROUP7_CHAT_TAG1)] = 7,
  659. [strlower(GROUP7_CHAT_TAG2)] = 7,
  660. [strlower(GROUP8_CHAT_TAG1)] = 8,
  661. [strlower(GROUP8_CHAT_TAG2)] = 8,
  662. --Language independent:
  663. ["g1"] = 1;
  664. ["g2"] = 2;
  665. ["g3"] = 3;
  666. ["g4"] = 4;
  667. ["g5"] = 5;
  668. ["g6"] = 6;
  669. ["g7"] = 7;
  670. ["g8"] = 8;
  671. };
  672. GROUP_LANGUAGE_INDEPENDENT_STRINGS =
  673. {
  674. "g1",
  675. "g2",
  676. "g3",
  677. "g4",
  678. "g5",
  679. "g6",
  680. "g7",
  681. "g8",
  682. };
  683. -- Arena Team Helper Function
  684. function ArenaTeam_GetTeamSizeID(teamsizearg)
  685. local teamname, teamsize, id;
  686. for i=1, MAX_ARENA_TEAMS do
  687. teamname, teamsize = GetArenaTeam(i)
  688. if ( teamsizearg == teamsize ) then
  689. id = i;
  690. end
  691. end
  692. return id;
  693. end
  694. --
  695. -- CastSequence support
  696. --
  697. local CastSequenceManager;
  698. local CastSequenceTable = {};
  699. local CastSequenceFreeList = {};
  700. local function CreateCanonicalActions(entry, ...)
  701. entry.spells = {};
  702. entry.spellNames = {};
  703. entry.items = {};
  704. local count = 0;
  705. for i=1, select("#", ...) do
  706. local action = strlower(strtrim((select(i, ...))));
  707. if ( action and action ~="" ) then
  708. count = count + 1;
  709. if ( GetItemInfo(action) or select(3, SecureCmdItemParse(action)) ) then
  710. entry.items[count] = action;
  711. entry.spells[count] = strlower(GetItemSpell(action) or "");
  712. entry.spellNames[count] = entry.spells[count];
  713. else
  714. entry.spells[count] = action;
  715. entry.spellNames[count] = gsub(action, "!*(.*)", "%1");
  716. end
  717. end
  718. end
  719. end
  720. local function SetCastSequenceIndex(entry, index)
  721. entry.index = index;
  722. entry.pending = nil;
  723. end
  724. local function ResetCastSequence(sequence, entry)
  725. SetCastSequenceIndex(entry, 1);
  726. CastSequenceFreeList[sequence] = entry;
  727. CastSequenceTable[sequence] = nil;
  728. end
  729. local function SetNextCastSequence(sequence, entry)
  730. if ( entry.index == #entry.spells ) then
  731. ResetCastSequence(sequence, entry);
  732. else
  733. SetCastSequenceIndex(entry, entry.index + 1);
  734. end
  735. end
  736. local function CastSequenceManager_OnEvent(self, event, ...)
  737. -- Reset all sequences when the player dies
  738. if ( event == "PLAYER_DEAD" ) then
  739. for sequence, entry in pairs(CastSequenceTable) do
  740. ResetCastSequence(sequence, entry);
  741. end
  742. return;
  743. end
  744. -- Increment sequences for spells which succeed.
  745. if ( event == "UNIT_SPELLCAST_SENT" or
  746. event == "UNIT_SPELLCAST_SUCCEEDED" or
  747. event == "UNIT_SPELLCAST_INTERRUPTED" or
  748. event == "UNIT_SPELLCAST_FAILED" or
  749. event == "UNIT_SPELLCAST_FAILED_QUIET" ) then
  750. local unit, name, rank, castID, _;
  751. if ( event == "UNIT_SPELLCAST_SENT" ) then
  752. unit, name, rank, _, castID = ...;
  753. else
  754. unit, name, rank, castID = ...;
  755. end
  756. if ( not name ) then
  757. -- This was a server-side only spell affecting the player somehow, don't do anything with cast sequencing, just bail.
  758. return;
  759. end
  760. if ( unit == "player" or unit == "pet" ) then
  761. name, rank = strlower(name), strlower(rank);
  762. local nameplus = name.."()";
  763. local fullname = name.."("..rank..")";
  764. for sequence, entry in pairs(CastSequenceTable) do
  765. local entryName = entry.spellNames[entry.index];
  766. if ( entryName == name or entryName == nameplus or entryName == fullname ) then
  767. if ( event == "UNIT_SPELLCAST_SENT" ) then
  768. entry.pending = castID;
  769. elseif ( entry.pending == castID ) then
  770. entry.pending = nil;
  771. if ( event == "UNIT_SPELLCAST_SUCCEEDED" ) then
  772. SetNextCastSequence(sequence, entry);
  773. end
  774. end
  775. end
  776. end
  777. end
  778. return;
  779. end
  780. -- Handle reset events
  781. local reset = "";
  782. if ( event == "PLAYER_TARGET_CHANGED" ) then
  783. reset = "target";
  784. elseif ( event == "PLAYER_REGEN_ENABLED" ) then
  785. reset = "combat";
  786. end
  787. for sequence, entry in pairs(CastSequenceTable) do
  788. if ( strfind(entry.reset, reset, 1, true) ) then
  789. ResetCastSequence(sequence, entry);
  790. end
  791. end
  792. end
  793. local function CastSequenceManager_OnUpdate(self, elapsed)
  794. elapsed = self.elapsed + elapsed;
  795. if ( elapsed < 1 ) then
  796. self.elapsed = elapsed;
  797. return;
  798. end
  799. for sequence, entry in pairs(CastSequenceTable) do
  800. if ( entry.timeout ) then
  801. if ( elapsed >= entry.timeout ) then
  802. ResetCastSequence(sequence, entry);
  803. else
  804. entry.timeout = entry.timeout - elapsed;
  805. end
  806. end
  807. end
  808. self.elapsed = 0;
  809. end
  810. local function ExecuteCastSequence(sequence, target)
  811. if ( not CastSequenceManager ) then
  812. CastSequenceManager = CreateFrame("Frame");
  813. CastSequenceManager.elapsed = 0;
  814. CastSequenceManager:RegisterEvent("PLAYER_DEAD");
  815. CastSequenceManager:RegisterEvent("UNIT_SPELLCAST_SENT");
  816. CastSequenceManager:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
  817. CastSequenceManager:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED");
  818. CastSequenceManager:RegisterEvent("UNIT_SPELLCAST_FAILED");
  819. CastSequenceManager:RegisterEvent("UNIT_SPELLCAST_FAILED_QUIET");
  820. CastSequenceManager:RegisterEvent("PLAYER_TARGET_CHANGED");
  821. CastSequenceManager:RegisterEvent("PLAYER_REGEN_ENABLED");
  822. CastSequenceManager:SetScript("OnEvent", CastSequenceManager_OnEvent);
  823. CastSequenceManager:SetScript("OnUpdate", CastSequenceManager_OnUpdate);
  824. end
  825. local entry = CastSequenceTable[sequence];
  826. if ( not entry ) then
  827. entry = CastSequenceFreeList[sequence];
  828. if ( not entry ) then
  829. local reset, spells = strmatch(sequence, "^reset=([^%s]+)%s*(.*)");
  830. if ( not reset ) then
  831. spells = sequence;
  832. end
  833. entry = {};
  834. CreateCanonicalActions(entry, strsplit(",", spells));
  835. entry.reset = strlower(reset or "");
  836. end
  837. CastSequenceTable[sequence] = entry;
  838. entry.index = 1;
  839. end
  840. -- Don't do anything if this entry is still pending
  841. if ( entry.pending ) then
  842. return;
  843. end
  844. -- See if modified click restarts the sequence
  845. if ( (IsShiftKeyDown() and strfind(entry.reset, "shift", 1, true)) or
  846. (IsControlKeyDown() and strfind(entry.reset, "ctrl", 1, true)) or
  847. (IsAltKeyDown() and strfind(entry.reset, "alt", 1, true)) ) then
  848. SetCastSequenceIndex(entry, 1);
  849. end
  850. -- Reset the timeout each time the sequence is used
  851. local timeout = strmatch(entry.reset, "(%d+)");
  852. if ( timeout ) then
  853. entry.timeout = CastSequenceManager.elapsed + tonumber(timeout);
  854. end
  855. -- Execute the sequence!
  856. local item, spell = entry.items[entry.index], entry.spells[entry.index];
  857. if ( item ) then
  858. local name, bag, slot = SecureCmdItemParse(item);
  859. if ( slot ) then
  860. if ( name ) then
  861. spell = strlower(GetItemSpell(name) or "");
  862. else
  863. spell = "";
  864. end
  865. entry.spellNames[entry.index] = spell;
  866. end
  867. if ( IsEquippableItem(name) and not IsEquippedItem(name) ) then
  868. EquipItemByName(name);
  869. else
  870. SecureCmdUseItem(name, bag, slot, target);
  871. end
  872. else
  873. CastSpellByName(spell, target);
  874. end
  875. if ( spell == "" ) then
  876. SetNextCastSequence(sequence, entry);
  877. end
  878. end
  879. function QueryCastSequence(sequence)
  880. local index = 1;
  881. local item, spell;
  882. local entry = CastSequenceTable[sequence];
  883. if ( entry ) then
  884. if ( (IsShiftKeyDown() and strfind(entry.reset, "shift", 1, true)) or
  885. (IsControlKeyDown() and strfind(entry.reset, "ctrl", 1, true)) or
  886. (IsAltKeyDown() and strfind(entry.reset, "alt", 1, true)) ) then
  887. index = 1;
  888. else
  889. index = entry.index;
  890. end
  891. item, spell = entry.items[index], entry.spells[index];
  892. else
  893. entry = CastSequenceFreeList[sequence];
  894. if ( entry ) then
  895. item, spell = entry.items[index], entry.spells[index];
  896. else
  897. local reset, spells = strmatch(sequence, "^reset=([^%s]+)%s*(.*)");
  898. if ( not reset ) then
  899. spells = sequence;
  900. end
  901. local action = strlower(strtrim((strsplit(",", spells))));
  902. if ( GetItemInfo(action) or select(3, SecureCmdItemParse(action)) ) then
  903. item, spell = action, strlower(GetItemSpell(action) or "");
  904. else
  905. item, spell = nil, action;
  906. end
  907. end
  908. end
  909. if ( item ) then
  910. local name, bag, slot = SecureCmdItemParse(item);
  911. if ( slot ) then
  912. if ( name ) then
  913. spell = strlower(GetItemSpell(name) or "");
  914. else
  915. spell = "";
  916. end
  917. end
  918. end
  919. return index, item, spell;
  920. end
  921. local CastRandomManager;
  922. local CastRandomTable = {};
  923. local function CastRandomManager_OnEvent(self, event, ...)
  924. local unit, name, rank = ...;
  925. if ( not name ) then
  926. -- This was a server-side only spell affecting the player somehow, don't do anything with cast sequencing, just bail.
  927. return;
  928. end
  929. if ( unit == "player" ) then
  930. name, rank = strlower(name), strlower(rank);
  931. local nameplus = name.."()";
  932. local fullname = name.."("..rank..")";
  933. for sequence, entry in pairs(CastRandomTable) do
  934. if ( entry.pending and entry.value ) then
  935. local entryName = strlower(entry.value);
  936. if ( entryName == name or entryName == nameplus or entryName == fullname ) then
  937. entry.pending = nil;
  938. if ( event == "UNIT_SPELLCAST_SUCCEEDED" ) then
  939. entry.value = nil;
  940. end
  941. end
  942. end
  943. end
  944. end
  945. end
  946. local function ExecuteCastRandom(actions)
  947. if ( not CastRandomManager ) then
  948. CastRandomManager = CreateFrame("Frame");
  949. CastRandomManager:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED");
  950. CastRandomManager:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED");
  951. CastRandomManager:RegisterEvent("UNIT_SPELLCAST_FAILED");
  952. CastRandomManager:RegisterEvent("UNIT_SPELLCAST_FAILED_QUIET");
  953. CastRandomManager:SetScript("OnEvent", CastRandomManager_OnEvent);
  954. end
  955. local entry = CastRandomTable[actions];
  956. if ( not entry ) then
  957. entry = {};
  958. CreateCanonicalActions(entry, strsplit(",", actions));
  959. CastRandomTable[actions] = entry;
  960. end
  961. if ( not entry.value ) then
  962. entry.value = strtrim(GetRandomArgument(strsplit(",", actions)));
  963. end
  964. entry.pending = true;
  965. return entry.value;
  966. end
  967. function GetRandomArgument(...)
  968. return (select(random(select("#", ...)), ...));
  969. end
  970. -- Slash commands that are protected from tampering
  971. local SecureCmdList = { };
  972. function IsSecureCmd(command)
  973. command = strupper(command);
  974. -- first check the hash table
  975. if ( hash_SecureCmdList[command] ) then
  976. return true;
  977. end
  978. for index, value in pairs(SecureCmdList) do
  979. local i = 1;
  980. local cmdString = _G["SLASH_"..index..i];
  981. while ( cmdString ) do
  982. cmdString = strupper(cmdString);
  983. if ( cmdString == command ) then
  984. return true;
  985. end
  986. i = i + 1;
  987. cmdString = _G["SLASH_"..index..i];
  988. end
  989. end
  990. end
  991. function SecureCmdItemParse(item)
  992. if ( not item ) then
  993. return nil, nil, nil;
  994. end
  995. local bag, slot = strmatch(item, "^(%d+)%s+(%d+)$");
  996. if ( not bag ) then
  997. slot = strmatch(item, "^(%d+)$");
  998. end
  999. if ( bag ) then
  1000. item = GetContainerItemLink(bag, slot);
  1001. elseif ( slot ) then
  1002. item = GetInventoryItemLink("player", slot);
  1003. end
  1004. return item, bag, slot;
  1005. end
  1006. function SecureCmdUseItem(name, bag, slot, target)
  1007. if ( bag ) then
  1008. UseContainerItem(bag, slot, target);
  1009. elseif ( slot ) then
  1010. UseInventoryItem(slot, target);
  1011. else
  1012. UseItemByName(name, target);
  1013. end
  1014. end
  1015. SecureCmdList["STARTATTACK"] = function(msg)
  1016. local action, target = SecureCmdOptionParse(msg);
  1017. if ( action ) then
  1018. if ( not target or target == "target" ) then
  1019. target = action;
  1020. end
  1021. StartAttack(target);
  1022. end
  1023. end
  1024. SecureCmdList["STOPATTACK"] = function(msg)
  1025. if ( SecureCmdOptionParse(msg) ) then
  1026. StopAttack();
  1027. end
  1028. end
  1029. SecureCmdList["CAST"] = function(msg)
  1030. local action, target = SecureCmdOptionParse(msg);
  1031. if ( action ) then
  1032. local name, bag, slot = SecureCmdItemParse(action);
  1033. if ( slot or GetItemInfo(name) ) then
  1034. SecureCmdUseItem(name, bag, slot, target);
  1035. else
  1036. CastSpellByName(action, target);
  1037. end
  1038. end
  1039. end
  1040. SecureCmdList["USE"] = SecureCmdList["CAST"];
  1041. SecureCmdList["CASTRANDOM"] = function(msg)
  1042. local actions, target = SecureCmdOptionParse(msg);
  1043. if ( actions ) then
  1044. local action = ExecuteCastRandom(actions);
  1045. local name, bag, slot = SecureCmdItemParse(action);
  1046. if ( slot or GetItemInfo(name) ) then
  1047. SecureCmdUseItem(name, bag, slot, target);
  1048. else
  1049. CastSpellByName(action, target);
  1050. end
  1051. end
  1052. end
  1053. SecureCmdList["USERANDOM"] = SecureCmdList["CASTRANDOM"];
  1054. SecureCmdList["CASTSEQUENCE"] = function(msg)
  1055. local sequence, target = SecureCmdOptionParse(msg);
  1056. if ( sequence and sequence ~= "" ) then
  1057. ExecuteCastSequence(sequence, target);
  1058. end
  1059. end
  1060. SecureCmdList["STOPCASTING"] = function(msg)
  1061. if ( SecureCmdOptionParse(msg) ) then
  1062. SpellStopCasting();
  1063. end
  1064. end
  1065. SecureCmdList["STOPSPELLTARGET"] = function(msg)
  1066. if ( SecureCmdOptionParse(msg) ) then
  1067. SpellStopTargeting();
  1068. end
  1069. end
  1070. SecureCmdList["CANCELAURA"] = function(msg)
  1071. local spell = SecureCmdOptionParse(msg);
  1072. if ( spell ) then
  1073. local name, rank = strmatch(spell, "([^(]+)[(]([^)]+)[)]");
  1074. if ( not name ) then
  1075. name = spell;
  1076. end
  1077. CancelUnitBuff("player", name, rank);
  1078. end
  1079. end
  1080. SecureCmdList["CANCELFORM"] = function(msg)
  1081. if ( SecureCmdOptionParse(msg) ) then
  1082. CancelShapeshiftForm();
  1083. end
  1084. end
  1085. -- Allow friendly names for glyph slots (needs to be local)
  1086. local GLYPH_SLOTS = {
  1087. minor1 = GLYPH_ID_MINOR_1;
  1088. minor2 = GLYPH_ID_MINOR_2;
  1089. minor3 = GLYPH_ID_MINOR_3;
  1090. major1 = GLYPH_ID_MAJOR_1;
  1091. major2 = GLYPH_ID_MAJOR_2;
  1092. major3 = GLYPH_ID_MAJOR_3;
  1093. -- prime1 = GLYPH_ID_PRIME_1;
  1094. -- prime2 = GLYPH_ID_PRIME_2;
  1095. -- prime3 = GLYPH_ID_PRIME_3;
  1096. };
  1097. SecureCmdList["CASTGLYPH"] = function(msg)
  1098. local action = SecureCmdOptionParse(msg);
  1099. if ( action ) then
  1100. local glyph, slot = strmatch(action, "^(%S+)%s+(%S+)$");
  1101. slot = (slot and GLYPH_SLOTS[slot]) or tonumber(slot);
  1102. local glyphID = tonumber(glyph);
  1103. if ( glyphID and slot ) then
  1104. CastGlyphByID(glyphID, slot);
  1105. elseif ( glyph and slot ) then
  1106. CastGlyphByName(glyph, slot);
  1107. end
  1108. end
  1109. end
  1110. SecureCmdList["EQUIP"] = function(msg)
  1111. local item = SecureCmdOptionParse(msg);
  1112. if ( item ) then
  1113. EquipItemByName((SecureCmdItemParse(item)));
  1114. end
  1115. end
  1116. SecureCmdList["EQUIP_TO_SLOT"] = function(msg)
  1117. local action = SecureCmdOptionParse(msg);
  1118. if ( action ) then
  1119. local slot, item = strmatch(action, "^(%d+)%s+(.*)");
  1120. if ( item ) then
  1121. if ( PaperDoll_IsEquippedSlot(slot) ) then
  1122. EquipItemByName(SecureCmdItemParse(item), slot);
  1123. else
  1124. -- user specified a bad slot number (slot that you can't equip an item to)
  1125. ChatFrame_DisplayUsageError(format(ERROR_SLASH_EQUIP_TO_SLOT, EQUIPPED_FIRST, EQUIPPED_LAST));
  1126. end
  1127. elseif ( slot ) then
  1128. -- user specified a slot but not an item
  1129. ChatFrame_DisplayUsageError(format(ERROR_SLASH_EQUIP_TO_SLOT, EQUIPPED_FIRST, EQUIPPED_LAST));
  1130. end
  1131. end
  1132. end
  1133. SecureCmdList["CHANGEACTIONBAR"] = function(msg)
  1134. local page = SecureCmdOptionParse(msg);
  1135. if ( page and page ~= "" ) then
  1136. page = tonumber(page);
  1137. if (page and page >= 1 and page <= NUM_ACTIONBAR_PAGES) then
  1138. ChangeActionBarPage(page);
  1139. else
  1140. ChatFrame_DisplayUsageError(format(ERROR_SLASH_CHANGEACTIONBAR, 1, NUM_ACTIONBAR_PAGES));
  1141. end
  1142. end
  1143. end
  1144. SecureCmdList["SWAPACTIONBAR"] = function(msg)
  1145. local action = SecureCmdOptionParse(msg);
  1146. if ( action ) then
  1147. local a, b = strmatch(action, "(%d+)%s+(%d+)");
  1148. if ( a and b ) then
  1149. a = tonumber(a);
  1150. b = tonumber(b);
  1151. if ( ( a and a >= 1 and a <= NUM_ACTIONBAR_PAGES ) and ( b and b >= 1 and b <= NUM_ACTIONBAR_PAGES ) ) then
  1152. if ( GetActionBarPage() == a ) then
  1153. ChangeActionBarPage(b);
  1154. else
  1155. ChangeActionBarPage(a);
  1156. end
  1157. else
  1158. ChatFrame_DisplayUsageError(format(ERROR_SLASH_SWAPACTIONBAR, 1, NUM_ACTIONBAR_PAGES));
  1159. end
  1160. end
  1161. end
  1162. end
  1163. SecureCmdList["TARGET"] = function(msg)
  1164. local action, target = SecureCmdOptionParse(msg);
  1165. if ( action ) then
  1166. if ( not target or target == "target" ) then
  1167. target = action;
  1168. end
  1169. TargetUnit(target);
  1170. end
  1171. end
  1172. SecureCmdList["TARGET_EXACT"] = function(msg)
  1173. local action, target = SecureCmdOptionParse(msg);
  1174. if ( action ) then
  1175. if ( not target or target == "target" ) then
  1176. target = action;
  1177. end
  1178. TargetUnit(target, 1);
  1179. end
  1180. end
  1181. SecureCmdList["TARGET_NEAREST_ENEMY"] = function(msg)
  1182. local action = SecureCmdOptionParse(msg);
  1183. if ( action ) then
  1184. TargetNearestEnemy(action);
  1185. end
  1186. end
  1187. SecureCmdList["TARGET_NEAREST_ENEMY_PLAYER"] = function(msg)
  1188. local action = SecureCmdOptionParse(msg);
  1189. if ( action ) then
  1190. TargetNearestEnemyPlayer(action);
  1191. end
  1192. end
  1193. SecureCmdList["TARGET_NEAREST_FRIEND"] = function(msg)
  1194. local action = SecureCmdOptionParse(msg);
  1195. if ( action ) then
  1196. TargetNearestFriend(action);
  1197. end
  1198. end
  1199. SecureCmdList["TARGET_NEAREST_FRIEND_PLAYER"] = function(msg)
  1200. local action = SecureCmdOptionParse(msg);
  1201. if ( action ) then
  1202. TargetNearestFriendPlayer(action);
  1203. end
  1204. end
  1205. SecureCmdList["TARGET_NEAREST_PARTY"] = function(msg)
  1206. local action = SecureCmdOptionParse(msg);
  1207. if ( action ) then
  1208. TargetNearestPartyMember(action);
  1209. end
  1210. end
  1211. SecureCmdList["TARGET_NEAREST_RAID"] = function(msg)
  1212. local action = SecureCmdOptionParse(msg);
  1213. if ( action ) then
  1214. TargetNearestRaidMember(action);
  1215. end
  1216. end
  1217. SecureCmdList["CLEARTARGET"] = function(msg)
  1218. if ( SecureCmdOptionParse(msg) ) then
  1219. ClearTarget();
  1220. end
  1221. end
  1222. SecureCmdList["TARGET_LAST_TARGET"] = function(msg)
  1223. if ( SecureCmdOptionParse(msg) ) then
  1224. TargetLastTarget();
  1225. end
  1226. end
  1227. SecureCmdList["TARGET_LAST_ENEMY"] = function(msg)
  1228. local action = SecureCmdOptionParse(msg);
  1229. if ( action ) then
  1230. TargetLastEnemy(action);
  1231. end
  1232. end
  1233. SecureCmdList["TARGET_LAST_FRIEND"] = function(msg)
  1234. local action = SecureCmdOptionParse(msg);
  1235. if ( action ) then
  1236. TargetLastFriend(action);
  1237. end
  1238. end
  1239. SecureCmdList["ASSIST"] = function(msg)
  1240. if ( msg == "" ) then
  1241. AssistUnit();
  1242. else
  1243. local action, target = SecureCmdOptionParse(msg);
  1244. if ( action ) then
  1245. if ( not target ) then
  1246. target = action;
  1247. end
  1248. AssistUnit(target);
  1249. end
  1250. end
  1251. end
  1252. SecureCmdList["FOCUS"] = function(msg)
  1253. if ( msg == "" ) then
  1254. FocusUnit();
  1255. else
  1256. local action, target = SecureCmdOptionParse(msg);
  1257. if ( action ) then
  1258. if ( not target or target == "focus" ) then
  1259. target = action;
  1260. end
  1261. FocusUnit(target);
  1262. end
  1263. end
  1264. end
  1265. SecureCmdList["CLEARFOCUS"] = function(msg)
  1266. if ( SecureCmdOptionParse(msg) ) then
  1267. ClearFocus();
  1268. end
  1269. end
  1270. SecureCmdList["MAINTANKON"] = function(msg)
  1271. local action, target = SecureCmdOptionParse(msg);
  1272. if ( action ) then
  1273. if ( not target ) then
  1274. target = action;
  1275. end
  1276. if ( target == "" ) then
  1277. target = "target";
  1278. end
  1279. SetPartyAssignment("MAINTANK", target);
  1280. end
  1281. end
  1282. SecureCmdList["MAINTANKOFF"] = function(msg)
  1283. local action, target = SecureCmdOptionParse(msg);
  1284. if ( action ) then
  1285. if ( not target ) then
  1286. target = action;
  1287. end
  1288. if ( target == "" ) then
  1289. target = "target";
  1290. end
  1291. ClearPartyAssignment("MAINTANK", target);
  1292. end
  1293. end
  1294. SecureCmdList["MAINASSISTON"] = function(msg)
  1295. local action, target = SecureCmdOptionParse(msg);
  1296. if ( action ) then
  1297. if ( not target ) then
  1298. target = action;
  1299. end
  1300. if ( target == "" ) then
  1301. target = "target";
  1302. end
  1303. SetPartyAssignment("MAINASSIST", target);
  1304. end
  1305. end
  1306. SecureCmdList["MAINASSISTOFF"] = function(msg)
  1307. local action, target = SecureCmdOptionParse(msg);
  1308. if ( action ) then
  1309. if ( not target ) then
  1310. target = action;
  1311. end
  1312. if ( target == "" ) then
  1313. target = "target";
  1314. end
  1315. ClearPartyAssignment("MAINASSIST", target);
  1316. end
  1317. end
  1318. SecureCmdList["DUEL"] = function(msg)
  1319. StartDuel(msg)
  1320. end
  1321. SecureCmdList["DUEL_CANCEL"] = function(msg)
  1322. CancelDuel()
  1323. end
  1324. SecureCmdList["PET_ATTACK"] = function(msg)
  1325. local action, target = SecureCmdOptionParse(msg);
  1326. if ( action ) then
  1327. if ( not target or target == "pettarget" ) then
  1328. target = action;
  1329. end
  1330. PetAttack(target);
  1331. end
  1332. end
  1333. SecureCmdList["PET_FOLLOW"] = function(msg)
  1334. if ( SecureCmdOptionParse(msg) ) then
  1335. PetFollow();
  1336. end
  1337. end
  1338. SecureCmdList["PET_MOVE_TO"] = function(msg)
  1339. local action, target = SecureCmdOptionParse(msg);
  1340. if ( action ) then
  1341. PetMoveTo(target);
  1342. end
  1343. end
  1344. SecureCmdList["PET_STAY"] = function(msg)
  1345. if ( SecureCmdOptionParse(msg) ) then
  1346. PetWait();
  1347. end
  1348. end
  1349. SecureCmdList["PET_PASSIVE"] = function(msg)
  1350. if ( SecureCmdOptionParse(msg) ) then
  1351. PetPassiveMode();
  1352. end
  1353. end
  1354. SecureCmdList["PET_DEFENSIVE"] = function(msg)
  1355. if ( SecureCmdOptionParse(msg) ) then
  1356. PetDefensiveMode();
  1357. end
  1358. end
  1359. SecureCmdList["PET_AGGRESSIVE"] = function(msg)
  1360. if ( SecureCmdOptionParse(msg) ) then
  1361. PetAggressiveMode();
  1362. end
  1363. end
  1364. SecureCmdList["PET_ASSIST"] = function(msg)
  1365. if ( SecureCmdOptionParse(msg) ) then
  1366. PetAssistMode();
  1367. end
  1368. end
  1369. SecureCmdList["PET_AUTOCASTON"] = function(msg)
  1370. local spell = SecureCmdOptionParse(msg);
  1371. if ( spell ) then
  1372. EnableSpellAutocast(spell);
  1373. end
  1374. end
  1375. SecureCmdList["PET_AUTOCASTOFF"] = function(msg)
  1376. local spell = SecureCmdOptionParse(msg);
  1377. if ( spell ) then
  1378. DisableSpellAutocast(spell);
  1379. end
  1380. end
  1381. SecureCmdList["PET_AUTOCASTTOGGLE"] = function(msg)
  1382. local spell = SecureCmdOptionParse(msg);
  1383. if ( spell ) then
  1384. ToggleSpellAutocast(spell);
  1385. end
  1386. end
  1387. SecureCmdList["STOPMACRO"] = function(msg)
  1388. if ( SecureCmdOptionParse(msg) ) then
  1389. StopMacro();
  1390. end
  1391. end
  1392. SecureCmdList["CANCELQUEUEDSPELL"] = function(msg)
  1393. if ( SecureCmdOptionParse(msg) ) then
  1394. SpellCancelQueuedSpell();
  1395. end
  1396. end
  1397. SecureCmdList["CLICK"] = function(msg)
  1398. local action = SecureCmdOptionParse(msg);
  1399. if ( action and action ~= "" ) then
  1400. local name, mouseButton, down = strmatch(action, "([^%s]+)%s+([^%s]+)%s*(.*)");
  1401. if ( not name ) then
  1402. name = action;
  1403. end
  1404. local button = GetClickFrame(name);
  1405. if ( button and button:IsObjectType("Button") ) then
  1406. button:Click(mouseButton, down);
  1407. end
  1408. end
  1409. end
  1410. SecureCmdList["EQUIP_SET"] = function(msg)
  1411. local set = SecureCmdOptionParse(msg);
  1412. if ( set and set ~= "" ) then
  1413. EquipmentManager_EquipSet(set);
  1414. end
  1415. end
  1416. SecureCmdList["WORLD_MARKER"] = function(msg)
  1417. local marker = SecureCmdOptionParse(msg);
  1418. if ( tonumber(marker) ) then
  1419. PlaceRaidMarker(tonumber(marker));
  1420. end
  1421. end
  1422. SecureCmdList["CLEAR_WORLD_MARKER"] = function(msg)
  1423. local marker = SecureCmdOptionParse(msg);
  1424. if ( tonumber(marker) ) then
  1425. ClearRaidMarker(tonumber(marker));
  1426. elseif ( type(marker) == "string" and strtrim(strlower(marker)) == strlower(ALL) ) then
  1427. ClearRaidMarker(nil); --Clear all world markers.
  1428. end
  1429. end
  1430. SecureCmdList["SUMMON_BATTLE_PET"] = function(msg)
  1431. local pet = SecureCmdOptionParse(msg);
  1432. if ( type(pet) == "string" ) then
  1433. local _, petID = C_PetJournal.FindPetIDByName(string.trim(pet));
  1434. if ( petID ) then
  1435. C_PetJournal.SummonPetByGUID(petID);
  1436. else
  1437. C_PetJournal.SummonPetByGUID(pet);
  1438. end
  1439. end
  1440. end
  1441. SecureCmdList["RANDOMPET"] = function(msg)
  1442. if ( SecureCmdOptionParse(msg) ) then
  1443. C_PetJournal.SummonRandomPet(true);
  1444. end
  1445. end
  1446. SecureCmdList["RANDOMFAVORITEPET"] = function(msg)
  1447. if ( SecureCmdOptionParse(msg) ) then
  1448. C_PetJournal.SummonRandomPet(false);
  1449. end
  1450. end
  1451. SecureCmdList["DISMISSBATTLEPET"] = function(msg)
  1452. if ( SecureCmdOptionParse(msg) ) then
  1453. local petID = C_PetJournal.GetSummonedPetGUID();
  1454. if ( petID ) then
  1455. C_PetJournal.SummonPetByGUID(petID);
  1456. end
  1457. end
  1458. end
  1459. -- Pre-populate the secure command hash table
  1460. for index, value in pairs(SecureCmdList) do
  1461. local i = 1;
  1462. local cmdString = _G["SLASH_"..index..i];
  1463. while ( cmdString ) do
  1464. cmdString = strupper(cmdString);
  1465. hash_SecureCmdList[cmdString] = value; -- add to hash
  1466. i = i + 1;
  1467. cmdString = _G["SLASH_"..index..i];
  1468. end
  1469. end
  1470. -- Slash commands
  1471. SlashCmdList = { };
  1472. SlashCmdList["CONSOLE"] = function(msg)
  1473. ConsoleExec(msg);
  1474. end
  1475. SlashCmdList["CHATLOG"] = function(msg)
  1476. local info = ChatTypeInfo["SYSTEM"];
  1477. if ( LoggingChat() ) then
  1478. LoggingChat(false);
  1479. DEFAULT_CHAT_FRAME:AddMessage(CHATLOGDISABLED, info.r, info.g, info.b, info.id);
  1480. else
  1481. LoggingChat(true);
  1482. DEFAULT_CHAT_FRAME:AddMessage(CHATLOGENABLED, info.r, info.g, info.b, info.id);
  1483. end
  1484. end
  1485. SlashCmdList["COMBATLOG"] = function(msg)
  1486. local info = ChatTypeInfo["SYSTEM"];
  1487. if ( LoggingCombat() ) then
  1488. LoggingCombat(false);
  1489. DEFAULT_CHAT_FRAME:AddMessage(COMBATLOGDISABLED, info.r, info.g, info.b, info.id);
  1490. else
  1491. LoggingCombat(true);
  1492. DEFAULT_CHAT_FRAME:AddMessage(COMBATLOGENABLED, info.r, info.g, info.b, info.id);
  1493. end
  1494. end
  1495. SlashCmdList["INVITE"] = function(msg)
  1496. if(msg == "") then
  1497. msg = UnitName("target");
  1498. end
  1499. if( msg and (strlen(msg) > MAX_CHARACTER_NAME_BYTES) ) then
  1500. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1501. return;
  1502. end
  1503. InviteToGroup(msg);
  1504. end
  1505. SlashCmdList["UNINVITE"] = function(msg)
  1506. if(msg == "") then
  1507. msg = UnitName("target");
  1508. end
  1509. UninviteUnit(msg);
  1510. end
  1511. SlashCmdList["PROMOTE"] = function(msg)
  1512. PromoteToLeader(msg);
  1513. end
  1514. SlashCmdList["REPLY"] = function(msg, editBox)
  1515. local lastTell = ChatEdit_GetLastTellTarget();
  1516. if ( lastTell ) then
  1517. msg = SubstituteChatMessageBeforeSend(msg);
  1518. SendChatMessage(msg, "WHISPER", editBox.languageID, lastTell);
  1519. else
  1520. -- error message
  1521. end
  1522. end
  1523. SlashCmdList["HELP"] = function(msg)
  1524. ChatFrame_DisplayHelpText(DEFAULT_CHAT_FRAME);
  1525. end
  1526. SlashCmdList["MACROHELP"] = function(msg)
  1527. ChatFrame_DisplayMacroHelpText(DEFAULT_CHAT_FRAME);
  1528. end
  1529. SlashCmdList["TIME"] = function(msg)
  1530. ChatFrame_DisplayGameTime(DEFAULT_CHAT_FRAME);
  1531. end
  1532. SlashCmdList["PLAYED"] = function(msg)
  1533. RequestTimePlayed();
  1534. end
  1535. SlashCmdList["FOLLOW"] = function(msg)
  1536. FollowUnit(msg);
  1537. end
  1538. SlashCmdList["TRADE"] = function(msg)
  1539. InitiateTrade("target");
  1540. end
  1541. SlashCmdList["INSPECT"] = function(msg)
  1542. InspectUnit("target");
  1543. end
  1544. SlashCmdList["LOGOUT"] = function(msg)
  1545. Logout();
  1546. end
  1547. SlashCmdList["QUIT"] = function(msg)
  1548. Quit();
  1549. end
  1550. SlashCmdList["JOIN"] = function(msg)
  1551. local name = gsub(msg, "%s*([^%s]+).*", "%1");
  1552. local password = gsub(msg, "%s*([^%s]+)%s*(.*)", "%2");
  1553. if(strlen(name) <= 0) then
  1554. local joinhelp = CHAT_JOIN_HELP;
  1555. local info = ChatTypeInfo["SYSTEM"];
  1556. DEFAULT_CHAT_FRAME:AddMessage(joinhelp, info.r, info.g, info.b, info.id);
  1557. else
  1558. local zoneChannel, channelName = JoinPermanentChannel(name, password, DEFAULT_CHAT_FRAME:GetID(), 1);
  1559. if ( channelName ) then
  1560. name = channelName;
  1561. end
  1562. if ( not zoneChannel ) then
  1563. local info = ChatTypeInfo["CHANNEL"];
  1564. DEFAULT_CHAT_FRAME:AddMessage(CHAT_INVALID_NAME_NOTICE, info.r, info.g, info.b, info.id);
  1565. return;
  1566. end
  1567. local i = 1;
  1568. while ( DEFAULT_CHAT_FRAME.channelList[i] ) do
  1569. i = i + 1;
  1570. end
  1571. DEFAULT_CHAT_FRAME.channelList[i] = name;
  1572. DEFAULT_CHAT_FRAME.zoneChannelList[i] = zoneChannel;
  1573. end
  1574. end
  1575. SlashCmdList["LEAVE"] = function(msg)
  1576. local name = strmatch(msg, "%s*([^%s]+)");
  1577. if ( name ) then
  1578. local nameNum = tonumber(name);
  1579. if ( nameNum and nameNum > MAX_WOW_CHAT_CHANNELS ) then
  1580. BNLeaveConversation(nameNum - MAX_WOW_CHAT_CHANNELS);
  1581. else
  1582. LeaveChannelByName(name);
  1583. end
  1584. end
  1585. end
  1586. SlashCmdList["LIST_CHANNEL"] = function(msg)
  1587. local name = strmatch(msg, "%s*([^%s]+)");
  1588. if ( name ) then
  1589. local nameNum = tonumber(name);
  1590. if ( nameNum and nameNum > MAX_WOW_CHAT_CHANNELS ) then
  1591. BNListConversation(nameNum - MAX_WOW_CHAT_CHANNELS);
  1592. else
  1593. ListChannelByName(name);
  1594. end
  1595. else
  1596. ListChannels();
  1597. end
  1598. end
  1599. SlashCmdList["CHAT_HELP"] =
  1600. function(msg)
  1601. ChatFrame_DisplayChatHelp(DEFAULT_CHAT_FRAME)
  1602. end
  1603. SlashCmdList["CHAT_PASSWORD"] =
  1604. function(msg)
  1605. local name = gsub(msg, "%s*([^%s]+).*", "%1");
  1606. local password = gsub(msg, "%s*([^%s]+)%s*(.*)", "%2");
  1607. SetChannelPassword(name, password);
  1608. end
  1609. SlashCmdList["CHAT_OWNER"] =
  1610. function(msg)
  1611. local channel = gsub(msg, "%s*([^%s]+).*", "%1");
  1612. local newOwner = gsub(msg, "%s*([^%s]+)%s*(.*)", "%2");
  1613. if ( not channel or not newOwner ) then
  1614. return;
  1615. end
  1616. local newOwnerLen = strlen(newOwner);
  1617. if ( newOwnerLen > MAX_CHARACTER_NAME_BYTES ) then
  1618. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1619. return;
  1620. end
  1621. if ( strlen(channel) > 0 ) then
  1622. if ( newOwnerLen > 0 ) then
  1623. SetChannelOwner(channel, newOwner);
  1624. else
  1625. DisplayChannelOwner(channel);
  1626. end
  1627. end
  1628. end
  1629. SlashCmdList["CHAT_MODERATOR"] =
  1630. function(msg)
  1631. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1632. if ( not channel or not player ) then
  1633. return;
  1634. end
  1635. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1636. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1637. return;
  1638. end
  1639. ChannelModerator(channel, player);
  1640. end
  1641. SlashCmdList["CHAT_UNMODERATOR"] =
  1642. function(msg)
  1643. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1644. if ( not channel or not player ) then
  1645. return;
  1646. end
  1647. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1648. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1649. return;
  1650. end
  1651. if ( channel and player ) then
  1652. ChannelUnmoderator(channel, player);
  1653. end
  1654. end
  1655. SlashCmdList["CHAT_MUTE"] =
  1656. function(msg)
  1657. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1658. if ( not channel or not player ) then
  1659. return;
  1660. end
  1661. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1662. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1663. return;
  1664. end
  1665. if ( channel and player ) then
  1666. ChannelMute(channel, player);
  1667. end
  1668. end
  1669. SlashCmdList["CHAT_UNMUTE"] =
  1670. function(msg)
  1671. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1672. if ( not channel or not player ) then
  1673. return;
  1674. end
  1675. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1676. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1677. return;
  1678. end
  1679. if ( channel and player ) then
  1680. ChannelUnmute(channel, player);
  1681. end
  1682. end
  1683. SlashCmdList["CHAT_CINVITE"] =
  1684. function(msg)
  1685. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1686. if ( not channel or not player ) then
  1687. return;
  1688. end
  1689. if ( channel and player ) then
  1690. if ( tonumber(channel) and tonumber(channel) > MAX_WOW_CHAT_CHANNELS ) then
  1691. --We have a BNet conversation.
  1692. channel = tonumber(channel) - MAX_WOW_CHAT_CHANNELS;
  1693. if ( BNGetConversationInfo(channel) ) then
  1694. local presenceID = BNet_GetPresenceID(player);
  1695. if ( presenceID ) then
  1696. BNInviteToConversation(channel, presenceID);
  1697. end
  1698. end
  1699. else
  1700. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1701. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1702. return;
  1703. end
  1704. ChannelInvite(channel, player);
  1705. end
  1706. end
  1707. end
  1708. SlashCmdList["CHAT_KICK"] =
  1709. function(msg)
  1710. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1711. if ( not channel or not player ) then
  1712. return;
  1713. end
  1714. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1715. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1716. return;
  1717. end
  1718. if ( channel and player ) then
  1719. ChannelKick(channel, player);
  1720. end
  1721. end
  1722. SlashCmdList["CHAT_BAN"] =
  1723. function(msg)
  1724. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1725. if ( not channel or not player ) then
  1726. return;
  1727. end
  1728. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1729. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1730. return;
  1731. end
  1732. if ( channel and player ) then
  1733. ChannelBan(channel, player);
  1734. end
  1735. end
  1736. SlashCmdList["CHAT_UNBAN"] =
  1737. function(msg)
  1738. local channel, player = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1739. if ( not channel or not player ) then
  1740. return;
  1741. end
  1742. if ( strlen(player) > MAX_CHARACTER_NAME_BYTES ) then
  1743. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1744. return;
  1745. end
  1746. if ( channel and player ) then
  1747. ChannelUnban(channel, player);
  1748. end
  1749. end
  1750. SlashCmdList["CHAT_ANNOUNCE"] =
  1751. function(msg)
  1752. local channel = strmatch(msg, "%s*([^%s]+)");
  1753. if ( channel ) then
  1754. ChannelToggleAnnouncements(channel);
  1755. end
  1756. end
  1757. SlashCmdList["TEAM_INVITE"] = function(msg)
  1758. if ( msg ~= "" ) then
  1759. local team, name = strmatch(msg, "^(%d+)[%w+%d+]*%s+(.*)");
  1760. if ( team and name ) then
  1761. if ( strlen(name) > MAX_CHARACTER_NAME_BYTES ) then
  1762. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1763. return;
  1764. end
  1765. team = tonumber(team);
  1766. if ( team ) then
  1767. local teamsizeID = ArenaTeam_GetTeamSizeID(team);
  1768. if ( teamsizeID ) then
  1769. ArenaTeamInviteByName(teamsizeID, name);
  1770. end
  1771. return;
  1772. end
  1773. end
  1774. end
  1775. ChatFrame_DisplayUsageError(ERROR_SLASH_TEAM_INVITE);
  1776. end
  1777. SlashCmdList["TEAM_QUIT"] = function(msg)
  1778. if ( msg ~= "" ) then
  1779. local team = strmatch(msg, "^(%d+)[%w+%d+]*");
  1780. if ( team ) then
  1781. team = tonumber(team);
  1782. if ( team ) then
  1783. local teamsizeID = ArenaTeam_GetTeamSizeID(team);
  1784. if ( teamsizeID ) then
  1785. ArenaTeamLeave(teamsizeID);
  1786. end
  1787. return;
  1788. end
  1789. end
  1790. end
  1791. ChatFrame_DisplayUsageError(ERROR_SLASH_TEAM_QUIT);
  1792. end
  1793. SlashCmdList["TEAM_UNINVITE"] = function(msg)
  1794. if ( msg ~= "" ) then
  1795. local team, name = strmatch(msg, "^(%d+)[%w+%d+]*%s+(.*)");
  1796. if ( team and name ) then
  1797. if ( strlen(name) > MAX_CHARACTER_NAME_BYTES ) then
  1798. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1799. return;
  1800. end
  1801. team = tonumber(team);
  1802. if ( team ) then
  1803. local teamsizeID = ArenaTeam_GetTeamSizeID(team);
  1804. if ( teamsizeID ) then
  1805. ArenaTeamUninviteByName(teamsizeID, name);
  1806. end
  1807. return;
  1808. end
  1809. end
  1810. end
  1811. ChatFrame_DisplayUsageError(ERROR_SLASH_TEAM_UNINVITE);
  1812. end
  1813. SlashCmdList["TEAM_CAPTAIN"] = function(msg)
  1814. if ( msg ~= "" ) then
  1815. local team, name = strmatch(msg, "^(%d+)[%w+%d+]*%s+(.*)");
  1816. if ( team and name ) then
  1817. if ( strlen(name) > MAX_CHARACTER_NAME_BYTES ) then
  1818. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1819. return;
  1820. end
  1821. team = tonumber(team);
  1822. if ( team ) then
  1823. local teamsizeID = ArenaTeam_GetTeamSizeID(team);
  1824. if ( teamsizeID ) then
  1825. ArenaTeamSetLeaderByName(teamsizeID, name);
  1826. end
  1827. return;
  1828. end
  1829. end
  1830. end
  1831. ChatFrame_DisplayUsageError(ERROR_SLASH_TEAM_CAPTAIN);
  1832. end
  1833. SlashCmdList["TEAM_DISBAND"] = function(msg)
  1834. if ( msg ~= "" ) then
  1835. local team = strmatch(msg, "^(%d+)[%w+%d+]*");
  1836. if ( team ) then
  1837. team = tonumber(team);
  1838. if ( team ) then
  1839. local teamsizeID = ArenaTeam_GetTeamSizeID(team);
  1840. if ( teamsizeID ) then
  1841. local teamName, teamSize = GetArenaTeam(teamsizeID);
  1842. for i = 1, teamSize * 2 do
  1843. local name, rank = GetArenaTeamRosterInfo(teamsizeID, i);
  1844. if ( rank == 0 ) then
  1845. if ( name == UnitName("player") ) then
  1846. local dialog = StaticPopup_Show("CONFIRM_TEAM_DISBAND", teamName);
  1847. if ( dialog ) then
  1848. dialog.data = teamsizeID;
  1849. end
  1850. end
  1851. break;
  1852. end
  1853. end
  1854. end
  1855. return;
  1856. end
  1857. end
  1858. end
  1859. ChatFrame_DisplayUsageError(ERROR_SLASH_TEAM_DISBAND);
  1860. end
  1861. SlashCmdList["GUILD_INVITE"] = function(msg)
  1862. if(msg == "") then
  1863. msg = UnitName("target");
  1864. end
  1865. if( msg and (strlen(msg) > MAX_CHARACTER_NAME_BYTES) ) then
  1866. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1867. return;
  1868. end
  1869. GuildInvite(msg);
  1870. end
  1871. SlashCmdList["GUILD_UNINVITE"] = function(msg)
  1872. if(msg == "") then
  1873. msg = UnitName("target");
  1874. end
  1875. if( msg and (strlen(msg) > MAX_CHARACTER_NAME_BYTES) ) then
  1876. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1877. return;
  1878. end
  1879. GuildUninvite(msg);
  1880. end
  1881. SlashCmdList["GUILD_PROMOTE"] = function(msg)
  1882. if( msg and (strlen(msg) > MAX_CHARACTER_NAME_BYTES) ) then
  1883. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1884. return;
  1885. end
  1886. GuildPromote(msg);
  1887. end
  1888. SlashCmdList["GUILD_DEMOTE"] = function(msg)
  1889. if( msg and (strlen(msg) > MAX_CHARACTER_NAME_BYTES) ) then
  1890. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1891. return;
  1892. end
  1893. GuildDemote(msg);
  1894. end
  1895. SlashCmdList["GUILD_LEADER"] = function(msg)
  1896. if( msg and (strlen(msg) > MAX_CHARACTER_NAME_BYTES) ) then
  1897. ChatFrame_DisplayUsageError(ERR_NAME_TOO_LONG2);
  1898. return;
  1899. end
  1900. GuildSetLeader(msg);
  1901. end
  1902. SlashCmdList["GUILD_MOTD"] = function(msg)
  1903. GuildSetMOTD(msg)
  1904. end
  1905. SlashCmdList["GUILD_LEAVE"] = function(msg)
  1906. GuildLeave();
  1907. end
  1908. SlashCmdList["GUILD_DISBAND"] = function(msg)
  1909. if ( IsGuildLeader() ) then
  1910. StaticPopup_Show("CONFIRM_GUILD_DISBAND");
  1911. end
  1912. end
  1913. SlashCmdList["GUILD_INFO"] = function(msg)
  1914. GuildInfo();
  1915. end
  1916. SlashCmdList["GUILD_ROSTER"] = function(msg)
  1917. if ( IsInGuild() ) then
  1918. GuildFrame_LoadUI();
  1919. if ( GuildFrame ) then
  1920. GuildFrameTab2:Click();
  1921. ShowUIPanel(GuildFrame);
  1922. end
  1923. end
  1924. end
  1925. --SlashCmdList["GUILD_HELP"] = function(msg)
  1926. -- ChatFrame_DisplayGuildHelp(DEFAULT_CHAT_FRAME);
  1927. --end
  1928. SlashCmdList["CHAT_AFK"] = function(msg)
  1929. SendChatMessage(msg, "AFK");
  1930. end
  1931. SlashCmdList["CHAT_DND"] = function(msg)
  1932. SendChatMessage(msg, "DND");
  1933. end
  1934. SlashCmdList["WHO"] = function(msg)
  1935. if ( msg == "" ) then
  1936. msg = WhoFrame_GetDefaultWhoCommand();
  1937. ShowWhoPanel();
  1938. end
  1939. WhoFrameEditBox:SetText(msg);
  1940. SendWho(msg);
  1941. end
  1942. SlashCmdList["CHANNEL"] = function(msg, editBox)
  1943. msg = SubstituteChatMessageBeforeSend(msg);
  1944. SendChatMessage(msg, "CHANNEL", editBox.languageID, editBox:GetAttribute("channelTarget"));
  1945. end
  1946. SlashCmdList["FRIENDS"] = function(msg)
  1947. local player, note = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  1948. if ( player ~= "" or UnitIsPlayer("target") ) then
  1949. AddOrRemoveFriend(player, note);
  1950. else
  1951. ToggleFriendsPanel();
  1952. end
  1953. end
  1954. SlashCmdList["REMOVEFRIEND"] = function(msg)
  1955. RemoveFriend(msg);
  1956. end
  1957. SlashCmdList["IGNORE"] = function(msg)
  1958. if ( msg ~= "" or UnitIsPlayer("target") ) then
  1959. local presenceID = BNet_GetPresenceID(msg);
  1960. if ( presenceID ) then
  1961. if ( BNIsFriend(presenceID) ) then
  1962. SendSystemMessage(ERR_CANNOT_IGNORE_BN_FRIEND);
  1963. else
  1964. BNSetToonBlocked(presenceID, not BNIsToonBlocked(presenceID));
  1965. end
  1966. else
  1967. AddOrDelIgnore(msg);
  1968. end
  1969. else
  1970. ToggleIgnorePanel();
  1971. end
  1972. end
  1973. SlashCmdList["UNIGNORE"] = function(msg)
  1974. if ( msg ~= "" or UnitIsPlayer("target") ) then
  1975. DelIgnore(msg);
  1976. else
  1977. ToggleIgnorePanel();
  1978. end
  1979. end
  1980. SlashCmdList["SCRIPT"] = function(msg)
  1981. RunScript(msg);
  1982. end
  1983. SlashCmdList["LOOT_FFA"] = function(msg)
  1984. SetLootMethod("freeforall");
  1985. end
  1986. SlashCmdList["LOOT_ROUNDROBIN"] = function(msg)
  1987. SetLootMethod("roundrobin");
  1988. end
  1989. SlashCmdList["LOOT_MASTER"] = function(msg)
  1990. SetLootMethod("master", msg);
  1991. end
  1992. SlashCmdList["LOOT_GROUP"] = function(msg)
  1993. SetLootMethod("group");
  1994. end
  1995. SlashCmdList["LOOT_NEEDBEFOREGREED"] = function(msg)
  1996. SetLootMethod("needbeforegreed");
  1997. end
  1998. SlashCmdList["LOOT_SETTHRESHOLD"] = function(msg)
  1999. if ( not msg ) then
  2000. local info = ChatTypeInfo["SYSTEM"];
  2001. DEFAULT_CHAT_FRAME:AddMessage(format(ERROR_SLASH_LOOT_SETTHRESHOLD, MIN_LOOT_THRESHOLD, MAX_LOOT_THRESHOLD), info.r, info.g, info.b, info.id);
  2002. return;
  2003. end
  2004. local MIN_LOOT_THRESHOLD = 2; -- "good" item quality
  2005. local MAX_LOOT_THRESHOLD = 6; -- "artifact" item quality
  2006. local threshold = strmatch(msg, "(%d+)");
  2007. threshold = tonumber(threshold);
  2008. if ( threshold and threshold >= MIN_LOOT_THRESHOLD and threshold <= MAX_LOOT_THRESHOLD ) then
  2009. -- try to match a threshold number first
  2010. SetLootThreshold(threshold);
  2011. else
  2012. msg = strupper(msg);
  2013. if ( msg == strupper(ITEM_QUALITY2_DESC) ) then
  2014. SetLootThreshold(2);
  2015. elseif ( msg == strupper(ITEM_QUALITY3_DESC) ) then
  2016. SetLootThreshold(3);
  2017. elseif ( msg == strupper(ITEM_QUALITY4_DESC) ) then
  2018. SetLootThreshold(4);
  2019. elseif ( msg == strupper(ITEM_QUALITY5_DESC) ) then
  2020. SetLootThreshold(5);
  2021. elseif ( msg == strupper(ITEM_QUALITY6_DESC) ) then
  2022. SetLootThreshold(6);
  2023. else
  2024. -- no matches found
  2025. local info = ChatTypeInfo["SYSTEM"];
  2026. DEFAULT_CHAT_FRAME:AddMessage(format(ERROR_SLASH_LOOT_SETTHRESHOLD, MIN_LOOT_THRESHOLD, MAX_LOOT_THRESHOLD), info.r, info.g, info.b, info.id);
  2027. end
  2028. end
  2029. end
  2030. SlashCmdList["RANDOM"] = function(msg)
  2031. local num1 = gsub(msg, "(%s*)(%d+)(.*)", "%2", 1);
  2032. local rest = gsub(msg, "(%s*)(%d+)(.*)", "%3", 1);
  2033. local num2 = "";
  2034. local numSubs;
  2035. if ( strlen(rest) > 0 ) then
  2036. num2, numSubs = gsub(msg, "(%s*)(%d+)([-%s]+)(%d+)(.*)", "%4", 1);
  2037. if ( numSubs == 0 ) then
  2038. num2 = "";
  2039. end
  2040. end
  2041. if ( num1 == "" and num2 == "" ) then
  2042. RandomRoll("1", "100");
  2043. elseif ( num2 == "" ) then
  2044. RandomRoll("1", num1);
  2045. else
  2046. RandomRoll(num1, num2);
  2047. end
  2048. end
  2049. SlashCmdList["MACRO"] = function(msg)
  2050. ShowMacroFrame();
  2051. end
  2052. SlashCmdList["PVP"] = function(msg)
  2053. TogglePVP();
  2054. end
  2055. SlashCmdList["RAID_INFO"] = function(msg)
  2056. RaidFrame.slashCommand = 1;
  2057. if ( ( GetNumSavedInstances() > 0 ) and not RaidInfoFrame:IsVisible() ) then
  2058. ToggleRaidFrame();
  2059. RaidInfoFrame:Show();
  2060. elseif ( not RaidFrame:IsVisible() ) then
  2061. ToggleRaidFrame();
  2062. end
  2063. end
  2064. SlashCmdList["READYCHECK"] = function(msg)
  2065. if ( UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") ) then
  2066. DoReadyCheck();
  2067. end
  2068. end
  2069. --[[All of this information is obtainable through the armory now.
  2070. SlashCmdList["SAVEGUILDROSTER"] = function(msg)
  2071. SaveGuildRoster();
  2072. end]]
  2073. SlashCmdList["DUNGEONS"] = function(msg)
  2074. ToggleLFDParentFrame();
  2075. end
  2076. SlashCmdList["RAIDBROWSER"] = function(msg)
  2077. ToggleRaidBrowser();
  2078. end
  2079. SlashCmdList["BENCHMARK"] = function(msg)
  2080. SetTaxiBenchmarkMode(msg);
  2081. end
  2082. SlashCmdList["DISMOUNT"] = function(msg)
  2083. if ( SecureCmdOptionParse(msg) ) then
  2084. Dismount();
  2085. end
  2086. end
  2087. SlashCmdList["LEAVEVEHICLE"] = function(msg)
  2088. if ( SecureCmdOptionParse(msg) ) then
  2089. VehicleExit();
  2090. end
  2091. end
  2092. SlashCmdList["RESETCHAT"] = function(msg)
  2093. FCF_ResetAllWindows();
  2094. end
  2095. SlashCmdList["ENABLE_ADDONS"] = function(msg)
  2096. EnableAllAddOns();
  2097. ReloadUI();
  2098. end
  2099. SlashCmdList["DISABLE_ADDONS"] = function(msg)
  2100. DisableAllAddOns();
  2101. ReloadUI();
  2102. end
  2103. SlashCmdList["STOPWATCH"] = function(msg)
  2104. if ( not IsAddOnLoaded("Blizzard_TimeManager") ) then
  2105. UIParentLoadAddOn("Blizzard_TimeManager");
  2106. end
  2107. if ( StopwatchFrame ) then
  2108. local text = strmatch(msg, "%s*([^%s]+)%s*");
  2109. if ( text ) then
  2110. text = strlower(text);
  2111. -- in any of the following cases, the stopwatch will be shown
  2112. StopwatchFrame:Show();
  2113. -- try to match a command
  2114. local function MatchCommand(param, text)
  2115. local i, compare;
  2116. i = 1;
  2117. repeat
  2118. compare = _G[param..i];
  2119. if ( compare and compare == text ) then
  2120. return true;
  2121. end
  2122. i = i + 1;
  2123. until ( not compare );
  2124. return false;
  2125. end
  2126. if ( MatchCommand("SLASH_STOPWATCH_PARAM_PLAY", text) ) then
  2127. Stopwatch_Play();
  2128. return;
  2129. end
  2130. if ( MatchCommand("SLASH_STOPWATCH_PARAM_PAUSE", text) ) then
  2131. Stopwatch_Pause();
  2132. return;
  2133. end
  2134. if ( MatchCommand("SLASH_STOPWATCH_PARAM_STOP", text) ) then
  2135. Stopwatch_Clear();
  2136. return;
  2137. end
  2138. -- try to match a countdown
  2139. -- kinda ghetto, but hey, it's simple and it works =)
  2140. local hour, minute, second = strmatch(msg, "(%d+):(%d+):(%d+)");
  2141. if ( not hour ) then
  2142. minute, second = strmatch(msg, "(%d+):(%d+)");
  2143. if ( not minute ) then
  2144. second = strmatch(msg, "(%d+)");
  2145. end
  2146. end
  2147. Stopwatch_StartCountdown(tonumber(hour), tonumber(minute), tonumber(second));
  2148. else
  2149. Stopwatch_Toggle();
  2150. end
  2151. end
  2152. end
  2153. SlashCmdList["CALENDAR"] = function(msg)
  2154. if ( not IsAddOnLoaded("Blizzard_Calendar") ) then
  2155. UIParentLoadAddOn("Blizzard_Calendar");
  2156. end
  2157. if ( Calendar_Toggle ) then
  2158. Calendar_Toggle();
  2159. end
  2160. end
  2161. SlashCmdList["ACHIEVEMENTUI"] = function(msg)
  2162. ToggleAchievementFrame();
  2163. end
  2164. SlashCmdList["SET_TITLE"] = function(msg)
  2165. local name = SecureCmdOptionParse(msg);
  2166. if ( name and name ~= "") then
  2167. if(not SetTitleByName(name)) then
  2168. UIErrorsFrame:AddMessage(TITLE_DOESNT_EXIST, 1.0, 0.1, 0.1, 1.0);
  2169. end
  2170. else
  2171. SetCurrentTitle(-1)
  2172. end
  2173. end
  2174. SlashCmdList["USE_TALENT_SPEC"] = function(msg)
  2175. local group = SecureCmdOptionParse(msg);
  2176. if ( group ) then
  2177. local groupNumber = tonumber(group);
  2178. if ( groupNumber ) then
  2179. SetActiveSpecGroup(groupNumber);
  2180. end
  2181. end
  2182. end
  2183. -- easier method to turn on/off errors for macros
  2184. SlashCmdList["UI_ERRORS_OFF"] = function(msg)
  2185. UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE");
  2186. SetCVar("Sound_EnableSFX", "0");
  2187. end
  2188. SlashCmdList["UI_ERRORS_ON"] = function(msg)
  2189. UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE");
  2190. SetCVar("Sound_EnableSFX", "1");
  2191. end
  2192. SlashCmdList["FRAMESTACK"] = function(msg)
  2193. UIParentLoadAddOn("Blizzard_DebugTools");
  2194. if(msg == tostring(true)) then
  2195. FrameStackTooltip_Toggle(true);
  2196. else
  2197. FrameStackTooltip_Toggle();
  2198. end
  2199. end
  2200. SlashCmdList["EVENTTRACE"] = function(msg)
  2201. UIParentLoadAddOn("Blizzard_DebugTools");
  2202. EventTraceFrame_HandleSlashCmd(msg);
  2203. end
  2204. SlashCmdList["DUMP"] = function(msg)
  2205. UIParentLoadAddOn("Blizzard_DebugTools");
  2206. DevTools_DumpCommand(msg);
  2207. end
  2208. SlashCmdList["RELOAD"] = function(msg)
  2209. ConsoleExec("reloadui");
  2210. end
  2211. SlashCmdList["WARGAME"] = function(msg)
  2212. local target, area = strmatch(msg, "%s*([^%s]+)%s*(.*)");
  2213. if ( target and target ~= "" ) then
  2214. if area and area == "" then area = nil end
  2215. StartWarGame(target, area );
  2216. end
  2217. end
  2218. SlashCmdList["GUILDFINDER"] = function(msg)
  2219. if ( IsTrialAccount() ) then
  2220. UIErrorsFrame:AddMessage(ERR_RESTRICTED_ACCOUNT, 1.0, 0.1, 0.1, 1.0);
  2221. else
  2222. ToggleGuildFinder();
  2223. end
  2224. end
  2225. SlashCmdList["TARGET_MARKER"] = function(msg)
  2226. local marker, target = SecureCmdOptionParse(msg);
  2227. if ( not target ) then
  2228. target = "target";
  2229. end
  2230. if ( tonumber(marker) ) then
  2231. SetRaidTarget(target, tonumber(marker)); --Using /tm 0 will clear the target marker.
  2232. end
  2233. end
  2234. SlashCmdList["OPEN_LOOT_HISTORY"] = function(msg)
  2235. ToggleLootHistoryFrame();
  2236. end
  2237. SlashCmdList["RAIDFINDER"] = function(msg)
  2238. PVEFrame_ToggleFrame("GroupFinderFrame", RaidFinderFrame);
  2239. end
  2240. function ChatFrame_SetupListProxyTable(list)
  2241. if ( getmetatable(list) ) then
  2242. return;
  2243. end
  2244. setmetatable(list, { __index = {} });
  2245. end
  2246. function ChatFrame_ImportListToHash(list, hash)
  2247. for k, v in pairs(list) do
  2248. local i = 1;
  2249. local tag = _G["SLASH_"..k..i];
  2250. while(tag) do
  2251. tag = strupper(tag);
  2252. if ( hash ) then
  2253. hash[tag] = v;
  2254. end
  2255. hash_ChatTypeInfoList[tag] = k; --Also need to import it here for all types.
  2256. i = i + 1;
  2257. tag = _G["SLASH_"..k..i];
  2258. end
  2259. --Add the item we removed to the proxy table.
  2260. local proxyTable = getmetatable(list).__index;
  2261. proxyTable[k] = v;
  2262. end
  2263. table.wipe(list);
  2264. end
  2265. function ChatFrame_ImportEmoteTokensToHash()
  2266. local i = 1;
  2267. local j = 1;
  2268. local cmdString = _G["EMOTE"..i.."_CMD"..j];
  2269. while ( i <= MAXEMOTEINDEX ) do
  2270. local token = _G["EMOTE"..i.."_TOKEN"];
  2271. -- if the code in here changes - change the corresponding code above
  2272. if ( token ) then
  2273. hash_EmoteTokenList[strupper(cmdString)] = token; -- add to hash
  2274. end
  2275. j = j + 1;
  2276. cmdString = _G["EMOTE"..i.."_CMD"..j];
  2277. if ( not cmdString ) then
  2278. i = i + 1;
  2279. j = 1;
  2280. cmdString = _G["EMOTE"..i.."_CMD"..j];
  2281. end
  2282. end
  2283. end
  2284. function ChatFrame_ImportAllListsToHash()
  2285. ChatFrame_ImportListToHash(SecureCmdList, hash_SecureCmdList);
  2286. ChatFrame_ImportListToHash(SlashCmdList, hash_SlashCmdList);
  2287. ChatFrame_ImportListToHash(ChatTypeInfo);
  2288. end
  2289. ChatFrame_SetupListProxyTable(SecureCmdList);
  2290. ChatFrame_SetupListProxyTable(SlashCmdList);
  2291. ChatFrame_SetupListProxyTable(ChatTypeInfo);
  2292. for index, value in pairs(ChatTypeInfo) do
  2293. value.r = 1.0;
  2294. value.g = 1.0;
  2295. value.b = 1.0;
  2296. value.id = GetChatTypeIndex(index);
  2297. end
  2298. ChatFrame_ImportAllListsToHash();
  2299. ChatFrame_ImportEmoteTokensToHash();
  2300. -- ChatFrame functions
  2301. function ChatFrame_OnLoad(self)
  2302. self.flashTimer = 0;
  2303. self:RegisterEvent("PLAYER_ENTERING_WORLD");
  2304. self:RegisterEvent("UPDATE_CHAT_COLOR");
  2305. self:RegisterEvent("UPDATE_CHAT_WINDOWS");
  2306. self:RegisterEvent("CHAT_MSG_CHANNEL");
  2307. self:RegisterEvent("ZONE_UNDER_ATTACK");
  2308. self:RegisterEvent("UPDATE_INSTANCE_INFO");
  2309. self:RegisterEvent("NEW_TITLE_EARNED");
  2310. self:RegisterEvent("OLD_TITLE_LOST");
  2311. self:RegisterEvent("UPDATE_CHAT_COLOR_NAME_BY_CLASS");
  2312. self:RegisterEvent("VARIABLES_LOADED");
  2313. self:RegisterEvent("CHAT_SERVER_DISCONNECTED");
  2314. self:RegisterEvent("CHAT_SERVER_RECONNECTED");
  2315. self:RegisterEvent("BN_CONNECTED");
  2316. self:RegisterEvent("BN_DISCONNECTED");
  2317. self:RegisterEvent("PLAYER_REPORT_SUBMITTED");
  2318. self:RegisterEvent("NEUTRAL_FACTION_SELECT_RESULT");
  2319. self.tellTimer = GetTime();
  2320. self.channelList = {};
  2321. self.zoneChannelList = {};
  2322. self.messageTypeList = {};
  2323. self.defaultLanguage = GetDefaultLanguage(); --If PLAYER_ENTERING_WORLD hasn't been called yet, this is nil, but it'll be fixed whent he event is fired.
  2324. end
  2325. function ChatFrame_RegisterForMessages(self, ...)
  2326. local messageGroup;
  2327. local index = 1;
  2328. for i=1, select("#", ...) do
  2329. messageGroup = ChatTypeGroup[select(i, ...)];
  2330. if ( messageGroup ) then
  2331. self.messageTypeList[index] = select(i, ...);
  2332. for index, value in pairs(messageGroup) do
  2333. self:RegisterEvent(value);
  2334. end
  2335. index = index + 1;
  2336. end
  2337. end
  2338. end
  2339. function ChatFrame_RegisterForChannels(self, ...)
  2340. local index = 1;
  2341. for i=1, select("#", ...), 2 do
  2342. self.channelList[index], self.zoneChannelList[index] = select(i, ...);
  2343. index = index + 1;
  2344. end
  2345. end
  2346. function ChatFrame_AddMessageGroup(chatFrame, group)
  2347. local info = ChatTypeGroup[group];
  2348. if ( info ) then
  2349. tinsert(chatFrame.messageTypeList, group);
  2350. for index, value in pairs(info) do
  2351. chatFrame:RegisterEvent(value);
  2352. end
  2353. AddChatWindowMessages(chatFrame:GetID(), group);
  2354. end
  2355. end
  2356. function ChatFrame_AddSingleMessageType(chatFrame, messageType)
  2357. local group = ChatTypeGroupInverted[messageType];
  2358. local info = ChatTypeGroup[group];
  2359. if ( info ) then
  2360. if (not tContains(chatFrame.messageTypeList, group)) then
  2361. tinsert(chatFrame.messageTypeList, group);
  2362. end
  2363. for index, value in pairs(info) do
  2364. if (value == messageType) then
  2365. chatFrame:RegisterEvent(value);
  2366. end
  2367. end
  2368. end
  2369. end
  2370. function ChatFrame_RemoveMessageGroup(chatFrame, group)
  2371. local info = ChatTypeGroup[group];
  2372. if ( info ) then
  2373. for index, value in pairs(chatFrame.messageTypeList) do
  2374. if ( strupper(value) == strupper(group) ) then
  2375. chatFrame.messageTypeList[index] = nil;
  2376. end
  2377. end
  2378. for index, value in pairs(info) do
  2379. chatFrame:UnregisterEvent(value);
  2380. end
  2381. RemoveChatWindowMessages(chatFrame:GetID(), group);
  2382. end
  2383. end
  2384. function ChatFrame_RemoveAllMessageGroups(chatFrame)
  2385. for index, value in pairs(chatFrame.messageTypeList) do
  2386. for eventIndex, eventValue in pairs(ChatTypeGroup[value]) do
  2387. chatFrame:UnregisterEvent(eventValue);
  2388. end
  2389. RemoveChatWindowMessages(chatFrame:GetID(), value);
  2390. end
  2391. chatFrame.messageTypeList = {};
  2392. end
  2393. function ChatFrame_AddChannel(chatFrame, channel)
  2394. local zoneChannel = AddChatWindowChannel(chatFrame:GetID(), channel);
  2395. if ( zoneChannel ) then
  2396. local i = 1;
  2397. while ( chatFrame.channelList[i] ) do
  2398. i = i + 1;
  2399. end
  2400. chatFrame.channelList[i] = channel;
  2401. chatFrame.zoneChannelList[i] = zoneChannel;
  2402. end
  2403. end
  2404. function ChatFrame_RemoveChannel(chatFrame, channel)
  2405. for index, value in pairs(chatFrame.channelList) do
  2406. if ( strupper(channel) == strupper(value) ) then
  2407. chatFrame.channelList[index] = nil;
  2408. chatFrame.zoneChannelList[index] = nil;
  2409. end
  2410. end
  2411. RemoveChatWindowChannel(chatFrame:GetID(), channel);
  2412. end
  2413. function ChatFrame_RemoveAllChannels(chatFrame)
  2414. for index, value in pairs(chatFrame.channelList) do
  2415. RemoveChatWindowChannel(chatFrame:GetID(), value);
  2416. end
  2417. chatFrame.channelList = {};
  2418. chatFrame.zoneChannelList = {};
  2419. end
  2420. function ChatFrame_AddPrivateMessageTarget(chatFrame, chatTarget)
  2421. ChatFrame_RemoveExcludePrivateMessageTarget(chatFrame, chatTarget);
  2422. if ( chatFrame.privateMessageList ) then
  2423. chatFrame.privateMessageList[strlower(chatTarget)] = true;
  2424. else
  2425. chatFrame.privateMessageList = { [strlower(chatTarget)] = true };
  2426. end
  2427. end
  2428. function ChatFrame_RemovePrivateMessageTarget(chatFrame, chatTarget)
  2429. if ( chatFrame.privateMessageList ) then
  2430. chatFrame.privateMessageList[strlower(chatTarget)] = nil;
  2431. end
  2432. end
  2433. function ChatFrame_ExcludePrivateMessageTarget(chatFrame, chatTarget)
  2434. ChatFrame_RemovePrivateMessageTarget(chatFrame, chatTarget);
  2435. if ( chatFrame.excludePrivateMessageList ) then
  2436. chatFrame.excludePrivateMessageList[strlower(chatTarget)] = true;
  2437. else
  2438. chatFrame.excludePrivateMessageList = { [strlower(chatTarget)] = true };
  2439. end
  2440. end
  2441. function ChatFrame_RemoveExcludePrivateMessageTarget(chatFrame, chatTarget)
  2442. if ( chatFrame.excludePrivateMessageList ) then
  2443. chatFrame.excludePrivateMessageList[strlower(chatTarget)] = nil;
  2444. end
  2445. end
  2446. function ChatFrame_ReceiveAllPrivateMessages(chatFrame)
  2447. chatFrame.privateMessageList = nil;
  2448. chatFrame.excludePrivateMessageList = nil;
  2449. end
  2450. function ChatFrame_AddBNConversationTarget(chatFrame, chatTarget)
  2451. ChatFrame_RemoveExcludeBNConversationTarget(chatFrame, chatTarget);
  2452. if ( chatFrame.bnConversationList ) then
  2453. chatFrame.bnConversationList[tonumber(chatTarget)] = true;
  2454. else
  2455. chatFrame.bnConversationList = { [tonumber(chatTarget)] = true };
  2456. end
  2457. end
  2458. function ChatFrame_RemoveBNConversationTarget(chatFrame, chatTarget)
  2459. if ( chatFrame.bnConversationList ) then
  2460. chatFrame.bnConversationList[tonumber(chatTarget)] = nil;
  2461. end
  2462. end
  2463. function ChatFrame_ExcludeBNConversationTarget(chatFrame, chatTarget)
  2464. ChatFrame_RemoveBNConversationTarget(chatFrame, chatTarget);
  2465. if ( chatFrame.excludeBNConversationList ) then
  2466. chatFrame.excludeBNConversationList[tonumber(chatTarget)] = true;
  2467. else
  2468. chatFrame.excludeBNConversationList = { [tonumber(chatTarget)] = true };
  2469. end
  2470. end
  2471. function ChatFrame_RemoveExcludeBNConversationTarget(chatFrame, chatTarget)
  2472. if ( chatFrame.excludeBNConversationList ) then
  2473. chatFrame.excludeBNConversationList[tonumber(chatTarget)] = nil;
  2474. end
  2475. end
  2476. function ChatFrame_ReceiveAllBNConversations(chatFrame)
  2477. chatFrame.bnConversationList = nil;
  2478. chatFrame.excludeBNConversationList = nil;
  2479. end
  2480. -- Set up a private editbox to handle macro execution
  2481. do
  2482. local function GetDefaultChatEditBox(field)
  2483. return DEFAULT_CHAT_FRAME.editBox;
  2484. end
  2485. local editbox = CreateFrame("Editbox", "MacroEditBox");
  2486. editbox:RegisterEvent("EXECUTE_CHAT_LINE");
  2487. editbox:SetScript("OnEvent",
  2488. function(self,event,line)
  2489. if ( event == "EXECUTE_CHAT_LINE" ) then
  2490. local defaulteditbox = securecall(GetDefaultChatEditBox);
  2491. self:SetAttribute("chatType", defaulteditbox:GetAttribute("chatType"));
  2492. self:SetAttribute("tellTarget", defaulteditbox:GetAttribute("tellTarget"));
  2493. self:SetAttribute("channelTarget", defaulteditbox:GetAttribute("channelTarget"));
  2494. self:SetText(line);
  2495. ChatEdit_SendText(self);
  2496. end
  2497. end
  2498. );
  2499. editbox:Hide();
  2500. end
  2501. function ChatFrame_OnEvent(self, event, ...)
  2502. if ( ChatFrame_ConfigEventHandler(self, event, ...) ) then
  2503. return;
  2504. end
  2505. if ( ChatFrame_SystemEventHandler(self, event, ...) ) then
  2506. return
  2507. end
  2508. if ( ChatFrame_MessageEventHandler(self, event, ...) ) then
  2509. return
  2510. end
  2511. end
  2512. function ChatFrame_ConfigEventHandler(self, event, ...)
  2513. if ( event == "PLAYER_ENTERING_WORLD" ) then
  2514. self.defaultLanguage = GetDefaultLanguage();
  2515. return true;
  2516. elseif ( event == "NEUTRAL_FACTION_SELECT_RESULT" ) then
  2517. self.defaultLanguage = GetDefaultLanguage();
  2518. return true;
  2519. elseif ( event == "UPDATE_CHAT_WINDOWS" ) then
  2520. local name, fontSize, r, g, b, a, shown, locked = FCF_GetChatWindowInfo(self:GetID());
  2521. if ( fontSize > 0 ) then
  2522. local fontFile, unused, fontFlags = self:GetFont();
  2523. self:SetFont(fontFile, fontSize, fontFlags);
  2524. end
  2525. if ( shown and not self.minimized ) then
  2526. self:Show();
  2527. end
  2528. -- Do more stuff!!!
  2529. ChatFrame_RegisterForMessages(self, GetChatWindowMessages(self:GetID()));
  2530. ChatFrame_RegisterForChannels(self, GetChatWindowChannels(self:GetID()));
  2531. -- GMOTD may have arrived before this frame registered for the event
  2532. if ( not self.checkedGMOTD and self:IsEventRegistered("GUILD_MOTD") ) then
  2533. self.checkedGMOTD = true;
  2534. ChatFrame_DisplayGMOTD(self, GetGuildRosterMOTD());
  2535. end
  2536. return true;
  2537. end
  2538. local arg1, arg2, arg3, arg4 = ...;
  2539. if ( event == "UPDATE_CHAT_COLOR" ) then
  2540. local info = ChatTypeInfo[strupper(arg1)];
  2541. if ( info ) then
  2542. info.r = arg2;
  2543. info.g = arg3;
  2544. info.b = arg4;
  2545. self:UpdateColorByID(info.id, info.r, info.g, info.b);
  2546. if ( strupper(arg1) == "WHISPER" ) then
  2547. info = ChatTypeInfo["REPLY"];
  2548. if ( info ) then
  2549. info.r = arg2;
  2550. info.g = arg3;
  2551. info.b = arg4;
  2552. self:UpdateColorByID(info.id, info.r, info.g, info.b);
  2553. end
  2554. end
  2555. end
  2556. return true;
  2557. elseif ( event == "UPDATE_CHAT_COLOR_NAME_BY_CLASS" ) then
  2558. local info = ChatTypeInfo[strupper(arg1)];
  2559. if ( info ) then
  2560. info.colorNameByClass = arg2;
  2561. if ( strupper(arg1) == "WHISPER" ) then
  2562. info = ChatTypeInfo["REPLY"];
  2563. if ( info ) then
  2564. info.colorNameByClass = arg2;
  2565. end
  2566. end
  2567. end
  2568. return true;
  2569. elseif ( event == "VARIABLES_LOADED" ) then
  2570. if ( GetCVarBool("chatMouseScroll") ) then
  2571. self:SetScript("OnMouseWheel", FloatingChatFrame_OnMouseScroll);
  2572. self:EnableMouseWheel(true);
  2573. end
  2574. self:UnregisterEvent("VARIABLES_LOADED");
  2575. return true;
  2576. end
  2577. end
  2578. function ChatFrame_SystemEventHandler(self, event, ...)
  2579. if ( event == "TIME_PLAYED_MSG" ) then
  2580. local arg1, arg2 = ...;
  2581. ChatFrame_DisplayTimePlayed(self, arg1, arg2);
  2582. return true;
  2583. elseif ( event == "PLAYER_LEVEL_UP" ) then
  2584. local level, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 = ...;
  2585. LevelUpDisplay_ChatPrint(self, level, LEVEL_UP_TYPE_CHARACTER)
  2586. return true;
  2587. elseif (event == "UNIT_LEVEL" ) then
  2588. local arg1 = ...;
  2589. if (arg1 == "pet" and UnitName("pet") ~= UNKNOWNOBJECT) then
  2590. LevelUpDisplay_ChatPrint(self, UnitLevel("pet"), LEVEL_UP_TYPE_PET);
  2591. end
  2592. elseif ( event == "CHARACTER_POINTS_CHANGED" ) then
  2593. local arg1 = ...;
  2594. local info = ChatTypeInfo["SYSTEM"];
  2595. return true;
  2596. elseif ( event == "GUILD_MOTD" ) then
  2597. ChatFrame_DisplayGMOTD(self, ...);
  2598. return true;
  2599. elseif ( event == "ZONE_UNDER_ATTACK" ) then
  2600. local arg1 = ...;
  2601. local info = ChatTypeInfo["SYSTEM"];
  2602. self:AddMessage(format(ZONE_UNDER_ATTACK, arg1), info.r, info.g, info.b, info.id);
  2603. return true;
  2604. elseif ( event == "UPDATE_INSTANCE_INFO" ) then
  2605. if ( RaidFrame.hasRaidInfo ) then
  2606. local info = ChatTypeInfo["SYSTEM"];
  2607. if ( RaidFrame.slashCommand and GetNumSavedInstances() == 0 and self == DEFAULT_CHAT_FRAME) then
  2608. self:AddMessage(NO_RAID_INSTANCES_SAVED, info.r, info.g, info.b, info.id);
  2609. RaidFrame.slashCommand = nil;
  2610. end
  2611. end
  2612. return true;
  2613. elseif ( event == "NEW_TITLE_EARNED" ) then
  2614. local arg1 = ...;
  2615. local info = ChatTypeInfo["SYSTEM"];
  2616. self:AddMessage(format(NEW_TITLE_EARNED, arg1), info.r, info.g, info.b, info.id);
  2617. return true;
  2618. elseif ( event == "OLD_TITLE_LOST" ) then
  2619. local arg1 = ...;
  2620. local info = ChatTypeInfo["SYSTEM"];
  2621. self:AddMessage(format(OLD_TITLE_LOST, arg1), info.r, info.g, info.b, info.id);
  2622. return true;
  2623. elseif ( event == "CHAT_SERVER_DISCONNECTED" ) then
  2624. local info = ChatTypeInfo["SYSTEM"];
  2625. local isInitialMessage = ...;
  2626. self:AddMessage(CHAT_SERVER_DISCONNECTED_MESSAGE, info.r, info.g, info.b, info.id);
  2627. return true;
  2628. elseif ( event == "CHAT_SERVER_RECONNECTED" ) then
  2629. local info = ChatTypeInfo["SYSTEM"];
  2630. self:AddMessage(CHAT_SERVER_RECONNECTED_MESSAGE, info.r, info.g, info.b, info.id);
  2631. return true;
  2632. elseif ( event == "BN_CONNECTED" ) then
  2633. local info = ChatTypeInfo["SYSTEM"];
  2634. self:AddMessage(BN_CHAT_CONNECTED, info.r, info.g, info.b, info.id);
  2635. elseif ( event == "BN_DISCONNECTED" ) then
  2636. local info = ChatTypeInfo["SYSTEM"];
  2637. self:AddMessage(BN_CHAT_DISCONNECTED, info.r, info.g, info.b, info.id);
  2638. elseif ( event == "UNIT_GUILD_LEVEL" ) then
  2639. local unit, level = ...;
  2640. if ( unit == "player" ) then
  2641. LevelUpDisplay_ChatPrint(self, level, LEVEL_UP_TYPE_GUILD);
  2642. end
  2643. elseif ( event == "PLAYER_REPORT_SUBMITTED" ) then
  2644. local guid = ...;
  2645. FCF_RemoveAllMessagesFromChanSender(self, guid);
  2646. return true;
  2647. end
  2648. end
  2649. function GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)
  2650. local chatType = strsub(event, 10);
  2651. if ( strsub(chatType, 1, 7) == "WHISPER" ) then
  2652. chatType = "WHISPER";
  2653. end
  2654. if ( strsub(chatType, 1, 7) == "CHANNEL" ) then
  2655. chatType = "CHANNEL"..arg8;
  2656. end
  2657. local info = ChatTypeInfo[chatType];
  2658. if ( info and info.colorNameByClass and arg12 ) then
  2659. local localizedClass, englishClass, localizedRace, englishRace, sex = GetPlayerInfoByGUID(arg12)
  2660. if ( englishClass ) then
  2661. local classColorTable = RAID_CLASS_COLORS[englishClass];
  2662. if ( not classColorTable ) then
  2663. return arg2;
  2664. end
  2665. return string.format("\124cff%.2x%.2x%.2x", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255)..arg2.."\124r"
  2666. end
  2667. end
  2668. return arg2;
  2669. end
  2670. function RemoveExtraSpaces(str)
  2671. return string.gsub(str, " +", " "); --Replace all instances of 5+ spaces with only 4 spaces.
  2672. end
  2673. function ChatFrame_DisplayGMOTD(frame, gmotd)
  2674. if ( gmotd and (strlen(gmotd) > 0) ) then
  2675. local info = ChatTypeInfo["GUILD"];
  2676. local string = format(GUILD_MOTD_TEMPLATE, gmotd);
  2677. frame:AddMessage(string, info.r, info.g, info.b, info.id);
  2678. end
  2679. end
  2680. function ChatFrame_GetMobileEmbeddedTexture(r, g, b)
  2681. r, g, b = floor(r * 255), floor(g * 255), floor(b * 255);
  2682. return format("|TInterface\\ChatFrame\\UI-ChatIcon-ArmoryChat:14:14:0:0:16:16:0:16:0:16:%d:%d:%d|t", r, g, b);
  2683. end
  2684. function ChatFrame_MessageEventHandler(self, event, ...)
  2685. if ( strsub(event, 1, 8) == "CHAT_MSG" ) then
  2686. local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14 = ...;
  2687. local type = strsub(event, 10);
  2688. local info = ChatTypeInfo[type];
  2689. local filter = false;
  2690. if ( chatFilters[event] ) then
  2691. local newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newarg14;
  2692. for _, filterFunc in next, chatFilters[event] do
  2693. filter, newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newarg14 = filterFunc(self, event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
  2694. if ( filter ) then
  2695. return true;
  2696. elseif ( newarg1 ) then
  2697. arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14 = newarg1, newarg2, newarg3, newarg4, newarg5, newarg6, newarg7, newarg8, newarg9, newarg10, newarg11, newarg12, newarg13, newarg14;
  2698. end
  2699. end
  2700. end
  2701. local coloredName = GetColoredName(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
  2702. local channelLength = strlen(arg4);
  2703. local infoType = type;
  2704. if ( (strsub(type, 1, 7) == "CHANNEL") and (type ~= "CHANNEL_LIST") and ((arg1 ~= "INVITE") or (type ~= "CHANNEL_NOTICE_USER")) ) then
  2705. if ( arg1 == "WRONG_PASSWORD" ) then
  2706. local staticPopup = _G[StaticPopup_Visible("CHAT_CHANNEL_PASSWORD") or ""];
  2707. if ( staticPopup and strupper(staticPopup.data) == strupper(arg9) ) then
  2708. -- Don't display invalid password messages if we're going to prompt for a password (bug 102312)
  2709. return;
  2710. end
  2711. end
  2712. local found = 0;
  2713. for index, value in pairs(self.channelList) do
  2714. if ( channelLength > strlen(value) ) then
  2715. -- arg9 is the channel name without the number in front...
  2716. if ( ((arg7 > 0) and (self.zoneChannelList[index] == arg7)) or (strupper(value) == strupper(arg9)) ) then
  2717. found = 1;
  2718. infoType = "CHANNEL"..arg8;
  2719. info = ChatTypeInfo[infoType];
  2720. if ( (type == "CHANNEL_NOTICE") and (arg1 == "YOU_LEFT") ) then
  2721. self.channelList[index] = nil;
  2722. self.zoneChannelList[index] = nil;
  2723. end
  2724. break;
  2725. end
  2726. end
  2727. end
  2728. if ( (found == 0) or not info ) then
  2729. return true;
  2730. end
  2731. end
  2732. local chatGroup = Chat_GetChatCategory(type);
  2733. local chatTarget;
  2734. if ( chatGroup == "CHANNEL" or chatGroup == "BN_CONVERSATION" ) then
  2735. chatTarget = tostring(arg8);
  2736. elseif ( chatGroup == "WHISPER" or chatGroup == "BN_WHISPER" ) then
  2737. if(not(strsub(arg2, 1, 2) == "|K")) then
  2738. chatTarget = strupper(arg2);
  2739. else
  2740. chatTarget = arg2;
  2741. end
  2742. end
  2743. if ( FCFManager_ShouldSuppressMessage(self, chatGroup, chatTarget) ) then
  2744. return true;
  2745. end
  2746. if ( chatGroup == "WHISPER" or chatGroup == "BN_WHISPER" ) then
  2747. if ( self.privateMessageList and not self.privateMessageList[strlower(arg2)] ) then
  2748. return true;
  2749. elseif ( self.excludePrivateMessageList and self.excludePrivateMessageList[strlower(arg2)]
  2750. and ( (chatGroup == "WHISPER" and GetCVar("whisperMode") ~= "popout_and_inline") or (chatGroup == "BN_WHISPER" and GetCVar("bnWhisperMode") ~= "popout_and_inline") ) ) then
  2751. return true;
  2752. end
  2753. elseif ( chatGroup == "BN_CONVERSATION" ) then
  2754. if ( self.bnConversationList and not self.bnConversationList[arg8] ) then
  2755. return true;
  2756. elseif ( self.excludeBNConversationList and self.excludeBNConversationList[arg8] and GetCVar("conversationMode") ~= "popout_and_inline") then
  2757. return true;
  2758. end
  2759. end
  2760. if (self.privateMessageList) then
  2761. -- Dedicated BN whisper windows need online/offline messages for only that player
  2762. if ( (chatGroup == "BN_INLINE_TOAST_ALERT" or chatGroup == "BN_WHISPER_PLAYER_OFFLINE") and not self.privateMessageList[strlower(arg2)] ) then
  2763. return true;
  2764. end
  2765. -- HACK to put certain system messages into dedicated whisper windows
  2766. if ( chatGroup == "SYSTEM") then
  2767. local matchFound = false;
  2768. local message = strlower(arg1);
  2769. for playerName, _ in pairs(self.privateMessageList) do
  2770. local playerNotFoundMsg = strlower(format(ERR_CHAT_PLAYER_NOT_FOUND_S, playerName));
  2771. local charOnlineMsg = strlower(format(ERR_FRIEND_ONLINE_SS, playerName, playerName));
  2772. local charOfflineMsg = strlower(format(ERR_FRIEND_OFFLINE_S, playerName));
  2773. if ( message == playerNotFoundMsg or message == charOnlineMsg or message == charOfflineMsg) then
  2774. matchFound = true;
  2775. break;
  2776. end
  2777. end
  2778. if (not matchFound) then
  2779. return true;
  2780. end
  2781. end
  2782. end
  2783. if ( type == "SYSTEM" or type == "SKILL" or type == "LOOT" or type == "CURRENCY" or type == "MONEY" or
  2784. type == "OPENING" or type == "TRADESKILLS" or type == "PET_INFO" or type == "TARGETICONS" or type == "BN_WHISPER_PLAYER_OFFLINE") then
  2785. self:AddMessage(arg1, info.r, info.g, info.b, info.id);
  2786. elseif ( strsub(type,1,7) == "COMBAT_" ) then
  2787. self:AddMessage(arg1, info.r, info.g, info.b, info.id);
  2788. elseif ( strsub(type,1,6) == "SPELL_" ) then
  2789. self:AddMessage(arg1, info.r, info.g, info.b, info.id);
  2790. elseif ( strsub(type,1,10) == "BG_SYSTEM_" ) then
  2791. self:AddMessage(arg1, info.r, info.g, info.b, info.id);
  2792. elseif ( strsub(type,1,11) == "ACHIEVEMENT" ) then
  2793. self:AddMessage(format(arg1, "|Hplayer:"..arg2.."|h".."["..coloredName.."]".."|h"), info.r, info.g, info.b, info.id);
  2794. elseif ( strsub(type,1,18) == "GUILD_ACHIEVEMENT" ) then
  2795. self:AddMessage(format(arg1, "|Hplayer:"..arg2.."|h".."["..coloredName.."]".."|h"), info.r, info.g, info.b, info.id);
  2796. elseif ( type == "IGNORED" ) then
  2797. self:AddMessage(format(CHAT_IGNORED, arg2), info.r, info.g, info.b, info.id);
  2798. elseif ( type == "FILTERED" ) then
  2799. self:AddMessage(format(CHAT_FILTERED, arg2), info.r, info.g, info.b, info.id);
  2800. elseif ( type == "RESTRICTED" ) then
  2801. self:AddMessage(CHAT_RESTRICTED, info.r, info.g, info.b, info.id);
  2802. elseif ( type == "CHANNEL_LIST") then
  2803. if(channelLength > 0) then
  2804. self:AddMessage(format(_G["CHAT_"..type.."_GET"]..arg1, tonumber(arg8), arg4), info.r, info.g, info.b, info.id);
  2805. else
  2806. self:AddMessage(arg1, info.r, info.g, info.b, info.id);
  2807. end
  2808. elseif (type == "CHANNEL_NOTICE_USER") then
  2809. local globalstring = _G["CHAT_"..arg1.."_NOTICE_BN"];
  2810. if ( not globalstring ) then
  2811. globalstring = _G["CHAT_"..arg1.."_NOTICE"];
  2812. end
  2813. if(strlen(arg5) > 0) then
  2814. -- TWO users in this notice (E.G. x kicked y)
  2815. self:AddMessage(format(globalstring, arg8, arg4, arg2, arg5), info.r, info.g, info.b, info.id);
  2816. elseif ( arg1 == "INVITE" ) then
  2817. self:AddMessage(format(globalstring, arg4, arg2), info.r, info.g, info.b, info.id);
  2818. else
  2819. self:AddMessage(format(globalstring, arg8, arg4, arg2), info.r, info.g, info.b, info.id);
  2820. end
  2821. elseif (type == "CHANNEL_NOTICE") then
  2822. local globalstring = _G["CHAT_"..arg1.."_NOTICE_BN"];
  2823. if ( not globalstring ) then
  2824. globalstring = _G["CHAT_"..arg1.."_NOTICE"];
  2825. end
  2826. if ( arg10 > 0 ) then
  2827. arg4 = arg4.." "..arg10;
  2828. end
  2829. local accessID = ChatHistory_GetAccessID(Chat_GetChatCategory(type), arg8);
  2830. local typeID = ChatHistory_GetAccessID(infoType, arg8, arg12);
  2831. self:AddMessage(format(globalstring, arg8, arg4), info.r, info.g, info.b, info.id, false, accessID, typeID);
  2832. elseif ( type == "BN_CONVERSATION_NOTICE" ) then
  2833. local channelLink = format(CHAT_BN_CONVERSATION_GET_LINK, arg8, MAX_WOW_CHAT_CHANNELS + arg8);
  2834. local playerLink = format("|HBNplayer:%s:%s:%s:%s:%s|h[%s]|h", arg2, arg13, arg11, Chat_GetChatCategory(type), arg8, arg2);
  2835. local message = format(_G["CHAT_CONVERSATION_"..arg1.."_NOTICE"], channelLink, playerLink)
  2836. local accessID = ChatHistory_GetAccessID(Chat_GetChatCategory(type), arg8);
  2837. local typeID = ChatHistory_GetAccessID(infoType, arg8, arg12);
  2838. self:AddMessage(message, info.r, info.g, info.b, info.id, false, accessID, typeID);
  2839. elseif ( type == "BN_CONVERSATION_LIST" ) then
  2840. local channelLink = format(CHAT_BN_CONVERSATION_GET_LINK, arg8, MAX_WOW_CHAT_CHANNELS + arg8);
  2841. local message = format(CHAT_BN_CONVERSATION_LIST, channelLink, arg1);
  2842. self:AddMessage(message, info.r, info.g, info.b, info.id, false, accessID, typeID);
  2843. elseif ( type == "BN_INLINE_TOAST_ALERT" ) then
  2844. if ( arg1 == "FRIEND_OFFLINE" and not BNet_ShouldProcessOfflineEvents() ) then
  2845. return true;
  2846. end
  2847. local globalstring = _G["BN_INLINE_TOAST_"..arg1];
  2848. local message;
  2849. if ( arg1 == "FRIEND_REQUEST" ) then
  2850. message = globalstring;
  2851. elseif ( arg1 == "FRIEND_PENDING" ) then
  2852. message = format(BN_INLINE_TOAST_FRIEND_PENDING, BNGetNumFriendInvites());
  2853. elseif ( arg1 == "FRIEND_REMOVED" or arg1 == "BATTLETAG_FRIEND_REMOVED" ) then
  2854. message = format(globalstring, arg2);
  2855. elseif ( arg1 == "FRIEND_ONLINE" or arg1 == "FRIEND_OFFLINE") then
  2856. local hasFocus, toonName, client, realmName, realmID, faction, race, class, guild, zoneName, level, gameText = BNGetToonInfo(arg13);
  2857. if (toonName and toonName ~= "" and client and client ~= "") then
  2858. local toonNameText = BNet_GetClientEmbeddedTexture(client, 14)..toonName;
  2859. local playerLink = format("|HBNplayer:%s:%s:%s:%s:%s|h[%s] (%s)|h", arg2, arg13, arg11, Chat_GetChatCategory(type), 0, arg2, toonNameText);
  2860. message = format(globalstring, playerLink);
  2861. else
  2862. local playerLink = format("|HBNplayer:%s:%s:%s:%s:%s|h[%s]|h", arg2, arg13, arg11, Chat_GetChatCategory(type), 0, arg2);
  2863. message = format(globalstring, playerLink);
  2864. end
  2865. else
  2866. local playerLink = format("|HBNplayer:%s:%s:%s:%s:%s|h[%s]|h", arg2, arg13, arg11, Chat_GetChatCategory(type), 0, arg2);
  2867. message = format(globalstring, playerLink);
  2868. end
  2869. self:AddMessage(message, info.r, info.g, info.b, info.id);
  2870. elseif ( type == "BN_INLINE_TOAST_BROADCAST" ) then
  2871. if ( arg1 ~= "" ) then
  2872. arg1 = RemoveExtraSpaces(arg1);
  2873. local playerLink = format("|HBNplayer:%s:%s:%s:%s:%s|h[%s]|h", arg2, arg13, arg11, Chat_GetChatCategory(type), 0, arg2);
  2874. self:AddMessage(format(BN_INLINE_TOAST_BROADCAST, playerLink, arg1), info.r, info.g, info.b, info.id);
  2875. end
  2876. elseif ( type == "BN_INLINE_TOAST_BROADCAST_INFORM" ) then
  2877. if ( arg1 ~= "" ) then
  2878. arg1 = RemoveExtraSpaces(arg1);
  2879. self:AddMessage(BN_INLINE_TOAST_BROADCAST_INFORM, info.r, info.g, info.b, info.id);
  2880. end
  2881. elseif ( type == "BN_INLINE_TOAST_CONVERSATION" ) then
  2882. self:AddMessage(format(BN_INLINE_TOAST_CONVERSATION, arg1), info.r, info.g, info.b, info.id);
  2883. else
  2884. local body;
  2885. local _, fontHeight = FCF_GetChatWindowInfo(self:GetID());
  2886. if ( fontHeight == 0 ) then
  2887. --fontHeight will be 0 if it's still at the default (14)
  2888. fontHeight = 14;
  2889. end
  2890. -- Add AFK/DND flags
  2891. local pflag;
  2892. if(strlen(arg6) > 0) then
  2893. if ( arg6 == "GM" ) then
  2894. --If it was a whisper, dispatch it to the GMChat addon.
  2895. if ( type == "WHISPER" ) then
  2896. return;
  2897. end
  2898. --Add Blizzard Icon, this was sent by a GM
  2899. pflag = "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz:12:20:0:0:32:16:4:28:0:16|t ";
  2900. elseif ( arg6 == "DEV" ) then
  2901. --Add Blizzard Icon, this was sent by a Dev
  2902. pflag = "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz:12:20:0:0:32:16:4:28:0:16|t ";
  2903. else
  2904. pflag = _G["CHAT_FLAG_"..arg6];
  2905. end
  2906. else
  2907. pflag = "";
  2908. end
  2909. if ( type == "WHISPER_INFORM" and GMChatFrame_IsGM and GMChatFrame_IsGM(arg2) ) then
  2910. return;
  2911. end
  2912. local showLink = 1;
  2913. if ( strsub(type, 1, 7) == "MONSTER" or strsub(type, 1, 9) == "RAID_BOSS") then
  2914. showLink = nil;
  2915. else
  2916. arg1 = gsub(arg1, "%%", "%%%%");
  2917. end
  2918. -- Search for icon links and replace them with texture links.
  2919. for tag in string.gmatch(arg1, "%b{}") do
  2920. local term = strlower(string.gsub(tag, "[{}]", ""));
  2921. if ( ICON_TAG_LIST[term] and ICON_LIST[ICON_TAG_LIST[term]] ) then
  2922. arg1 = string.gsub(arg1, tag, ICON_LIST[ICON_TAG_LIST[term]] .. "0|t");
  2923. elseif ( GROUP_TAG_LIST[term] ) then
  2924. local groupIndex = GROUP_TAG_LIST[term];
  2925. local groupList = "[";
  2926. for i=1, GetNumGroupMembers() do
  2927. local name, rank, subgroup, level, class, classFileName = GetRaidRosterInfo(i);
  2928. if ( name and subgroup == groupIndex ) then
  2929. local classColorTable = RAID_CLASS_COLORS[classFileName];
  2930. if ( classColorTable ) then
  2931. name = string.format("\124cff%.2x%.2x%.2x%s\124r", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255, name);
  2932. end
  2933. groupList = groupList..(groupList == "[" and "" or PLAYER_LIST_DELIMITER)..name;
  2934. end
  2935. end
  2936. groupList = groupList.."]";
  2937. arg1 = string.gsub(arg1, tag, groupList);
  2938. end
  2939. end
  2940. --Remove groups of many spaces
  2941. arg1 = RemoveExtraSpaces(arg1);
  2942. local playerLink;
  2943. if ( type ~= "BN_WHISPER" and type ~= "BN_WHISPER_INFORM" and type ~= "BN_CONVERSATION" ) then
  2944. playerLink = "|Hplayer:"..arg2..":"..arg11..":"..chatGroup..(chatTarget and ":"..chatTarget or "").."|h";
  2945. else
  2946. playerLink = "|HBNplayer:"..arg2..":"..arg13..":"..arg11..":"..chatGroup..(chatTarget and ":"..chatTarget or "").."|h";
  2947. end
  2948. local message = arg1;
  2949. if ( arg14 ) then --isMobile
  2950. message = ChatFrame_GetMobileEmbeddedTexture(info.r, info.g, info.b)..message;
  2951. end
  2952. if ( (strlen(arg3) > 0) and (arg3 ~= self.defaultLanguage) ) then
  2953. local languageHeader = "["..arg3.."] ";
  2954. if ( showLink and (strlen(arg2) > 0) ) then
  2955. body = format(_G["CHAT_"..type.."_GET"]..languageHeader..message, pflag..playerLink.."["..coloredName.."]".."|h");
  2956. else
  2957. body = format(_G["CHAT_"..type.."_GET"]..languageHeader..message, pflag..arg2);
  2958. end
  2959. else
  2960. if ( not showLink or strlen(arg2) == 0 ) then
  2961. if ( type == "TEXT_EMOTE" ) then
  2962. body = message;
  2963. else
  2964. body = format(_G["CHAT_"..type.."_GET"]..message, pflag..arg2, arg2);
  2965. end
  2966. else
  2967. if ( type == "EMOTE" ) then
  2968. body = format(_G["CHAT_"..type.."_GET"]..message, pflag..playerLink..coloredName.."|h");
  2969. elseif ( type == "TEXT_EMOTE") then
  2970. body = string.gsub(message, arg2, pflag..playerLink..coloredName.."|h", 1);
  2971. else
  2972. body = format(_G["CHAT_"..type.."_GET"]..message, pflag..playerLink.."["..coloredName.."]".."|h");
  2973. end
  2974. end
  2975. end
  2976. -- Add Channel
  2977. arg4 = gsub(arg4, "%s%-%s.*", "");
  2978. if( chatGroup == "BN_CONVERSATION" ) then
  2979. body = format(CHAT_BN_CONVERSATION_GET_LINK, arg8, MAX_WOW_CHAT_CHANNELS + arg8)..body;
  2980. elseif(channelLength > 0) then
  2981. body = "|Hchannel:channel:"..arg8.."|h["..arg4.."]|h "..body;
  2982. end
  2983. --Add Timestamps
  2984. if ( CHAT_TIMESTAMP_FORMAT ) then
  2985. body = BetterDate(CHAT_TIMESTAMP_FORMAT, time())..body;
  2986. end
  2987. local accessID = ChatHistory_GetAccessID(chatGroup, chatTarget);
  2988. local typeID = ChatHistory_GetAccessID(infoType, chatTarget, arg12 or arg13);
  2989. self:AddMessage(body, info.r, info.g, info.b, info.id, false, accessID, typeID);
  2990. end
  2991. if ( type == "WHISPER" or type == "BN_WHISPER" ) then
  2992. --BN_WHISPER FIXME
  2993. ChatEdit_SetLastTellTarget(arg2, type);
  2994. if ( self.tellTimer and (GetTime() > self.tellTimer) ) then
  2995. PlaySound("TellMessage");
  2996. end
  2997. self.tellTimer = GetTime() + CHAT_TELL_ALERT_TIME;
  2998. --FCF_FlashTab(self);
  2999. end
  3000. if ( not self:IsShown() ) then
  3001. if ( (self == DEFAULT_CHAT_FRAME and info.flashTabOnGeneral) or (self ~= DEFAULT_CHAT_FRAME and info.flashTab) ) then
  3002. if ( not CHAT_OPTIONS.HIDE_FRAME_ALERTS or type == "WHISPER" or type == "BN_WHISPER" ) then --BN_WHISPER FIXME
  3003. if (not (type == "BN_CONVERSATION" and BNIsSelf(arg13))) then
  3004. if (not FCFManager_ShouldSuppressMessageFlash(self, chatGroup, chatTarget) ) then
  3005. FCF_StartAlertFlash(self);
  3006. end
  3007. end
  3008. end
  3009. end
  3010. end
  3011. return true;
  3012. end
  3013. end
  3014. function ChatFrame_AddMessageEventFilter (event, filter)
  3015. assert(event and filter);
  3016. if ( chatFilters[event] ) then
  3017. -- Only allow a filter to be added once
  3018. for index, filterFunc in next, chatFilters[event] do
  3019. if ( filterFunc == filter ) then
  3020. return;
  3021. end
  3022. end
  3023. else
  3024. chatFilters[event] = {};
  3025. end
  3026. tinsert(chatFilters[event], filter);
  3027. end
  3028. function ChatFrame_RemoveMessageEventFilter (event, filter)
  3029. assert(event and filter);
  3030. if ( chatFilters[event] ) then
  3031. for index, filterFunc in next, chatFilters[event] do
  3032. if ( filterFunc == filter ) then
  3033. tremove(chatFilters[event], index);
  3034. end
  3035. end
  3036. if ( #chatFilters[event] == 0 ) then
  3037. chatFilters[event] = nil;
  3038. end
  3039. end
  3040. end
  3041. function ChatFrame_GetMessageEventFilters (event)
  3042. assert(event);
  3043. return chatFilters[event];
  3044. end
  3045. function ChatFrame_OnUpdate(self, elapsedSec)
  3046. local flash = _G[self:GetName().."ButtonFrameBottomButtonFlash"];
  3047. if ( not flash ) then
  3048. return;
  3049. end
  3050. if ( self:AtBottom() ) then
  3051. if ( flash:IsShown() ) then
  3052. flash:Hide();
  3053. end
  3054. return;
  3055. end
  3056. local flashTimer = self.flashTimer + elapsedSec;
  3057. if ( flashTimer < CHAT_BUTTON_FLASH_TIME ) then
  3058. self.flashTimer = flashTimer;
  3059. return;
  3060. end
  3061. while ( flashTimer >= CHAT_BUTTON_FLASH_TIME ) do
  3062. flashTimer = flashTimer - CHAT_BUTTON_FLASH_TIME;
  3063. end
  3064. self.flashTimer = flashTimer;
  3065. if ( flash:IsShown() ) then
  3066. flash:Hide();
  3067. else
  3068. flash:Show();
  3069. end
  3070. end
  3071. function ChatFrame_OnHyperlinkShow(self, link, text, button)
  3072. SetItemRef(link, text, button, self);
  3073. end
  3074. function ChatFrame_OnMouseWheel(value)
  3075. if ( value > 0 ) then
  3076. SELECTED_DOCK_FRAME:ScrollUp();
  3077. elseif ( value < 0 ) then
  3078. SELECTED_DOCK_FRAME:ScrollDown();
  3079. end
  3080. end
  3081. function ChatFrame_OpenChat(text, chatFrame)
  3082. local editBox = ChatEdit_ChooseBoxForSend(chatFrame);
  3083. ChatEdit_ActivateChat(editBox);
  3084. editBox.setText = 1;
  3085. editBox.text = text;
  3086. if ( editBox:GetAttribute("chatType") == editBox:GetAttribute("stickyType") ) then
  3087. if ( (editBox:GetAttribute("stickyType") == "PARTY") and (not IsInGroup(LE_PARTY_CATEGORY_HOME)) or
  3088. (editBox:GetAttribute("stickyType") == "RAID") and (not IsInRaid(LE_PARTY_CATEGORY_HOME)) or
  3089. (editBox:GetAttribute("stickyType") == "INSTANCE_CHAT") and (not IsInGroup(LE_PARTY_CATEGORY_INSTANCE))) then
  3090. editBox:SetAttribute("chatType", "SAY");
  3091. end
  3092. end
  3093. ChatEdit_UpdateHeader(editBox);
  3094. return editBox;
  3095. end
  3096. function ChatFrame_ScrollToBottom()
  3097. SELECTED_DOCK_FRAME:ScrollToBottom();
  3098. end
  3099. function ChatFrame_ScrollUp()
  3100. SELECTED_DOCK_FRAME:ScrollUp();
  3101. end
  3102. function ChatFrame_ScrollDown()
  3103. SELECTED_DOCK_FRAME:ScrollDown();
  3104. end
  3105. --used for chatframe and combat log
  3106. function MessageFrameScrollButton_OnLoad(self)
  3107. self.clickDelay = MESSAGE_SCROLLBUTTON_INITIAL_DELAY;
  3108. self:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonUp", "RightButtonDown");
  3109. end
  3110. --Controls scrolling for chatframe and combat log
  3111. function MessageFrameScrollButton_OnUpdate(self, elapsed)
  3112. if (self:GetButtonState() == "PUSHED") then
  3113. self.clickDelay = self.clickDelay - elapsed;
  3114. if ( self.clickDelay < 0 ) then
  3115. local name = self:GetName();
  3116. if ( name == self:GetParent():GetName().."DownButton" ) then
  3117. self:GetParent():GetParent():ScrollDown();
  3118. elseif ( name == self:GetParent():GetName().."UpButton" ) then
  3119. self:GetParent():GetParent():ScrollUp();
  3120. end
  3121. self.clickDelay = MESSAGE_SCROLLBUTTON_SCROLL_DELAY;
  3122. end
  3123. end
  3124. end
  3125. function ChatFrame_OpenMenu()
  3126. ChatMenu:Show();
  3127. end
  3128. function ChatFrameMenu_UpdateAnchorPoint()
  3129. --Update the menu anchor point
  3130. if ( FCF_GetButtonSide(DEFAULT_CHAT_FRAME) == "right" ) then
  3131. ChatMenu:ClearAllPoints();
  3132. ChatMenu:SetPoint("BOTTOMRIGHT", ChatFrameMenuButton, "TOPLEFT");
  3133. else
  3134. ChatMenu:ClearAllPoints();
  3135. ChatMenu:SetPoint("BOTTOMLEFT", ChatFrameMenuButton, "TOPRIGHT");
  3136. end
  3137. end
  3138. function ChatFrame_SendTell(name, chatFrame)
  3139. local editBox = ChatEdit_ChooseBoxForSend(chatFrame);
  3140. --DEBUG FIXME - for now, we're not going to remove spaces from names. We need to make sure X-server still works.
  3141. -- Remove spaces from the server name for slash command parsing
  3142. --name = gsub(name, " ", "");
  3143. if ( editBox ~= ChatEdit_GetActiveWindow() ) then
  3144. ChatFrame_OpenChat(SLASH_WHISPER1.." "..name.." ", chatFrame);
  3145. else
  3146. editBox:SetText(SLASH_WHISPER1.." "..name.." ");
  3147. end
  3148. ChatEdit_ParseText(editBox, 0);
  3149. end
  3150. function ChatFrame_SendSmartTell(name, chatFrame)
  3151. local editBox = ChatEdit_ChooseBoxForSend(chatFrame);
  3152. --DEBUG FIXME - for now, we're not going to remove spaces from names. We need to make sure X-server still works.
  3153. -- Remove spaces from the server name for slash command parsing
  3154. --name = gsub(name, " ", "");
  3155. if ( editBox ~= ChatEdit_GetActiveWindow() ) then
  3156. ChatFrame_OpenChat(SLASH_SMART_WHISPER1.." "..name.." ", chatFrame);
  3157. else
  3158. editBox:SetText(SLASH_SMART_WHISPER1.." "..name.." ");
  3159. end
  3160. ChatEdit_ParseText(editBox, 0);
  3161. end
  3162. function ChatFrame_ReplyTell(chatFrame)
  3163. local editBox = ChatEdit_ChooseBoxForSend(chatFrame);
  3164. local lastTell, lastTellType = ChatEdit_GetLastTellTarget();
  3165. if ( lastTell ) then
  3166. --BN_WHISPER FIXME
  3167. editBox:SetAttribute("chatType", lastTellType);
  3168. editBox:SetAttribute("tellTarget", lastTell);
  3169. ChatEdit_UpdateHeader(editBox);
  3170. if ( editBox ~= ChatEdit_GetActiveWindow() ) then
  3171. ChatFrame_OpenChat("", chatFrame);
  3172. end
  3173. else
  3174. -- Error message
  3175. end
  3176. end
  3177. function ChatFrame_ReplyTell2(chatFrame)
  3178. local editBox = ChatEdit_ChooseBoxForSend(chatFrame);
  3179. local lastTold, lastToldType = ChatEdit_GetLastToldTarget();
  3180. if ( lastTold ) then
  3181. --BN_WHISPER FIXME
  3182. editBox:SetAttribute("chatType", lastToldType);
  3183. editBox:SetAttribute("tellTarget", lastTold);
  3184. ChatEdit_UpdateHeader(editBox);
  3185. if ( editBox ~= ChatEdit_GetActiveWindow() ) then
  3186. ChatFrame_OpenChat("", chatFrame);
  3187. end
  3188. else
  3189. -- Error message
  3190. end
  3191. end
  3192. function ChatFrame_DisplayStartupText(frame)
  3193. if ( not frame ) then
  3194. return;
  3195. end
  3196. local info = ChatTypeInfo["SYSTEM"];
  3197. local i = 1;
  3198. local text = _G["STARTUP_TEXT_LINE"..i];
  3199. while text do
  3200. frame:AddMessage(text, info.r, info.g, info.b, info.id);
  3201. i = i + 1;
  3202. text = _G["STARTUP_TEXT_LINE"..i];
  3203. end
  3204. end
  3205. function ChatFrame_DisplayHelpText(frame)
  3206. if ( not frame ) then
  3207. return;
  3208. end
  3209. local info = ChatTypeInfo["SYSTEM"];
  3210. local i = 1;
  3211. local text = _G["HELP_TEXT_LINE"..i];
  3212. while text do
  3213. frame:AddMessage(text, info.r, info.g, info.b, info.id);
  3214. i = i + 1;
  3215. text = _G["HELP_TEXT_LINE"..i];
  3216. end
  3217. end
  3218. function ChatFrame_DisplayMacroHelpText(frame)
  3219. if ( not frame ) then
  3220. return;
  3221. end
  3222. local info = ChatTypeInfo["SYSTEM"];
  3223. local i = 1;
  3224. local text = _G["MACRO_HELP_TEXT_LINE"..i];
  3225. while text do
  3226. frame:AddMessage(text, info.r, info.g, info.b, info.id);
  3227. i = i + 1;
  3228. text = _G["MACRO_HELP_TEXT_LINE"..i];
  3229. end
  3230. end
  3231. function ChatFrame_DisplayChatHelp(frame)
  3232. if ( not frame ) then
  3233. return;
  3234. end
  3235. local info = ChatTypeInfo["SYSTEM"];
  3236. local i = 1;
  3237. local text = _G["CHAT_HELP_TEXT_LINE"..i];
  3238. while text do
  3239. frame:AddMessage(text, info.r, info.g, info.b, info.id);
  3240. i = i + 1;
  3241. -- hack fix for removing a line without causing localization problems
  3242. if ( i == 15 ) then
  3243. i = i + 1;
  3244. end
  3245. text = _G["CHAT_HELP_TEXT_LINE"..i];
  3246. end
  3247. end
  3248. function ChatFrame_DisplayGuildHelp(frame)
  3249. if ( not frame ) then
  3250. return;
  3251. end
  3252. local info = ChatTypeInfo["SYSTEM"];
  3253. local i = 1;
  3254. local text = _G["GUILD_HELP_TEXT_LINE"..i];
  3255. while text do
  3256. frame:AddMessage(text, info.r, info.g, info.b, info.id);
  3257. i = i + 1;
  3258. text = _G["GUILD_HELP_TEXT_LINE"..i];
  3259. end
  3260. end
  3261. function ChatFrame_DisplayGameTime(frame)
  3262. if ( not frame ) then
  3263. return;
  3264. end
  3265. local info = ChatTypeInfo["SYSTEM"];
  3266. frame:AddMessage(GameTime_GetGameTime(true), info.r, info.g, info.b, info.id);
  3267. end
  3268. function ChatFrame_TimeBreakDown(time)
  3269. local days = floor(time / (60 * 60 * 24));
  3270. local hours = floor((time - (days * (60 * 60 * 24))) / (60 * 60));
  3271. local minutes = floor((time - (days * (60 * 60 * 24)) - (hours * (60 * 60))) / 60);
  3272. local seconds = mod(time, 60);
  3273. return days, hours, minutes, seconds;
  3274. end
  3275. function ChatFrame_DisplayTimePlayed(self, totalTime, levelTime)
  3276. local info = ChatTypeInfo["SYSTEM"];
  3277. local d;
  3278. local h;
  3279. local m;
  3280. local s;
  3281. d, h, m, s = ChatFrame_TimeBreakDown(totalTime);
  3282. local string = format(TIME_PLAYED_TOTAL, format(TIME_DAYHOURMINUTESECOND, d, h, m, s));
  3283. self:AddMessage(string, info.r, info.g, info.b, info.id);
  3284. d, h, m, s = ChatFrame_TimeBreakDown(levelTime);
  3285. local string = format(TIME_PLAYED_LEVEL, format(TIME_DAYHOURMINUTESECOND, d, h, m, s));
  3286. self:AddMessage(string, info.r, info.g, info.b, info.id);
  3287. end
  3288. function ChatFrame_ChatPageUp()
  3289. SELECTED_CHAT_FRAME:PageUp();
  3290. end
  3291. function ChatFrame_ChatPageDown()
  3292. SELECTED_CHAT_FRAME:PageDown();
  3293. end
  3294. function ChatFrame_DisplayUsageError(messageTag)
  3295. ChatFrame_DisplaySystemMessageInPrimary(messageTag);
  3296. end
  3297. function ChatFrame_DisplaySystemMessageInPrimary(messageTag)
  3298. local info = ChatTypeInfo["SYSTEM"];
  3299. DEFAULT_CHAT_FRAME:AddMessage(messageTag, info.r, info.g, info.b, info.id);
  3300. end
  3301. -- ChatEdit functions
  3302. local ChatEdit_LastTell = {};
  3303. local ChatEdit_LastTellType = {};
  3304. for i = 1, NUM_REMEMBERED_TELLS, 1 do
  3305. ChatEdit_LastTell[i] = "";
  3306. ChatEdit_LastTellType[i] = "";
  3307. end
  3308. local ChatEdit_LastTold;
  3309. local ChatEdit_LastToldType;
  3310. function ChatEdit_OnLoad(self)
  3311. self:SetFrameLevel(self.chatFrame:GetFrameLevel()+1);
  3312. self:SetAttribute("chatType", "SAY");
  3313. self:SetAttribute("stickyType", "SAY");
  3314. self.chatLanguage = GetDefaultLanguage();
  3315. self:RegisterEvent("UPDATE_CHAT_COLOR");
  3316. self.addSpaceToAutoComplete = true;
  3317. if ( CHAT_OPTIONS.ONE_EDIT_AT_A_TIME == "many" ) then
  3318. self:Show();
  3319. end
  3320. end
  3321. function ChatEdit_OnEvent(self, event, ...)
  3322. if ( event == "UPDATE_CHAT_COLOR" ) then
  3323. local chatType = ...;
  3324. if ( self:IsShown() ) then
  3325. ChatEdit_UpdateHeader(self);
  3326. end
  3327. end
  3328. end
  3329. function ChatEdit_OnUpdate(self, elapsedSec)
  3330. if ( self.setText == 1) then
  3331. self:SetText(self.text);
  3332. self.setText = 0;
  3333. ChatEdit_ParseText(self, 0, true);
  3334. end
  3335. end
  3336. function ChatEdit_OnShow(self)
  3337. ChatEdit_ResetChatType(self);
  3338. end
  3339. function ChatEdit_ResetChatType(self)
  3340. if ( self:GetAttribute("chatType") == "PARTY" and (not IsInGroup(LE_PARTY_CATEGORY_HOME)) ) then
  3341. self:SetAttribute("chatType", "SAY");
  3342. end
  3343. if ( self:GetAttribute("chatType") == "RAID" and (not IsInRaid(LE_PARTY_CATEGORY_HOME)) ) then
  3344. self:SetAttribute("chatType", "SAY");
  3345. end
  3346. if ( (self:GetAttribute("chatType") == "GUILD" or self:GetAttribute("chatType") == "OFFICER") and not IsInGuild() ) then
  3347. self:SetAttribute("chatType", "SAY");
  3348. end
  3349. if ( self:GetAttribute("chatType") == "INSTANCE_CHAT" and (not IsInGroup(LE_PARTY_CATEGORY_INSTANCE)) ) then
  3350. self:SetAttribute("chatType", "SAY");
  3351. end
  3352. self.lastTabComplete = nil;
  3353. self.tabCompleteText = nil;
  3354. self.tabCompleteTableIndex = 1;
  3355. ChatEdit_UpdateHeader(self);
  3356. ChatEdit_OnInputLanguageChanged(self);
  3357. --[[if ( CHAT_OPTIONS.ONE_EDIT_AT_A_TIME == "old") then
  3358. self:SetFocus();
  3359. end]]
  3360. end
  3361. function ChatEdit_OnHide(self)
  3362. if ( ACTIVE_CHAT_EDIT_BOX == self ) then
  3363. ChatEdit_DeactivateChat(self);
  3364. end
  3365. if ( LAST_ACTIVE_CHAT_EDIT_BOX == self and self:IsShown() ) then --Our parent was hidden. Let's find a new default frame.
  3366. --We'll go with the active dock frame since people think of that as the primary chat.
  3367. ChatEdit_SetLastActiveWindow(FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK).editBox);
  3368. end
  3369. end
  3370. function ChatEdit_OnEditFocusGained(self)
  3371. ChatEdit_ActivateChat(self);
  3372. end
  3373. function ChatEdit_OnEditFocusLost(self)
  3374. AutoCompleteEditBox_OnEditFocusLost(self);
  3375. ChatEdit_DeactivateChat(self);
  3376. end
  3377. function ChatEdit_ActivateChat(editBox)
  3378. if ( ACTIVE_CHAT_EDIT_BOX and ACTIVE_CHAT_EDIT_BOX ~= editBox ) then
  3379. ChatEdit_DeactivateChat(ACTIVE_CHAT_EDIT_BOX);
  3380. end
  3381. ACTIVE_CHAT_EDIT_BOX = editBox;
  3382. ChatEdit_SetLastActiveWindow(editBox);
  3383. --Stop any sort of fading
  3384. UIFrameFadeRemoveFrame(editBox);
  3385. editBox:Show();
  3386. editBox:SetFocus();
  3387. editBox:SetFrameStrata("DIALOG");
  3388. editBox:Raise();
  3389. editBox.header:Show();
  3390. editBox.focusLeft:Show();
  3391. editBox.focusRight:Show();
  3392. editBox.focusMid:Show();
  3393. editBox:SetAlpha(1.0);
  3394. ChatEdit_UpdateHeader(editBox);
  3395. if ( CHAT_SHOW_IME ) then
  3396. _G[editBox:GetName().."Language"]:Show();
  3397. end
  3398. end
  3399. local function ChatEdit_SetDeactivated(editBox)
  3400. editBox:SetFrameStrata("LOW");
  3401. if ( GetCVar("chatStyle") == "classic" and not editBox.isGM ) then
  3402. editBox:Hide();
  3403. else
  3404. editBox:SetText("");
  3405. editBox.header:Hide();
  3406. if ( not editBox.isGM ) then
  3407. editBox:SetAlpha(0.35);
  3408. end
  3409. editBox:ClearFocus();
  3410. editBox.focusLeft:Hide();
  3411. editBox.focusRight:Hide();
  3412. editBox.focusMid:Hide();
  3413. ChatEdit_ResetChatTypeToSticky(editBox);
  3414. ChatEdit_ResetChatType(editBox);
  3415. end
  3416. _G[editBox:GetName().."Language"]:Hide();
  3417. end
  3418. function ChatEdit_DeactivateChat(editBox)
  3419. if ( ACTIVE_CHAT_EDIT_BOX == editBox ) then
  3420. ACTIVE_CHAT_EDIT_BOX = nil;
  3421. end
  3422. ChatEdit_SetDeactivated(editBox);
  3423. end
  3424. function ChatEdit_ChooseBoxForSend(preferredChatFrame)
  3425. if ( GetCVar("chatStyle") == "classic" ) then
  3426. return DEFAULT_CHAT_FRAME.editBox;
  3427. elseif ( preferredChatFrame and preferredChatFrame:IsShown() ) then
  3428. return preferredChatFrame.editBox;
  3429. elseif ( ChatEdit_GetLastActiveWindow() and ChatEdit_GetLastActiveWindow():GetParent():IsShown() ) then
  3430. return ChatEdit_GetLastActiveWindow();
  3431. else
  3432. return FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK).editBox;
  3433. end
  3434. end
  3435. function ChatEdit_SetLastActiveWindow(editBox)
  3436. local previousValue = LAST_ACTIVE_CHAT_EDIT_BOX;
  3437. if ( LAST_ACTIVE_CHAT_EDIT_BOX and not LAST_ACTIVE_CHAT_EDIT_BOX.isGM and LAST_ACTIVE_CHAT_EDIT_BOX ~= editBox ) then
  3438. if ( GetCVar("chatStyle") == "im" ) then
  3439. LAST_ACTIVE_CHAT_EDIT_BOX:Hide();
  3440. end
  3441. end
  3442. LAST_ACTIVE_CHAT_EDIT_BOX = editBox;
  3443. if ( GetCVar("chatStyle") == "im" and ACTIVE_CHAT_EDIT_BOX ~= editBox ) then
  3444. editBox:Show();
  3445. ChatEdit_SetDeactivated(editBox);
  3446. end
  3447. if ( previousValue ) then
  3448. FCFClickAnywhereButton_UpdateState(previousValue.chatFrame.clickAnywhereButton);
  3449. end
  3450. FCFClickAnywhereButton_UpdateState(editBox.chatFrame.clickAnywhereButton);
  3451. end
  3452. function ChatEdit_GetActiveWindow()
  3453. return ACTIVE_CHAT_EDIT_BOX;
  3454. end
  3455. function ChatEdit_GetLastActiveWindow()
  3456. return LAST_ACTIVE_CHAT_EDIT_BOX;
  3457. end
  3458. function ChatEdit_FocusActiveWindow()
  3459. local active = ChatEdit_GetActiveWindow()
  3460. if ( active ) then
  3461. ChatEdit_ActivateChat(active);
  3462. end
  3463. end
  3464. function ChatEdit_InsertLink(text)
  3465. if ( not text ) then
  3466. return false;
  3467. end
  3468. local activeWindow = ChatEdit_GetActiveWindow();
  3469. if ( activeWindow ) then
  3470. -- add a space for proper parsing
  3471. activeWindow:Insert(" "..text);
  3472. return true;
  3473. end
  3474. if ( BrowseName and BrowseName:IsVisible() ) then
  3475. local item;
  3476. if ( strfind(text, "battlepet:") ) then
  3477. local petName = strmatch(text, "%[(.+)%]");
  3478. item = petName;
  3479. elseif ( strfind(text, "item:", 1, true) ) then
  3480. item = GetItemInfo(text);
  3481. end
  3482. if ( item ) then
  3483. BrowseName:SetText(item);
  3484. return true;
  3485. end
  3486. end
  3487. if ( MacroFrameText and MacroFrameText:HasFocus() ) then
  3488. local item;
  3489. if ( strfind(text, "item:", 1, true) ) then
  3490. item = GetItemInfo(text);
  3491. end
  3492. local cursorPosition = MacroFrameText:GetCursorPosition();
  3493. if (cursorPosition == 0 or strsub(MacroFrameText:GetText(), cursorPosition, cursorPosition) == "\n" ) then
  3494. if ( item ) then
  3495. if ( GetItemSpell(text) ) then
  3496. MacroFrameText:Insert(SLASH_USE1.." "..item.."\n");
  3497. else
  3498. MacroFrameText:Insert(SLASH_EQUIP1.." "..item.."\n");
  3499. end
  3500. else
  3501. MacroFrameText:Insert(SLASH_CAST1.." "..text.."\n");
  3502. end
  3503. else
  3504. MacroFrameText:Insert(item or text);
  3505. end
  3506. return true;
  3507. end
  3508. if ( TradeSkillFrame and TradeSkillFrame:IsShown() ) then
  3509. local item;
  3510. if ( strfind(text, "item:", 1, true) ) then
  3511. item = GetItemInfo(text);
  3512. end
  3513. if ( item ) then
  3514. TradeSkillFrameSearchBox:SetFontObject("ChatFontSmall");
  3515. TradeSkillFrameSearchBoxSearchIcon:SetVertexColor(1.0, 1.0, 1.0);
  3516. TradeSkillFrameSearchBox:SetText(item);
  3517. return true;
  3518. end
  3519. end
  3520. return false;
  3521. end
  3522. function ChatEdit_GetLastTellTarget()
  3523. for i=1, #ChatEdit_LastTell do
  3524. local value = ChatEdit_LastTell[i];
  3525. if ( value ~= "" ) then
  3526. return value, ChatEdit_LastTellType[i];
  3527. end
  3528. end
  3529. return nil;
  3530. end
  3531. function ChatEdit_SetLastTellTarget(target, chatType)
  3532. local found = #ChatEdit_LastTell;
  3533. for i=1, #ChatEdit_LastTell do
  3534. local tellTarget, tellChatType = ChatEdit_LastTell[i], ChatEdit_LastTellType[i];
  3535. if ( strupper(target) == strupper(tellTarget) and strupper(chatType) == strupper(tellChatType) ) then
  3536. found = i;
  3537. break;
  3538. end
  3539. end
  3540. for i = found, 2, -1 do
  3541. ChatEdit_LastTell[i] = ChatEdit_LastTell[i-1];
  3542. ChatEdit_LastTellType[i] = ChatEdit_LastTellType[i-1];
  3543. end
  3544. ChatEdit_LastTell[1] = target;
  3545. ChatEdit_LastTellType[1] = chatType;
  3546. end
  3547. function ChatEdit_GetNextTellTarget(target, chatType)
  3548. if ( not target or target == "" ) then
  3549. return ChatEdit_LastTell[1], ChatEdit_LastTellType[1];
  3550. end
  3551. for i = 1, #ChatEdit_LastTell - 1, 1 do
  3552. if ( ChatEdit_LastTell[i] == "" ) then
  3553. break;
  3554. elseif ( strupper(target) == strupper(ChatEdit_LastTell[i]) and
  3555. strupper(chatType) == strupper(ChatEdit_LastTellType[i]) ) then
  3556. if ( ChatEdit_LastTell[i+1] ~= "" ) then
  3557. return ChatEdit_LastTell[i+1], ChatEdit_LastTellType[i+1];
  3558. else
  3559. break;
  3560. end
  3561. end
  3562. end
  3563. return ChatEdit_LastTell[1], ChatEdit_LastTellType[1];
  3564. end
  3565. function ChatEdit_GetLastToldTarget()
  3566. return ChatEdit_LastTold, ChatEdit_LastToldType;
  3567. end
  3568. function ChatEdit_SetLastToldTarget(name, chatType)
  3569. ChatEdit_LastTold = name;
  3570. ChatEdit_LastToldType = chatType;
  3571. end
  3572. function ChatEdit_UpdateHeader(editBox)
  3573. local type = editBox:GetAttribute("chatType");
  3574. if ( not type ) then
  3575. return;
  3576. end
  3577. local info = ChatTypeInfo[type];
  3578. local header = _G[editBox:GetName().."Header"];
  3579. local headerSuffix = _G[editBox:GetName().."HeaderSuffix"];
  3580. if ( not header ) then
  3581. return;
  3582. end
  3583. header:SetWidth(0);
  3584. --BN_WHISPER FIXME
  3585. if ( type == "SMART_WHISPER" ) then
  3586. --If we have a BN presence ID for this name, it's a BN whisper.
  3587. if ( BNet_GetPresenceID(editBox:GetAttribute("tellTarget")) ) then
  3588. editBox:SetAttribute("chatType", "BN_WHISPER");
  3589. else
  3590. editBox:SetAttribute("chatType", "WHISPER");
  3591. end
  3592. ChatEdit_UpdateHeader(editBox);
  3593. return;
  3594. elseif ( type == "WHISPER" ) then
  3595. header:SetFormattedText(CHAT_WHISPER_SEND, editBox:GetAttribute("tellTarget"));
  3596. elseif ( type == "BN_WHISPER" ) then
  3597. local name = editBox:GetAttribute("tellTarget");
  3598. header:SetFormattedText(CHAT_BN_WHISPER_SEND, name);
  3599. elseif ( type == "EMOTE" ) then
  3600. header:SetFormattedText(CHAT_EMOTE_SEND, UnitName("player"));
  3601. elseif ( type == "CHANNEL" ) then
  3602. local channel, channelName, instanceID = GetChannelName(editBox:GetAttribute("channelTarget"));
  3603. if ( channelName ) then
  3604. if ( instanceID > 0 ) then
  3605. channelName = channelName.." "..instanceID;
  3606. end
  3607. info = ChatTypeInfo["CHANNEL"..channel];
  3608. editBox:SetAttribute("channelTarget", channel);
  3609. header:SetFormattedText(CHAT_CHANNEL_SEND, channel, channelName);
  3610. end
  3611. elseif ( type == "BN_CONVERSATION" ) then
  3612. local conversationID = editBox:GetAttribute("channelTarget");
  3613. header:SetFormattedText(CHAT_BN_CONVERSATION_SEND, conversationID + MAX_WOW_CHAT_CHANNELS);
  3614. elseif ( (type == "PARTY") and
  3615. (not IsInGroup(LE_PARTY_CATEGORY_HOME) and IsInGroup(LE_PARTY_CATEGORY_INSTANCE)) ) then
  3616. --Smartly switch to instance chat
  3617. editBox:SetAttribute("chatType", "INSTANCE_CHAT");
  3618. ChatEdit_UpdateHeader(editBox);
  3619. return;
  3620. elseif ( (type == "RAID") and
  3621. (not IsInRaid(LE_PARTY_CATEGORY_HOME) and IsInRaid(LE_PARTY_CATEGORY_INSTANCE)) ) then
  3622. --Smartly switch to instance chat
  3623. editBox:SetAttribute("chatType", "INSTANCE_CHAT");
  3624. ChatEdit_UpdateHeader(editBox);
  3625. return;
  3626. elseif ( (type == "INSTANCE_CHAT") and
  3627. (IsInGroup(LE_PARTY_CATEGORY_HOME) and not IsInGroup(LE_PARTY_CATEGORY_INSTANCE)) )then
  3628. if ( IsInRaid(LE_PARTY_CATEGORY_HOME) ) then
  3629. editBox:SetAttribute("chatType", "RAID");
  3630. else
  3631. editBox:SetAttribute("chatType", "PARTY");
  3632. end
  3633. ChatEdit_UpdateHeader(editBox);
  3634. return;
  3635. else
  3636. header:SetText(_G["CHAT_"..type.."_SEND"]);
  3637. end
  3638. local headerWidth = (header:GetRight() or 0) - (header:GetLeft() or 0);
  3639. local editBoxWidth = editBox:GetRight() - editBox:GetLeft();
  3640. if ( headerWidth > editBoxWidth / 2 ) then
  3641. header:SetWidth(editBoxWidth / 2);
  3642. headerSuffix:Show();
  3643. else
  3644. headerSuffix:Hide();
  3645. end
  3646. header:SetTextColor(info.r, info.g, info.b);
  3647. headerSuffix:SetTextColor(info.r, info.g, info.b);
  3648. editBox:SetTextInsets(15 + header:GetWidth() + (headerSuffix:IsShown() and headerSuffix:GetWidth() or 0), 13, 0, 0);
  3649. editBox:SetTextColor(info.r, info.g, info.b);
  3650. editBox.focusLeft:SetVertexColor(info.r, info.g, info.b);
  3651. editBox.focusRight:SetVertexColor(info.r, info.g, info.b);
  3652. editBox.focusMid:SetVertexColor(info.r, info.g, info.b);
  3653. end
  3654. function ChatEdit_AddHistory(editBox)
  3655. local text = "";
  3656. local type = editBox:GetAttribute("chatType");
  3657. local header = _G["SLASH_"..type.."1"];
  3658. if ( header ) then
  3659. text = header;
  3660. end
  3661. if ( type == "WHISPER" ) then
  3662. text = text.." "..editBox:GetAttribute("tellTarget");
  3663. elseif ( type == "CHANNEL" ) then
  3664. text = "/"..editBox:GetAttribute("channelTarget");
  3665. end
  3666. local editBoxText = editBox:GetText();
  3667. if ( strlen(editBoxText) > 0 ) then
  3668. text = text.." "..editBox:GetText();
  3669. end
  3670. if ( strlen(text) > 0 ) then
  3671. editBox:AddHistoryLine(text);
  3672. end
  3673. end
  3674. function ChatEdit_SendText(editBox, addHistory)
  3675. ChatEdit_ParseText(editBox, 1);
  3676. local type = editBox:GetAttribute("chatType");
  3677. local text = editBox:GetText();
  3678. if ( strfind(text, "%s*[^%s]+") ) then
  3679. text = SubstituteChatMessageBeforeSend(text);
  3680. --BN_WHISPER FIXME
  3681. if ( type == "WHISPER") then
  3682. local target = editBox:GetAttribute("tellTarget");
  3683. ChatEdit_SetLastToldTarget(target, type);
  3684. SendChatMessage(text, type, editBox.languageID, target);
  3685. elseif ( type == "BN_WHISPER" ) then
  3686. local target = editBox:GetAttribute("tellTarget");
  3687. local presenceID = BNet_GetPresenceID(target);
  3688. if ( presenceID ) then
  3689. ChatEdit_SetLastToldTarget(target, type);
  3690. BNSendWhisper(presenceID, text);
  3691. else
  3692. local info = ChatTypeInfo["SYSTEM"]
  3693. editBox.chatFrame:AddMessage(format(BN_UNABLE_TO_RESOLVE_NAME, target), info.r, info.g, info.b);
  3694. end
  3695. elseif ( type == "BN_CONVERSATION" ) then
  3696. local target = tonumber(editBox:GetAttribute("channelTarget"));
  3697. BNSendConversationMessage(target, text);
  3698. elseif ( type == "CHANNEL") then
  3699. SendChatMessage(text, type, editBox.languageID, editBox:GetAttribute("channelTarget"));
  3700. else
  3701. SendChatMessage(text, type, editBox.languageID);
  3702. end
  3703. if ( addHistory ) then
  3704. ChatEdit_AddHistory(editBox);
  3705. end
  3706. end
  3707. end
  3708. function ChatEdit_OnEnterPressed(self)
  3709. if(AutoCompleteEditBox_OnEnterPressed(self)) then
  3710. return;
  3711. end
  3712. ChatEdit_SendText(self, 1);
  3713. local type = self:GetAttribute("chatType");
  3714. local chatFrame = self:GetParent();
  3715. if ( chatFrame.isTemporary and chatFrame.chatType ~= "PET_BATTLE_COMBAT_LOG" ) then --Temporary window sticky types never change.
  3716. self:SetAttribute("stickyType", chatFrame.chatType);
  3717. --BN_WHISPER FIXME
  3718. if ( chatFrame.chatType == "WHISPER" or chatFrame.chatType == "BN_WHISPER" ) then
  3719. self:SetAttribute("tellTarget", chatFrame.chatTarget);
  3720. end
  3721. elseif ( ChatTypeInfo[type].sticky == 1 ) then
  3722. self:SetAttribute("stickyType", type);
  3723. end
  3724. ChatEdit_OnEscapePressed(self);
  3725. end
  3726. function ChatEdit_OnEscapePressed(editBox)
  3727. if ( not AutoCompleteEditBox_OnEscapePressed(editBox) ) then
  3728. ChatEdit_ResetChatTypeToSticky(editBox);
  3729. if ( not editBox.isGM and (GetCVar("chatStyle") ~= "im" or editBox == MacroEditBox) ) then
  3730. editBox:SetText("");
  3731. editBox:Hide();
  3732. else
  3733. ChatEdit_DeactivateChat(editBox);
  3734. end
  3735. end
  3736. end
  3737. function ChatEdit_ResetChatTypeToSticky(editBox)
  3738. editBox:SetAttribute("chatType", editBox:GetAttribute("stickyType"));
  3739. end
  3740. function ChatEdit_OnSpacePressed(self)
  3741. ChatEdit_ParseText(self, 0);
  3742. end
  3743. function ChatEdit_CustomTabPressed(self)
  3744. end
  3745. local tabCompleteTables = { hash_ChatTypeInfoList, hash_EmoteTokenList };
  3746. function ChatEdit_SecureTabPressed(self)
  3747. local chatType = self:GetAttribute("chatType");
  3748. if ( chatType == "WHISPER" or chatType == "BN_WHISPER" ) then
  3749. local newTarget, newTargetType = ChatEdit_GetNextTellTarget(self:GetAttribute("tellTarget"), chatType);
  3750. if ( newTarget and newTarget ~= "" ) then
  3751. self:SetAttribute("chatType", newTargetType);
  3752. self:SetAttribute("tellTarget", newTarget);
  3753. ChatEdit_UpdateHeader(self);
  3754. end
  3755. return;
  3756. end
  3757. local text = self.tabCompleteText;
  3758. if ( not text ) then
  3759. text = self:GetText();
  3760. self.tabCompleteText = text;
  3761. end
  3762. if ( strsub(text, 1, 1) ~= "/" ) then
  3763. return;
  3764. end
  3765. ChatFrame_ImportAllListsToHash();
  3766. local lastTabComplete = self.lastTabComplete;
  3767. -- If the string is in the format "/cmd blah", command will be "/cmd"
  3768. local command = strmatch(text, "^(/[^%s]+)") or "";
  3769. local cmdString = lastTabComplete;
  3770. repeat --The outer loop lets us go through multiple hash tables of commands.
  3771. repeat --Loop through this table to find matching items.
  3772. cmdString = next(tabCompleteTables[self.tabCompleteTableIndex], cmdString);
  3773. until ( not cmdString or strfind(cmdString, strupper(command), 1, 1) ); --Either we finished going through this table or we found a match.
  3774. if ( not cmdString ) then --Nothing else in the current table, move to the next one.
  3775. self.tabCompleteTableIndex = self.tabCompleteTableIndex + 1;
  3776. end
  3777. until ( cmdString or self.tabCompleteTableIndex > #tabCompleteTables );
  3778. self.lastTabComplete = cmdString;
  3779. if ( cmdString ) then
  3780. self.ignoreTextChange = 1;
  3781. self:SetText(strlower(cmdString));
  3782. else
  3783. self.tabCompleteTableIndex = 1;
  3784. self:SetText(self.tabCompleteText);
  3785. end
  3786. end
  3787. function ChatEdit_OnTabPressed(self)
  3788. if ( not AutoCompleteEditBox_OnTabPressed(self) ) then
  3789. if ( securecall("ChatEdit_CustomTabPressed", self) ) then
  3790. return;
  3791. end
  3792. ChatEdit_SecureTabPressed(self);
  3793. end
  3794. end
  3795. function ChatEdit_OnTextChanged(self, userInput)
  3796. ChatEdit_ParseText(self, 0);
  3797. if ( not self.ignoreTextChange ) then
  3798. self.lastTabComplete = nil;
  3799. self.tabCompleteText = nil;
  3800. self.tabCompleteTableIndex = 1;
  3801. end
  3802. self.ignoreTextChange = nil;
  3803. local regex = "^((/[^%s]+)%s+)(.+)"
  3804. local full, command, target = strmatch(self:GetText(), regex);
  3805. if ( not target or (strsub(target, 1, 1) == "|") ) then
  3806. AutoComplete_HideIfAttachedTo(self);
  3807. return;
  3808. end
  3809. if ( userInput ) then
  3810. self.autoCompleteRegex = regex;
  3811. self.autoCompleteFormatRegex = "%2$s%1$s"
  3812. self.autoCompleteXOffset = 35;
  3813. AutoComplete_Update(self, target, self:GetUTF8CursorPosition() - strlenutf8(command) - 1);
  3814. end
  3815. end
  3816. function ChatEdit_OnTextSet(self)
  3817. ChatEdit_ParseText(self, 0);
  3818. end
  3819. function ChatEdit_LanguageShow()
  3820. CHAT_SHOW_IME = true;
  3821. end
  3822. function ChatEdit_OnInputLanguageChanged(self)
  3823. local button = _G[self:GetName().."Language"];
  3824. local variable = _G["INPUT_"..self:GetInputLanguage()];
  3825. button:SetText(variable);
  3826. end
  3827. local function processChatType(editBox, msg, index, send)
  3828. editBox.autoCompleteParams = AUTOCOMPLETE_LIST[index];
  3829. -- this is a special function for "ChatEdit_HandleChatType"
  3830. if ( ChatTypeInfo[index] ) then
  3831. if ( index == "WHISPER" or index == "SMART_WHISPER" ) then
  3832. local targetFound, target, chatType, parsedMsg = ChatEdit_ExtractTellTarget(editBox, msg, index);
  3833. if ( targetFound ) then
  3834. editBox:SetAttribute("tellTarget", target);
  3835. editBox:SetAttribute("chatType", chatType);
  3836. editBox:SetText(parsedMsg);
  3837. ChatEdit_UpdateHeader(editBox);
  3838. elseif ( send == 1 ) then
  3839. ChatEdit_OnEscapePressed(editBox);
  3840. end
  3841. elseif ( index == "REPLY" ) then
  3842. local lastTell, lastTellType = ChatEdit_GetLastTellTarget();
  3843. if ( lastTell ) then
  3844. --BN_WHISPER FIXME
  3845. editBox:SetAttribute("chatType", lastTellType);
  3846. editBox:SetAttribute("tellTarget", lastTell);
  3847. editBox:SetText(msg);
  3848. ChatEdit_UpdateHeader(editBox);
  3849. else
  3850. if ( send == 1 ) then
  3851. ChatEdit_OnEscapePressed(editBox);
  3852. end
  3853. end
  3854. elseif (index == "CHANNEL") then
  3855. ChatEdit_ExtractChannel(editBox, msg);
  3856. elseif ( index == "BN_CONVERSATION" ) then
  3857. ChatEdit_ExtractBNConversation(editBox, msg);
  3858. else
  3859. editBox:SetAttribute("chatType", index);
  3860. editBox:SetText(msg);
  3861. ChatEdit_UpdateHeader(editBox);
  3862. end
  3863. return true;
  3864. end
  3865. return false;
  3866. end
  3867. function ChatEdit_HandleChatType(editBox, msg, command, send)
  3868. local channel = strmatch(command, "/([0-9]+)");
  3869. if( channel ) then
  3870. local chanNum = tonumber(channel);
  3871. if ( chanNum > 0 and chanNum <= MAX_WOW_CHAT_CHANNELS ) then
  3872. local channelNum, channelName = GetChannelName(channel);
  3873. if ( channelNum > 0 ) then
  3874. editBox:SetAttribute("channelTarget", channelNum);
  3875. editBox:SetAttribute("chatType", "CHANNEL");
  3876. editBox:SetText(msg);
  3877. ChatEdit_UpdateHeader(editBox);
  3878. return true;
  3879. end
  3880. elseif ( chanNum > MAX_WOW_CHAT_CHANNELS ) then --This is a B.Net chat.
  3881. local conversationNum = chanNum - MAX_WOW_CHAT_CHANNELS;
  3882. if ( BNGetConversationInfo(conversationNum) ) then
  3883. editBox:SetAttribute("channelTarget", conversationNum);
  3884. editBox:SetAttribute("chatType", "BN_CONVERSATION");
  3885. editBox:SetText(msg);
  3886. ChatEdit_UpdateHeader(editBox);
  3887. return true;
  3888. end
  3889. end
  3890. else
  3891. -- first check the hash table
  3892. ChatFrame_ImportAllListsToHash();
  3893. if ( hash_ChatTypeInfoList[command] ) then
  3894. return processChatType(editBox, msg, hash_ChatTypeInfoList[command], send);
  3895. end
  3896. end
  3897. --This isn't one we found in our list, so we're not going to autocomplete.
  3898. editBox.autoCompleteParams = nil;
  3899. return false;
  3900. end
  3901. function ChatEdit_ParseText(editBox, send, parseIfNoSpaces)
  3902. local text = editBox:GetText();
  3903. if ( strlen(text) <= 0 ) then
  3904. return;
  3905. end
  3906. if ( strsub(text, 1, 1) ~= "/" ) then
  3907. return;
  3908. end
  3909. --Do not bother parsing if there is no space in the message and we aren't sending.
  3910. if ( send ~= 1 and not parseIfNoSpaces and not strfind(text, "%s") ) then
  3911. return;
  3912. end
  3913. -- If the string is in the format "/cmd blah", command will be "/cmd"
  3914. local command = strmatch(text, "^(/[^%s]+)") or "";
  3915. local msg = "";
  3916. if ( command ~= text ) then
  3917. msg = strsub(text, strlen(command) + 2);
  3918. end
  3919. command = strupper(command);
  3920. -- Check and see if we've got secure commands to run before we look for chat types or slash commands.
  3921. -- This hash table is prepopulated, unlike the other ones, since nobody can add secure commands. (See line 1205 or thereabouts)
  3922. -- We don't want this code to run unless send is 1, but we need ChatEdit_HandleChatType to run when send is 1 as well, which is why we
  3923. -- didn't just move ChatEdit_HandleChatType inside the send == 0 conditional, which could have also solved the problem with insecure
  3924. -- code having the ability to affect secure commands.
  3925. if ( send == 1 and hash_SecureCmdList[command] ) then
  3926. hash_SecureCmdList[command](strtrim(msg));
  3927. editBox:AddHistoryLine(text);
  3928. ChatEdit_OnEscapePressed(editBox);
  3929. return;
  3930. end
  3931. ChatFrame_ImportAllListsToHash();
  3932. -- Handle chat types. No need for a securecall here, since we should be done with anything secure.
  3933. if ( ChatEdit_HandleChatType(editBox, msg, command, send) ) then
  3934. return;
  3935. end
  3936. if ( send == 0 ) then
  3937. return;
  3938. end
  3939. -- Check the hash tables for slash commands and emotes to see if we've run this before.
  3940. if ( hash_SlashCmdList[command] ) then
  3941. -- if the code in here changes - change the corresponding code below
  3942. hash_SlashCmdList[command](strtrim(msg), editBox);
  3943. editBox:AddHistoryLine(text);
  3944. ChatEdit_OnEscapePressed(editBox);
  3945. return;
  3946. elseif ( hash_EmoteTokenList[command] ) then
  3947. -- if the code in here changes - change the corresponding code below
  3948. DoEmote(hash_EmoteTokenList[command], msg);
  3949. editBox:AddHistoryLine(text);
  3950. ChatEdit_OnEscapePressed(editBox);
  3951. return;
  3952. end
  3953. -- Unrecognized chat command, show simple help text
  3954. if ( editBox.chatFrame ) then
  3955. local info = ChatTypeInfo["SYSTEM"];
  3956. editBox.chatFrame:AddMessage(HELP_TEXT_SIMPLE, info.r, info.g, info.b, info.id);
  3957. end
  3958. -- Reset the chat type and clear the edit box's contents
  3959. ChatEdit_OnEscapePressed(editBox);
  3960. return;
  3961. end
  3962. function SubstituteChatMessageBeforeSend(msg)
  3963. for tag in string.gmatch(msg, "%b{}") do
  3964. local term = strlower(string.gsub(tag, "[{}]", ""));
  3965. if ( GROUP_TAG_LIST[term] ) then
  3966. local groupIndex = GROUP_TAG_LIST[term];
  3967. msg = string.gsub(msg, tag, "{"..GROUP_LANGUAGE_INDEPENDENT_STRINGS[groupIndex].."}");
  3968. end
  3969. end
  3970. return msg;
  3971. end
  3972. function ChatEdit_ExtractTellTarget(editBox, msg, chatType)
  3973. local tellTargetExtractionAutoComplete;
  3974. if ( chatType == "WHISPER" ) then
  3975. tellTargetExtractionAutoComplete = AUTOCOMPLETE_LIST.WHISPER_EXTRACT;
  3976. else
  3977. tellTargetExtractionAutoComplete = AUTOCOMPLETE_LIST.SMART_WHISPER_EXTRACT;
  3978. end
  3979. -- Grab the string after the slash command
  3980. local target = strmatch(msg, "%s*(.*)");
  3981. --If we haven't even finished one word, we aren't done.
  3982. if ( not target or not strfind(target, "%s") ) then
  3983. return false;
  3984. end
  3985. if((strsub(target, 1, 1) == "|") and not(strsub(target, 1, 2) == "|K")) then
  3986. return false;
  3987. end
  3988. if ( GetAutoCompleteResults(target, tellTargetExtractionAutoComplete.include, tellTargetExtractionAutoComplete.exclude, 1, nil, true) ) then
  3989. --Even if there's a space, we still want to let the person keep typing -- they may be trying to type whatever is in AutoComplete.
  3990. return false;
  3991. end
  3992. if(strsub(target, 1, 2) == "|K") then
  3993. target, msg = BNTokenFindName(target);
  3994. --If there is a space just after the name (to trigger a parse), remove it.
  3995. if ( strsub(msg, 1, 1) == " " ) then
  3996. msg = strsub(msg, 2);
  3997. end
  3998. else
  3999. --Keep pulling off everything after the last space until we either have something on the AutoComplete list or only a single word is left.
  4000. while ( strfind(target, "%s") ) do
  4001. --Pull off everything after the last space.
  4002. target = strmatch(target, "(.+)%s+[^%s]*");
  4003. if ( GetAutoCompleteResults(target, tellTargetExtractionAutoComplete.include, tellTargetExtractionAutoComplete.exclude, 1, nil, true) ) then
  4004. break;
  4005. end
  4006. end
  4007. msg = strsub(msg, strlen(target) + 2);
  4008. end
  4009. if ( chatType ~= "WHISPER" and BNet_GetPresenceID(target) ) then --"WHISPER" forces character whisper
  4010. chatType = "BN_WHISPER";
  4011. else
  4012. chatType = "WHISPER";
  4013. end
  4014. return true, target, chatType, msg;
  4015. end
  4016. function ChatEdit_ExtractChannel(editBox, msg)
  4017. local target = strmatch(msg, "%s*([^%s]+)");
  4018. if ( not target ) then
  4019. return;
  4020. end
  4021. local channelNum, channelName = GetChannelName(target);
  4022. if ( channelNum <= 0 ) then
  4023. return;
  4024. end
  4025. msg = strsub(msg, strlen(target) + 2);
  4026. editBox:SetAttribute("channelTarget", channelNum);
  4027. editBox:SetAttribute("chatType", "CHANNEL");
  4028. editBox:SetText(msg);
  4029. ChatEdit_UpdateHeader(editBox);
  4030. end
  4031. function ChatEdit_ExtractBNConversation(editBox, msg)
  4032. local target = tonumber(strmatch(msg, "%s*(%d+)"));
  4033. if ( not target ) then
  4034. return;
  4035. end
  4036. local conversationType = BNGetConversationInfo(target);
  4037. if ( not conversationType ) then
  4038. return;
  4039. end
  4040. msg = strsub(msg, strlen(tostring(target)) + 2);
  4041. editBox:SetAttribute("channelTarget", target);
  4042. editBox:SetAttribute("chatType", "BN_CONVERSATION");
  4043. editBox:SetText(msg);
  4044. ChatEdit_UpdateHeader(editBox);
  4045. end
  4046. -- Chat menu functions
  4047. function ChatMenu_SetChatType(chatFrame, type)
  4048. local editBox = ChatFrame_OpenChat("");
  4049. editBox:SetAttribute("chatType", type);
  4050. ChatEdit_UpdateHeader(editBox);
  4051. end
  4052. function ChatMenu_Say(self)
  4053. ChatMenu_SetChatType(self:GetParent().chatFrame, "SAY");
  4054. end
  4055. function ChatMenu_Party(self)
  4056. ChatMenu_SetChatType(self:GetParent().chatFrame, "PARTY");
  4057. end
  4058. function ChatMenu_Raid(self)
  4059. ChatMenu_SetChatType(self:GetParent().chatFrame, "RAID");
  4060. end
  4061. function ChatMenu_InstanceChat(self)
  4062. ChatMenu_SetChatType(self:GetParent().chatFrame, "INSTANCE_CHAT");
  4063. end
  4064. function ChatMenu_Guild(self)
  4065. ChatMenu_SetChatType(self:GetParent().chatFrame, "GUILD");
  4066. end
  4067. function ChatMenu_Yell(self)
  4068. ChatMenu_SetChatType(self:GetParent().chatFrame, "YELL");
  4069. end
  4070. function ChatMenu_Whisper(self)
  4071. local editBox = ChatFrame_OpenChat(SLASH_SMART_WHISPER1.." ", chatFrame);
  4072. editBox:SetText(SLASH_SMART_WHISPER1.." "..editBox:GetText());
  4073. end
  4074. function ChatMenu_Emote(self)
  4075. ChatMenu_SetChatType(self:GetParent().chatFrame, "EMOTE");
  4076. end
  4077. function ChatMenu_Reply(self)
  4078. ChatFrame_ReplyTell();
  4079. end
  4080. function ChatMenu_VoiceMacro(self)
  4081. ChatMenu_SetChatType(self:GetParent().chatFrame, "YELL");
  4082. end
  4083. function ChatMenu_OnLoad(self)
  4084. self.chatFrame = DEFAULT_CHAT_FRAME;
  4085. UIMenu_Initialize(self);
  4086. UIMenu_AddButton(self, SAY_MESSAGE, SLASH_SAY1, ChatMenu_Say);
  4087. UIMenu_AddButton(self, PARTY_MESSAGE, SLASH_PARTY1, ChatMenu_Party);
  4088. UIMenu_AddButton(self, RAID_MESSAGE, SLASH_RAID1, ChatMenu_Raid);
  4089. UIMenu_AddButton(self, INSTANCE_CHAT_MESSAGE, SLASH_INSTANCE_CHAT1, ChatMenu_InstanceChat);
  4090. UIMenu_AddButton(self, GUILD_MESSAGE, SLASH_GUILD1, ChatMenu_Guild);
  4091. UIMenu_AddButton(self, YELL_MESSAGE, SLASH_YELL1, ChatMenu_Yell);
  4092. UIMenu_AddButton(self, WHISPER_MESSAGE, SLASH_SMART_WHISPER1, ChatMenu_Whisper);
  4093. UIMenu_AddButton(self, EMOTE_MESSAGE, SLASH_EMOTE1, ChatMenu_Emote, "EmoteMenu");
  4094. UIMenu_AddButton(self, REPLY_MESSAGE, SLASH_REPLY1, ChatMenu_Reply);
  4095. UIMenu_AddButton(self, LANGUAGE, nil, nil, "LanguageMenu");
  4096. UIMenu_AddButton(self, VOICEMACRO_LABEL, nil, nil, "VoiceMacroMenu");
  4097. UIMenu_AddButton(self, MACRO, SLASH_MACRO1, ShowMacroFrame);
  4098. UIMenu_AutoSize(self);
  4099. end
  4100. function ChatMenu_OnShow(self)
  4101. UIMenu_OnShow(self);
  4102. EmoteMenu:Hide();
  4103. LanguageMenu:Hide();
  4104. VoiceMacroMenu:Hide();
  4105. self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b);
  4106. self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b);
  4107. end
  4108. function EmoteMenu_Click(self)
  4109. DoEmote(EmoteList[self:GetID()]);
  4110. ChatMenu:Hide();
  4111. end
  4112. function TextEmoteSort(token1, token2)
  4113. local i = 1;
  4114. local string1, string2;
  4115. local token = _G["EMOTE"..i.."_TOKEN"];
  4116. while ( token ) do
  4117. if ( token == token1 ) then
  4118. string1 = _G["EMOTE"..i.."_CMD1"];
  4119. if ( string2 ) then
  4120. break;
  4121. end
  4122. end
  4123. if ( token == token2 ) then
  4124. string2 = _G["EMOTE"..i.."_CMD1"];
  4125. if ( string1 ) then
  4126. break;
  4127. end
  4128. end
  4129. i = i + 1;
  4130. token = _G["EMOTE"..i.."_TOKEN"];
  4131. end
  4132. return string1 < string2;
  4133. end
  4134. function OnMenuLoad(self,list,func)
  4135. sort(list, TextEmoteSort);
  4136. UIMenu_Initialize(self);
  4137. self.parentMenu = "ChatMenu";
  4138. for index, value in pairs(list) do
  4139. local i = 1;
  4140. local token = _G["EMOTE"..i.."_TOKEN"];
  4141. while ( token ) do
  4142. if ( token == value ) then
  4143. break;
  4144. end
  4145. i = i + 1;
  4146. token = _G["EMOTE"..i.."_TOKEN"];
  4147. end
  4148. local label = _G["EMOTE"..i.."_CMD1"];
  4149. if ( not label ) then
  4150. label = value;
  4151. end
  4152. UIMenu_AddButton(self, label, nil, func);
  4153. end
  4154. UIMenu_AutoSize(self);
  4155. end
  4156. function EmoteMenu_OnLoad(self)
  4157. OnMenuLoad(self, EmoteList, EmoteMenu_Click);
  4158. end
  4159. function LanguageMenu_OnLoad(self)
  4160. UIMenu_Initialize(self);
  4161. self.parentMenu = "ChatMenu";
  4162. self:RegisterEvent("PLAYER_ENTERING_WORLD");
  4163. self:RegisterEvent("LANGUAGE_LIST_CHANGED");
  4164. self:RegisterEvent("NEUTRAL_FACTION_SELECT_RESULT");
  4165. end
  4166. function VoiceMacroMenu_Click(self)
  4167. DoEmote(TextEmoteSpeechList[self:GetID()]);
  4168. ChatMenu:Hide();
  4169. end
  4170. function VoiceMacroMenu_OnLoad(self)
  4171. OnMenuLoad(self, TextEmoteSpeechList, VoiceMacroMenu_Click);
  4172. end
  4173. function LanguageMenu_OnEvent(self, event, ...)
  4174. if ( event == "PLAYER_ENTERING_WORLD" ) then
  4175. self:Hide();
  4176. UIMenu_Initialize(self);
  4177. LanguageMenu_LoadLanguages(self);
  4178. self:GetParent().chatFrame.editBox.language, self:GetParent().chatFrame.editBox.languageID = GetDefaultLanguage();
  4179. return;
  4180. end
  4181. if ( event == "LANGUAGE_LIST_CHANGED" ) then
  4182. self:Hide();
  4183. UIMenu_Initialize(self);
  4184. LanguageMenu_LoadLanguages(self);
  4185. return;
  4186. end
  4187. if ( event == "NEUTRAL_FACTION_SELECT_RESULT" ) then
  4188. self:Hide();
  4189. self:GetParent().chatFrame.editBox.language, self:GetParent().chatFrame.editBox.languageID = GetDefaultLanguage();
  4190. return;
  4191. end
  4192. end
  4193. function LanguageMenu_LoadLanguages(self)
  4194. local numLanguages = GetNumLanguages();
  4195. local i;
  4196. local editBoxLanguageID = self:GetParent().chatFrame.editBox.languageID;
  4197. local languageKnown = false;
  4198. for i = 1, numLanguages, 1 do
  4199. local language, languageID = GetLanguageByIndex(i);
  4200. UIMenu_AddButton(self, language, nil, LanguageMenu_Click);
  4201. if ( languageID == editBoxLanguageID ) then
  4202. languageKnown = true;
  4203. end
  4204. end
  4205. if ( languageKnown ~= true ) then
  4206. self:GetParent().chatFrame.editBox.language, self:GetParent().chatFrame.editBox.languageID = GetLanguageByIndex(1);
  4207. end
  4208. UIMenu_AutoSize(self);
  4209. end
  4210. function LanguageMenu_Click(self)
  4211. self:GetParent():GetParent().chatFrame.editBox.language, self:GetParent():GetParent().chatFrame.editBox.languageID = GetLanguageByIndex(self:GetID());
  4212. ChatMenu:Hide();
  4213. end
  4214. function ChatFrame_ActivateCombatMessages(chatFrame)
  4215. ChatFrame_AddMessageGroup(chatFrame, "OPENING");
  4216. ChatFrame_AddMessageGroup(chatFrame, "TRADESKILLS");
  4217. ChatFrame_AddMessageGroup(chatFrame, "PET_INFO");
  4218. ChatFrame_AddMessageGroup(chatFrame, "COMBAT_MISC_INFO");
  4219. ChatFrame_AddMessageGroup(chatFrame, "COMBAT_XP_GAIN");
  4220. ChatFrame_AddMessageGroup(chatFrame, "COMBAT_GUILD_XP_GAIN");
  4221. ChatFrame_AddMessageGroup(chatFrame, "COMBAT_HONOR_GAIN");
  4222. ChatFrame_AddMessageGroup(chatFrame, "COMBAT_FACTION_CHANGE");
  4223. end
  4224. function ChatChannelDropDown_Show(chatFrame, chatType, chatTarget, chatName)
  4225. HideDropDownMenu(1);
  4226. ChatChannelDropDown.initialize = ChatChannelDropDown_Initialize;
  4227. ChatChannelDropDown.displayMode = "MENU";
  4228. ChatChannelDropDown.chatType = chatType;
  4229. ChatChannelDropDown.chatTarget = chatTarget;
  4230. ChatChannelDropDown.chatName = chatName;
  4231. ChatChannelDropDown.chatFrame = chatFrame;
  4232. ToggleDropDownMenu(1, nil, ChatChannelDropDown, "cursor");
  4233. end
  4234. function ChatChannelDropDown_Initialize()
  4235. local frame = ChatChannelDropDown;
  4236. local info = UIDropDownMenu_CreateInfo();
  4237. info.text = frame.chatName;
  4238. info.notCheckable = true;
  4239. info.isTitle = true;
  4240. UIDropDownMenu_AddButton(info, 1);
  4241. info = UIDropDownMenu_CreateInfo();
  4242. if ( frame.chatType ~= "BN_CONVERSATION" or (FCFManager_GetNumDedicatedFrames(frame.chatType, frame.chatTarget) == 0)) then
  4243. if ( frame.chatType == "BN_CONVERSATION" ) then
  4244. info.text = MOVE_TO_CONVERSATION_WINDOW;
  4245. else
  4246. info.text = MOVE_TO_NEW_WINDOW;
  4247. end
  4248. info.notCheckable = 1;
  4249. info.func = ChatChannelDropDown_PopOutChat;
  4250. info.arg1 = frame.chatType;
  4251. info.arg2 = frame.chatTarget;
  4252. if ( frame.chatType ~= "BN_CONVERSATION" and FCF_GetNumActiveChatFrames() == NUM_CHAT_WINDOWS ) then
  4253. info.disabled = 1;
  4254. end
  4255. UIDropDownMenu_AddButton(info);
  4256. end
  4257. if ( frame.chatType == "BN_CONVERSATION" ) then
  4258. info = UIDropDownMenu_CreateInfo();
  4259. info.text = INVITE_FRIEND_TO_CONVERSATION;
  4260. info.notCheckable = 1;
  4261. info.func = ChatChannelDropDown_InviteToConversation;
  4262. info.arg1 = frame.chatType;
  4263. info.arg2 = frame.chatTarget;
  4264. UIDropDownMenu_AddButton(info);
  4265. info = UIDropDownMenu_CreateInfo();
  4266. info.text = LEAVE_CONVERSATION;
  4267. info.notCheckable = 1;
  4268. info.func = ChatChannelDropDown_LeaveConversation;
  4269. info.arg1 = frame.chatType;
  4270. info.arg2 = frame.chatTarget;
  4271. UIDropDownMenu_AddButton(info);
  4272. end
  4273. end
  4274. function ChatChannelDropDown_InviteToConversation(self, chatType, chatTarget)
  4275. if ( chatType == "BN_CONVERSATION" ) then
  4276. BNConversationInvite_SelectPlayers(chatTarget);
  4277. end
  4278. end
  4279. function ChatChannelDropDown_LeaveConversation(self, chatType, chatTarget)
  4280. BNLeaveConversation(chatTarget);
  4281. end
  4282. function ChatChannelDropDown_PopOutChat(self, chatType, chatTarget)
  4283. local sourceChatFrame = ChatChannelDropDown.chatFrame;
  4284. if ( chatType == "BN_CONVERSATION" ) then
  4285. FCF_OpenTemporaryWindow(chatType, chatTarget, sourceChatFrame, true);
  4286. else
  4287. local windowName;
  4288. if ( chatType == "CHANNEL" ) then
  4289. windowName = Chat_GetChannelShortcutName(chatTarget);
  4290. else
  4291. windowName = _G[chatType];
  4292. end
  4293. local frame = FCF_OpenNewWindow(windowName);
  4294. FCF_CopyChatSettings(frame, sourceChatFrame);
  4295. ChatFrame_RemoveAllMessageGroups(frame);
  4296. ChatFrame_RemoveAllChannels(frame);
  4297. ChatFrame_ReceiveAllPrivateMessages(frame);
  4298. ChatFrame_ReceiveAllBNConversations(frame);
  4299. ChatFrame_AddMessageGroup(frame, chatType);
  4300. if ( CHAT_CATEGORY_LIST[chatType] ) then
  4301. for _, chat in pairs(CHAT_CATEGORY_LIST[chatType]) do
  4302. ChatFrame_AddMessageGroup(frame, chat);
  4303. end
  4304. end
  4305. frame.editBox:SetAttribute("chatType", chatType);
  4306. frame.editBox:SetAttribute("stickyType", chatType);
  4307. if ( chatType == "CHANNEL" ) then
  4308. frame.editBox:SetAttribute("channelTarget", chatTarget);
  4309. ChatFrame_AddChannel(frame, Chat_GetChannelShortcutName(chatTarget));
  4310. end
  4311. if ( chatType == "PET_BATTLE_COMBAT_LOG" or chatType == "PET_BATTLE_INFO" ) then
  4312. frame.editBox:SetAttribute("chatType", "SAY");
  4313. frame.editBox:SetAttribute("stickyType", "SAY");
  4314. end
  4315. --Remove the things popped out from the source chat frame.
  4316. if ( chatType == "CHANNEL" ) then
  4317. ChatFrame_RemoveChannel(sourceChatFrame, Chat_GetChannelShortcutName(chatTarget));
  4318. else
  4319. ChatFrame_RemoveMessageGroup(sourceChatFrame, chatType);
  4320. if ( CHAT_CATEGORY_LIST[chatType] ) then
  4321. for _, chat in pairs(CHAT_CATEGORY_LIST[chatType]) do
  4322. ChatFrame_RemoveMessageGroup(sourceChatFrame, chat);
  4323. end
  4324. end
  4325. end
  4326. --Copy over messages
  4327. local accessID = ChatHistory_GetAccessID(chatType, chatTarget);
  4328. for i = 1, sourceChatFrame:GetNumMessages(accessID) do
  4329. local text, accessID, lineID, extraData = sourceChatFrame:GetMessageInfo(i, accessID);
  4330. local cType, cTarget = ChatHistory_GetChatType(extraData);
  4331. local info = ChatTypeInfo[cType];
  4332. frame:AddMessage(text, info.r, info.g, info.b, lineID, false, accessID, extraData);
  4333. end
  4334. --Remove the messages from the old frame.
  4335. sourceChatFrame:RemoveMessagesByAccessID(accessID);
  4336. end
  4337. end
  4338. function Chat_GetChannelShortcutName(index)
  4339. local _, name = GetChannelName(index);
  4340. name = strtrim(name:match("([^%-]+)"));
  4341. return name;
  4342. end
  4343. function ChatChannelDropDown_PopInChat(self, chatType, chatTarget)
  4344. --PopOutChat_PopInChat(chatType, chatTarget);
  4345. end
  4346. function Chat_GetColoredChatName(chatType, chatTarget)
  4347. if ( chatType == "CHANNEL" ) then
  4348. local info = ChatTypeInfo["CHANNEL"..chatTarget];
  4349. local colorString = format("|cff%02x%02x%02x", info.r * 255, info.g * 255, info.b * 255);
  4350. local chanNum, channelName = GetChannelName(chatTarget);
  4351. return format("%s|Hchannel:channel:%d|h[%d. %s]|h", colorString, chanNum, chanNum, gsub(channelName, "%s%-%s.*", "")); --The gsub removes zone-specific markings (e.g. "General - Ironforge" to "General")
  4352. elseif ( chatType == "WHISPER" ) then
  4353. local info = ChatTypeInfo["WHISPER"];
  4354. local colorString = format("|cff%02x%02x%02x", info.r * 255, info.g * 255, info.b * 255);
  4355. return format("%s[%s] |Hplayer:%3$s|h[%3$s]|h|r", colorString, _G[chatType], chatTarget);
  4356. else
  4357. local info = ChatTypeInfo[chatType];
  4358. local colorString = format("|cff%02x%02x%02x", info.r * 255, info.g * 255, info.b * 255);
  4359. return format("%s|Hchannel:%s|h[%s]|h|r", colorString, chatType, _G[chatType]);
  4360. end
  4361. end