vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 
2 local mod = klhtm
3 local me = { }
4 mod.net = me
5  
6 --[[
7 KTM_Net.lua
8  
9 This module has all the code for operating the chat channel and sending KLHTM messages on it. Note that it doesn't
10 deal with parsing / interpreting messages received from the chat channel - this is all done in KTM_NetIn.lua.
11  
12 ]]
13  
14 me.channelname = ""
15 me.channelnumber = 0
16 me.source = ""
17  
18 me.manualchannel = nil -- manual override
19  
20 me.lastmtsender = "" -- name of the player who sent the last mt
21 me.lastmtstring = "" -- name of the last mt, as sent by the player
22 me.lastmttime = 0 -- time you last updated MT
23 me.mtrepeattime = 10.0
24  
25 -- Special onupdate method from Core.lua
26 me.onupdate = function()
27  
28 me.updatethreattoraid()
29 me.checkversionquery()
30 me.checkadvertise()
31  
32 -- check to repeat mt string
33 if me.lastmtsender == UnitName("player") then
34  
35 -- check if you are still an assistant
36 if mod.unit.isplayerofficer(UnitName("player")) == nil then
37 me.lastmtsender = ""
38  
39 elseif GetTime() > me.lastmttime + me.mtrepeattime then
40  
41 -- resend and reset timer
42 me.lastmttime = GetTime()
43  
44 -- Now, was it a clear or a name?
45 if me.lastmtstring == "clear" then
46  
47 -- temporary: only send this to new versions (or else old versions might get spammed!)
48 if mod.isnewwowversion then
49 me.clearmastertarget()
50 end
51  
52 else
53 -- temporary: only send this to new versions (or else old versions might get spammed!)
54 if mod.isnewwowversion then
55 me.sendmessage("mtpoll " .. me.lastmtstring)
56 end
57 end
58 end
59 end
60 end
61  
62  
63 ------------------------------------------------------------------------------------------------
64  
65 ---------------------------------
66 -- Chat Channel Operation --
67 ---------------------------------
68  
69 -- return: number, name, method
70 me.getchannel = function()
71  
72 local name
73 local number
74 local test
75  
76 -- use the current channel, if that works
77 number, name = GetChannelName(me.channelname)
78  
79 if number > 0 then
80 return number, name, me.source
81 end
82  
83 -- Channel broken. look for oRA, CT_RA, manual set channels.
84  
85 -- First priority: manual override
86 if me.manualchannel then
87 number, name = GetChannelName(me.manualchannel)
88  
89 if number > 0 then
90 me.channelnumber = number
91 me.channelname = name
92 me.source = mod.string.get("print", "network", "channel", "manual")
93 return number, name, me.source
94 end
95 end
96  
97 -- Second priority: oRA
98 if oRA_Core then
99 test = oRA_Core:GetOpt("channel")
100  
101 if test then
102 number, name = GetChannelName(test)
103  
104 if number > 0 then
105 me.channelnumber = number
106 me.channelname = name
107 me.source = mod.string.get("print", "network", "channel", "ora")
108 return number, name, me.source
109 end
110 end
111 end
112  
113 -- Third priority: CT_RA
114 if CT_RA_Channel then
115 number, name = GetChannelName(CT_RA_Channel)
116  
117 if number > 0 then
118 me.channelnumber = number
119 me.channelname = name
120 me.source = mod.string.get("print", "network", "channel", "ctra")
121 return number, name, me.source
122 end
123 end
124  
125 -- can't find it!
126 return 0
127 end
128  
129  
130 --[[
131 mod.net.sendmessage(message)
132 Sends a message to the KLHTM chat channel.
133 <message> is a string. Don't put the "KLHTM " header on it; that's what this method does.
134 Return: true if the mod could find the right channel, false otherwise.
135 ]]
136 me.sendmessage = function(message)
137  
138 -- 1.12 override
139 if mod.isnewwowversion then
140  
141 if GetNumRaidMembers() > 0 then
142 SendAddonMessage("KLHTM", message, "RAID")
143  
144 elseif GetNumPartyMembers() > 0 then
145 SendAddonMessage("KLHTM", message, "PARTY")
146  
147 else
148 -- Send directly to our input handler
149 mod.netin.messagein(UnitName("player"), message, 1)
150 end
151  
152 return true
153 end
154  
155 local channelnumber = me.getchannel()
156  
157 if channelnumber > 0 then
158  
159 -- add KLHTM header
160 message = "KLHTM " .. message
161  
162 -- send
163 SendChatMessage(message, "CHANNEL", nil, channelnumber)
164  
165 -- debug
166 if mod.out.checktrace("info", me, "message") then
167 mod.out.printtrace(string.format("Sent this message: %s.", message))
168 end
169  
170 return true
171  
172 else
173  
174 return false
175 end
176  
177 end
178  
179  
180 ------------------------------------------------------------------------------------------------
181  
182 ---------------------------------
183 -- Special Raid Commands --
184 ---------------------------------
185  
186 --[[
187 me.checkpermission()
188 Returns: non-nil iff you are allowed to send special commands (raid assistant / party leader, etc)
189 ]]
190 me.checkpermission = function()
191  
192 if mod.unit.isplayerofficer(UnitName("player")) == true then
193 return true
194  
195 else
196 mod.out.print(mod.string.get("print", "network", "raidpermission"))
197 return
198 end
199  
200 end
201  
202 --[[
203 mod.net.clearmastertarget()
204 Sends a message to clear the master target. This is called from "/ktm mastertarget", or clicking the master target button
205 when you have no target.
206 ]]
207 me.clearmastertarget = function()
208  
209 if me.checkpermission() == nil then
210 return
211 end
212  
213 me.sendmessage("cleartarget")
214  
215 end
216  
217 --[[
218 mod.net.sendmastertarget()
219 Sends a message to set the master target to your current target. The name of your current target, as you see it, is sent along with the command, in case someone is out of (targetting) range of your target. This is called from
220 "/ktm mastertarget", or clicking the master target button when you have a target.
221 ]]
222 me.sendmastertarget = function()
223  
224 if me.checkpermission() == nil then
225 return
226 end
227  
228 if UnitName("target") == nil then
229 mod.out.print(mod.string.get("print", "network", "needtarget"))
230 return
231 end
232  
233 me.sendmessage("target " .. UnitName("target"))
234  
235 end
236  
237 --[[
238 mod.net.clearraidthreat()
239 Commands everyone in the raid to reset their threat. Called when you type "/ktm resetraid" or click the "clear threat"
240 button on the GUI (which is not visible by default).
241 ]]
242 me.clearraidthreat = function()
243  
244 if me.checkpermission() == nil then
245 return
246 end
247  
248 me.sendmessage("clear")
249  
250 end
251  
252 -- Commands in the Boss Section
253  
254 me.startspellreporting = function()
255  
256 if me.checkpermission() == nil then
257 return
258 end
259  
260 me.sendmessage("spellstart")
261  
262 end
263  
264 me.stopspellreporting = function()
265  
266 if me.checkpermission() == nil then
267 return
268 end
269  
270 me.sendmessage("spellstop")
271  
272 end
273  
274 me.reportspelleffect = function(spellname, bossname, result, value1, value2)
275  
276 if result == "miss" then
277 me.sendmessage(string.format("spelleffect \"%s\" \"%s\" %s", spellname, bossname, result))
278  
279 else
280 me.sendmessage(string.format("spelleffect \"%s\" \"%s\" %s %s %s", spellname, bossname, result, value1, value2))
281 end
282  
283 end
284  
285 me.setspellvalue = function(spellid, bossid, parameter, value)
286  
287 if me.checkpermission() == nil then
288 return
289 end
290  
291 me.sendmessage(string.format("spellvalue %s %s %s %s", spellid, bossid, parameter, value))
292  
293 end
294  
295 -- syntax: <spellid> <bossid> <parameter> <value>
296 --[[
297 if it succeeds, it will return just the value that is set.
298 if it fails, it will return nil, then the error message.
299 ]]
300 me.checkspellvaluesyntax = function(allvalues)
301  
302 local x, spellid, bossid, parameter, value, key, message
303  
304 -- Check their first argument, <spellid>, is valid
305 spellid = allvalues[1]
306 if (spellid == nil) or (mod.boss.bossattacks[spellid] == nil) then
307  
308 message = "The argument |cffffff00" .. tostring(spellid) .. "|r does not match any boss spell id. Valid spellids are|cffffff00"
309  
310 for key, value in mod.boss.bossattacks do
311 message = message .. " " .. key
312 end
313  
314 message = message .. "|r."
315 return nil, message
316 end
317  
318 -- Check their second argument, <bossid>, is valid
319 local dataset = mod.boss.bossattacks[spellid]
320  
321 bossid = allvalues[2]
322 if (bossid == nil) or (dataset[bossid] == nil) then
323  
324 message = "The argument |cffffff00" .. tostring(bossid) .. "|r does not match any boss that uses the spell |cffffff00" .. mod.string.get("boss", "spell", spellid) .. "|r. Valid bossids are|cffffff00"
325  
326 for key, value in dataset do
327 message = message .. " " .. key
328 end
329  
330 message = message .. "|r."
331 return nil, message
332 end
333  
334 -- Check their third argument, <parameter>, is valid
335 dataset = dataset[bossid]
336  
337 parameter = allvalues[3]
338 if (parameter == nil) or (dataset[parameter] == nil) then
339  
340 message = "The argument |cffffff00" .. tostring(parameter) .. "|r does not match any parameter that can be set. Valid parameters are|cffffff00"
341  
342 for key, valud in dataset do
343 message = message .. " " .. key
344 end
345  
346 message = message .. "|r."
347 return nil, message
348 end
349  
350 -- 4th parameter is value
351  
352 -- multiplier / addition: need number
353 if (parameter == "addition") or (parameter == "multiplier") then
354 value = tonumber(allvalues[4])
355  
356 if value == nil then
357  
358 message = "The argument |cffffff00" .. tostring(allvalues[4]) .. "|r is not a number."
359 return nil, message
360 end
361  
362 elseif parameter == "ticks" then
363 value = tonumber(allvalues[4])
364  
365 if (value == nil) or (math.floor(value) ~= value) or (value < 1) then
366  
367 message = "The argument |cffffff00" .. tostring(allvalues[4]) .. "|r is not a positive integer."
368 return nil, message
369 end
370  
371 elseif parameter == "effectonmiss" then
372  
373 if value == "true" then
374 value = true
375  
376 elseif value == "false" then
377 value = false
378  
379 else
380 message = "The argument |cffffff00" .. tostring(allvalues[4]) .. "|r is not a boolean value."
381 return nil, message
382 end
383  
384 elseif parameter == "type" then
385  
386 if (value ~= "physical") or (value ~= "debuff") or (value ~= "spell") then
387  
388 message = "The argument |cffffff00" .. tostring(allvalues[4]) .. "|r is not one of |cffffff00 physical debuff spell|r."
389 return nil, message
390 end
391 end
392  
393 -- it worked!
394 return value
395 end
396  
397  
398 me.versionnotify = function()
399  
400 if me.checkpermission() == nil then
401 return
402 end
403  
404 me.sendmessage(string.format("version %d.%d", mod.release, mod.revision))
405 mod.out.print(mod.string.get("print", "network", "upgradenote"))
406  
407 end
408  
409 me.versionquery = function()
410  
411 if me.checkpermission() == nil then
412 return
413 end
414  
415 -- clear the version table
416 local key
417  
418 for key, _ in me.raidversions do
419 table.remove(me.raidversions, key)
420 end
421  
422 -- set the timeout for responses
423 me.versionquerytimeout = GetTime() + 3
424  
425 -- Notify the user
426 mod.out.print(mod.string.get("print", "network", "versionrequest"))
427  
428 -- send the message
429 me.sendmessage("versionquery")
430  
431 end
432  
433 me.setraidknockbackvalue = function(value, attack)
434  
435 if me.checkpermission() == nil then
436 return
437 end
438  
439 if mod.boss.isknockbackdiscoveryactive == false then
440 mod.out.print(mod.string.get("print", "network", "knockbackinactive"))
441 else
442 me.sendmessage("knockbackvalue " .. value .. " " .. attack)
443 end
444  
445 end
446  
447 me.sendknockbackevent = function(enemy, ability, value)
448  
449 if (mod.boss.isknockbackdiscoveryactive == true) and (enemy == mod.boss.mastertarget) then
450  
451 me.sendmessage("knockaway " .. math.ceil(0.5 + mod.table.getraidthreat()))
452 me.sendmessage(string.format("knockawaytext {%s, %s, %s}", enemy, ability, value))
453 end
454  
455 end
456  
457 -- don't send an event if one has already been received and confirmed recently.
458 me.sendevent = function(event)
459  
460 me.sendmessage("event " .. event)
461  
462 end
463  
464 -- Version Querying Stuff. Key = release number, value = array of names
465 me.raidversions = { }
466 me.versionquerytimeout = 0 -- 0 = inactive, > 0 = active. Return value of GetTime()
467  
468 me.addversionresponse = function(playername, version)
469  
470 local versionstring = tostring(version)
471  
472 -- ignore unless we are checking versions
473 if me.versionquerytimeout > 0 then
474  
475 if me.raidversions[versionstring] == nil then
476 me.raidversions[versionstring] = { }
477 end
478  
479 me.raidversions[versionstring][playername] = true
480 end
481  
482 end
483  
484  
485 -- When we do "/ktm version query", the rest of the raid has 3 seconds to respond.
486 me.checkversionquery = function()
487  
488 if me.versionquerytimeout == 0 then
489 return
490 end
491  
492 if GetTime() > me.versionquerytimeout then
493  
494 -- print it out and stuff
495 me.versionquerytimeout = 0
496  
497 local message
498 local key
499 local value
500 local key2
501 local namesfound = { }
502  
503 for key, value in me.raidversions do
504 message = string.format(mod.string.get("print", "network", "versionrecent"), key)
505  
506 for key2, _ in value do
507 message = message .. key2 .. ", "
508 namesfound[key2] = true
509 end
510  
511 message = message .. " }."
512 mod.out.print(message)
513  
514 table.remove(me.raidversions, key)
515 end
516  
517 -- Now print the people who have out of date versions
518 message = mod.string.get("print", "network", "versionold")
519 for key, _ in mod.table.raiddata do
520 if namesfound[key] == nil and mod.unit.isplayeringroup(key) == true then
521 namesfound[key] = true
522 message = message .. key .. ", "
523 end
524 end
525  
526 message = message .. " }."
527 mod.out.print(message)
528  
529 -- Now print out people who are not talking to us
530 message = mod.string.get("print", "network", "versionnone")
531  
532 for value = 1, 40 do
533 key = GetRaidRosterInfo(value)
534 if (key ~= nil) and (namesfound[key] == nil) then
535 namesfound[key] = true
536 message = message .. key .. ", "
537 end
538 end
539  
540 message = message .. " }."
541 mod.out.print(message)
542  
543 end
544 end
545  
546 me.lastthreatupdate = 0 -- value of GetTime(). When we last posted our threat to the raid
547 me.minimumupdateinterval = 0.5 -- minimum time, in seconds, between threat updates to the raid
548 me.idleupdateinterval = 10.0 -- how often to update when our value is not changing
549 me.lastthreatvaluesent = -1 -- the name says it all, really
550  
551 --[[
552 me.updatethreattoraid()
553 Posts your threat value to the KLHTM channel if necessary. You will send your threat at most once every
554 <me.minimumupdateinterval> = 0.5 seconds. If your threat value is unchanged, you will repeat it once every 10
555 seconds only. If you aren't in a party or raid, you won't repeat your value if it is constant.
556 ]]
557 me.updatethreattoraid = function()
558  
559 local interval
560 local myraidthreat
561  
562 if mod.my.states.incombat.value == true then
563 myraidthreat = math.floor(0.5 + mod.table.getraidthreat())
564 else
565 myraidthreat = 0
566 end
567  
568 if myraidthreat == me.lastthreatvaluesent then
569 interval = me.idleupdateinterval
570  
571 -- check for solo, then no updates
572 if GetNumRaidMembers() == 0 and GetNumPartyMembers() == 0 then
573 return
574 end
575  
576 -- also don't send idle updates when afk
577 if mod.my.states.afk.value == true then
578 return
579 end
580  
581 else
582 interval = me.minimumupdateinterval
583  
584 end
585  
586 -- check update frequency
587 if GetTime() < me.lastthreatupdate + interval then
588 return -- only just sent an update. Wait a bit to send the next one.
589 end
590  
591 -- OK. Send.
592 local message = "threat " .. myraidthreat
593 if mod.isnewwowversion then
594 message = "t " .. myraidthreat
595 end
596  
597 if me.sendmessage(message) == nil then
598 if mod.out.checktrace("warning", me, "channel") then
599 mod.out.printtrace("Threat was not updated because the CTRA Channel is not set up properly.")
600 end
601 end
602  
603 me.lastthreatupdate = GetTime()
604 me.lastthreatvaluesent = myraidthreat
605  
606 end
607  
608 --------------------------------------------------------------------------------------------------
609  
610 -------------------------------------------------------
611 -- Advertising KLHTM to people who pull aggro! --
612 -------------------------------------------------------
613  
614 me.isadvertising = false
615 me.lastadvert = 0
616 me.advertinterval = 300 -- seconds
617  
618 --[[
619 mod.net.toggleadvertise()
620 Switch the advertising function on or off.
621 ]]
622 me.toggleadvertise = function()
623  
624 me.isadvertising = not me.isadvertising
625  
626 if me.isadvertising == true then
627 mod.out.print(mod.string.get("print", "network", "advertisestart"))
628 else
629 mod.out.print(mod.string.get("print", "network", "advertisestop"))
630 end
631  
632 end
633  
634 me.raidnumbers = { } -- {1, 2, 3, ..., 40}
635  
636 for x = 1, 40 do
637 me.raidnumbers[x] = x
638 end
639  
640 --[[
641 me.checkadvertise()
642 Looks for people who have pulled aggro but don't have KLHTM, and tells them to get it. A message will be sent no more than
643 once every <me.advertinterval> = 5 minutes. Messages will be sent to non-warriors who are being targetted by a mob, so it's
644 not a complete guarantee that they have aggro.
645 ]]
646 me.checkadvertise = function()
647  
648 if me.isadvertising == false then
649 return
650 end
651  
652 -- don't spam
653 if GetTime() < me.lastadvert + me.advertinterval then
654 return
655 end
656  
657 -- look for someone who has aggro, is not a warrior, is not in the raid threat
658 if GetNumRaidMembers() <= 0 then
659 return
660 end
661  
662 local target = ""
663 local player = ""
664 local x
665  
666 -- make it a random permutation of the raid, to stop bugging one person
667 me.scrambleraid(me.raidnumbers)
668  
669 for y = 1, 40 do
670  
671 -- get x from scrambled array
672 x = me.raidnumbers[y]
673  
674 -- there is a raid player
675 target = "raid" .. x
676 if UnitExists(target) == 1 then
677  
678 -- the player is targetting a mob
679 target = target .. "target"
680 if UnitExists(target) == 1 and UnitIsFriend("player", target) ~= 1 then
681  
682 -- mob has another player targetted
683 player = target .. "target"
684 if UnitIsFriend("player", player) == 1 then
685  
686 -- player is not yourself, not a warrior, is a player
687 if (UnitIsPlayer(player) == 1) and (UnitName("player") ~= UnitName(player)) then
688  
689 local _, class = UnitClass(player)
690 if class ~= "WARRIOR" then
691  
692 -- check they arne't using the meter
693 if mod.table.raiddata[UnitName(player)] == nil then
694  
695 -- send them a message
696 SendChatMessage(string.format(mod.string.get("print", "network", "advertisemessage"), UnitName(target)), "WHISPER", nil, UnitName(player))
697 me.lastadvert = GetTime()
698 return
699 end
700 end
701 end
702 end
703 end
704 end
705 end
706 end
707  
708 --[[
709 me.scrambleraid(numbers)
710 Slightly scrambles the array <numbers>. Picks 10 random pairs and swaps them. Since this scramble method gets called
711 each time we check, the array will be sufficiently inconstant all the time.
712 ]]
713 me.scrambleraid = function(numbers)
714  
715 local x
716 local temp
717 local box1
718 local box2
719  
720 for x = 1, 10 do
721 box1 = math.random(1, 40)
722 box2 = math.random(1, 40)
723  
724 temp = numbers[box1]
725 numbers[box1] = numbers[box2]
726 numbers[box2] = temp
727 end
728  
729 end
730