vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --[[ |
2 | Healers Assist by Kiki - European Cho'gall |
||
3 | |||
4 | TODO : |
||
5 | |||
6 | GESTION/CONFIG : |
||
7 | - Handle Talent/Armor bonus in _HA_GetDuration function |
||
8 | - Handle pets (with config option to show them in emergency) |
||
9 | - For the buf request, add an option to refuse requests when in combat (for some bufs, maybe configurable per buf with 3 options, deny:not-in-combat:always) |
||
10 | |||
11 | GUI : |
||
12 | - Possibility to configure color used in the HA_GUI_Process_Announce function |
||
13 | - Possibility to only show hots I can cast in emergency list |
||
14 | - Emergency list : Show in another color, people out of my healing range (CheckInteractDistance() is 30yards max, maybe show in yellow) |
||
15 | - Show an estimated time of remaining regen time for a healer in Resting mode (dans le champ de casting) (new field EndRegenTime to compute in HA_Healers struct) |
||
16 | - Show remaining effect time of a cooldown spell casted on a healer |
||
17 | |||
18 | SORTING : |
||
19 | [Quote from Freddy] Some feature ideas I heard about the emergency list: |
||
20 | - Mark players which are in your party (different color of HP bar?) + priority option |
||
21 | - Option to limit filter the estimated heal value that is added to the HP by casting time (e.g. only add heal which should have finished in <1.5sek) |
||
22 | - Make an option which allowes it to set a fixed value of HP difference to show up the player in the list (not percentage) |
||
23 | - Add something which put's the tanks at a higher priorty (class specific settings for casting tiem filter?) |
||
24 | |||
25 | TODO WARRIOR PLUGIN : |
||
26 | - Show for "YOU", current casts on yourself, with casting times (sorted by casting time) |
||
27 | -> Prints a warning to yourself (use healing potion !! for example) if no spell is coming, and you have the agro, or gonna die soon ^^ |
||
28 | |||
29 | BUGS : |
||
30 | - Unit IDs changing during a SpellRequest (raid changes while the SpellRequest popup is shown -> possible wrong unitid) (NOT SURE IF THIS IS POSSIBLE) |
||
31 | -> In _HA_SetRaiderVariables function (and GA callback) |
||
32 | -> Callback a function in GUI to update all internal variables using IDs (like SpellRequest) |
||
33 | - RaiderDeath not always correct (maybe check with hp==0 ?) |
||
34 | - Hunter that Feign death will be counted as "dead/rezzed" |
||
35 | - Druid shifting back to humain with full mana, will show empty mana (need to grab mp/mpmax after a shift) |
||
36 | - Without GroupAnalyse, if I'm in Group Mode (not raid) all members are set as GroupLeader |
||
37 | - Heal on an external player or NPC (out of raid), will trigger overheal status after spell complete -> Well... nevermind right now |
||
38 | |||
39 | ChangeLog : |
||
40 | - 2006/09/12 : 1.1 |
||
41 | - Fixed incorrect healing debuff detection of Nefarius encounter |
||
42 | - 2006/08/31 : |
||
43 | - Fixed Item Bonuses not correct with latest BonusScanner addon installed (Scan not done, if no other addon ask BS for a scan) |
||
44 | - 2006/08/30 : |
||
45 | - Fixed minor xml error (minimap button not highlighting correctly (thanks Kagar) |
||
46 | - Fixed initialization issue, if not using GroupAnalyse addon |
||
47 | |||
48 | [Full ChangeLog in readme.txt file] |
||
49 | ]] |
||
50 | |||
51 | |||
52 | |||
53 | --------------- Shared Constantes --------------- |
||
54 | HA_MODE_NONE = 0; |
||
55 | HA_MODE_SOLO = 1 |
||
56 | HA_MODE_GROUP = 2 |
||
57 | HA_MODE_RAID = 3; |
||
58 | |||
59 | --------------- Shared variables --------------- |
||
60 | HA_VERSION = "1.1"; |
||
61 | HA_PlayerName = nil; |
||
62 | HA_CurrentTarget = nil; |
||
63 | HA_LibramItem = nil; |
||
64 | HA_Healers = {}; |
||
65 | HA_Raiders = {}; |
||
66 | HA_RaidersByID = {}; |
||
67 | HA_CurrentGroupMode = HA_MODE_NONE; |
||
68 | HA_MyselfHealer = nil; |
||
69 | HA_MyselfRaider = nil; |
||
70 | HA_CurrentZone = nil; |
||
71 | HA_SpellCooldowns = {}; |
||
72 | HA_AFK_Mode = false; |
||
73 | HA_ClassesID = { |
||
74 | ["DRUID"] = 1; |
||
75 | ["HUNTER"] = 2; |
||
76 | ["MAGE"] = 3; |
||
77 | ["PRIEST"] = 4; |
||
78 | ["ROGUE"] = 5; |
||
79 | ["WARLOCK"] = 6; |
||
80 | ["WARRIOR"] = 7; |
||
81 | ["PALADIN"] = 8; |
||
82 | ["SHAMAN"] = 8; |
||
83 | }; |
||
84 | |||
85 | --------------- Local Constantes --------------- |
||
86 | local HA_COOLDOWN_SPELLS_UPDATE_DELAY = 60; -- Every 60sec |
||
87 | local HA_VERSION_SEND_DELAY = 60; -- Every 60sec |
||
88 | local HA_MAX_HEAL_UPDATES = 10; -- Keep max 10 incoming heal per raider |
||
89 | local _HA_LastTimeEmergency = 0; |
||
90 | |||
91 | --------------- Local variables --------------- |
||
92 | local HA_NeedInit = true; |
||
93 | local HA_CastingSpell = nil; |
||
94 | local HA_HookActionName = nil; |
||
95 | local HA_HookActionRank = 0; |
||
96 | local HA_StopCommandSent = true; |
||
97 | local HA_StopCommandLastTime = 0; |
||
98 | local HA_CastingInstantSpell = nil; |
||
99 | local HA_CastingInstantRank = 0; |
||
100 | local HA_SpellTargetName = nil; |
||
101 | local HA_PotentialSpellTargetName = nil; |
||
102 | local HA_LastRegrowthRank = 0; |
||
103 | local HA_MaxRanks = {}; |
||
104 | local _HA_UseBonusScannerAddon = false; |
||
105 | local _HA_BonusScanScheduled = false; |
||
106 | local _HA_LastSendVersion = 0; |
||
107 | |||
108 | |||
109 | --------------- Internal functions --------------- |
||
110 | |||
111 | function HA_SetNewLock(printmsg) |
||
112 | if(HA_Config.Lock) |
||
113 | then |
||
114 | HealersAssistMainFrame:EnableMouse("false"); |
||
115 | if(printmsg) |
||
116 | then |
||
117 | HA_ChatPrint(HA_CHAT_LOCK_ON); |
||
118 | end |
||
119 | else |
||
120 | HealersAssistMainFrame:EnableMouse("true"); |
||
121 | if(printmsg) |
||
122 | then |
||
123 | HA_ChatPrint(HA_CHAT_LOCK_OFF); |
||
124 | end |
||
125 | end |
||
126 | end |
||
127 | |||
128 | local function _HA_GetMaxSpellRanks() |
||
129 | local maxRanks = {}; |
||
130 | local index = 1; |
||
131 | while(1) do |
||
132 | local spellName, spellRank = GetSpellName(index, BOOKTYPE_SPELL) |
||
133 | if(not spellName) then |
||
134 | break; |
||
135 | elseif(HA_Spells[spellName]) then |
||
136 | local _,_,ranknum = string.find(spellRank,HA_RANK.." (%d+)"); |
||
137 | ranknum = tonumber(ranknum,10); |
||
138 | if(not maxRanks[spellName]) then |
||
139 | maxRanks[spellName] = ranknum; |
||
140 | elseif(ranknum > maxRanks[spellName]) then |
||
141 | maxRanks[spellName] = ranknum; |
||
142 | end |
||
143 | end |
||
144 | index = index + 1 |
||
145 | end |
||
146 | return maxRanks; |
||
147 | end |
||
148 | |||
149 | local function _HA_SetRaiderAsHealer(raider) |
||
150 | if(not raider.ishealer) |
||
151 | then |
||
152 | raider.ishealer = true; |
||
153 | -- Call plugins |
||
154 | for n,pl in HA_ActivePlugins |
||
155 | do |
||
156 | if(pl.OnEvent) |
||
157 | then |
||
158 | pl.OnEvent(HA_EVENT_HEALER_JOINED,{raider.name}); |
||
159 | end |
||
160 | end |
||
161 | end |
||
162 | end |
||
163 | |||
164 | local function _HA_UpdateOtherVariables(raider) |
||
165 | raider.percent = floor(raider.hp / raider.hpmax * 100); |
||
166 | raider.mppercent = floor(raider.mp / raider.mpmax * 100); |
||
167 | |||
168 | local healer = HA_Healers[raider.name]; |
||
169 | if(healer and (raider.class == "PRIEST" or raider.class == "DRUID" or raider.class == "PALADIN" or raider.class == "SHAMAN")) -- This is a healer |
||
170 | then |
||
171 | _HA_SetRaiderAsHealer(raider); |
||
172 | healer.id = raider.id; |
||
173 | healer.Raider = raider; |
||
174 | end |
||
175 | end |
||
176 | |||
177 | local function _HA_SetMinimalRaiderVariables(raider,raidid,rank,subgrp) |
||
178 | raider.id = raidid; |
||
179 | HA_RaidersByID[raidid] = raider; |
||
180 | raider.rank = rank; |
||
181 | raider.subgrp = subgrp; |
||
182 | end |
||
183 | |||
184 | local function _HA_SetFullRaiderVariables(raider,raidid,rank,subgrp) |
||
185 | _HA_SetMinimalRaiderVariables(raider,raidid,rank,subgrp); |
||
186 | _,raider.class = UnitClass(raider.id); |
||
187 | raider.classid = HA_ClassesID[raider.class]; |
||
188 | raider.isdead = UnitIsDeadOrGhost(raider.id); |
||
189 | raider.oldisdead = raider.isdead; |
||
190 | raider.hp_real = UnitHealth(raider.id); |
||
191 | raider.hpmax = UnitHealthMax(raider.id); |
||
192 | raider.ischarmed = UnitIsCharmed(raider.id); |
||
193 | raider.mp = UnitMana(raider.id); |
||
194 | raider.mpmax = UnitManaMax(raider.id); |
||
195 | raider.isconnected = UnitIsConnected(raider.id); |
||
196 | |||
197 | raider.hp = raider.hp_real; |
||
198 | raider.hp_estim = raider.hp_real; |
||
199 | raider.ignore_next_wound = 0; |
||
200 | raider.life_updates = {}; |
||
201 | raider.heal_updates = {}; |
||
202 | |||
203 | _HA_UpdateOtherVariables(raider); |
||
204 | end |
||
205 | |||
206 | local function _HA_CreateRaider(name) |
||
207 | local infos = {}; |
||
208 | infos.name = name; |
||
209 | infos.count = 0; |
||
210 | infos.estimates = {}; |
||
211 | infos.estimate_ratio = 1; |
||
212 | infos.overtime = {}; |
||
213 | return infos; |
||
214 | end |
||
215 | |||
216 | local function _HA_AddHealer(pl_name) |
||
217 | if(HA_Healers[pl_name] == nil) |
||
218 | then |
||
219 | local infos = {}; |
||
220 | local raider = HA_Raiders[pl_name]; |
||
221 | infos.Cooldown = {}; |
||
222 | infos.Name = pl_name; |
||
223 | infos.State = HA_STATE_NOTHING; |
||
224 | infos.OverHealPercent = 0; |
||
225 | infos.EstimateRatio = 1; |
||
226 | infos.Estimate = 0; |
||
227 | infos.StartTime = 0; |
||
228 | infos.Raider = raider; |
||
229 | |||
230 | if(raider) |
||
231 | then |
||
232 | local class = raider.class; |
||
233 | infos.id = raider.id; |
||
234 | if(class == "PRIEST" or class == "DRUID" or class == "PALADIN" or class == "SHAMAN") |
||
235 | then |
||
236 | HA_ChatDebug(HA_DEBUG_MEMBERS,"HA_CheckPlayerJoined : "..pl_name.." is in my Raiders list and is a Healer"); |
||
237 | _HA_SetRaiderAsHealer(raider); |
||
238 | else |
||
239 | HA_ChatDebug(HA_DEBUG_MEMBERS,"HA_CheckPlayerJoined : "..pl_name.." is in my Raiders list but is not a Healer"); |
||
240 | end |
||
241 | else |
||
242 | HA_ChatDebug(HA_DEBUG_MEMBERS,"HA_CheckPlayerJoined : "..pl_name.." is not in my Raiders list"); |
||
243 | end |
||
244 | |||
245 | HA_Healers[pl_name] = infos; |
||
246 | if(pl_name == HA_PlayerName) |
||
247 | then |
||
248 | HA_MyselfHealer = infos; |
||
249 | HA_ChatDebug(HA_DEBUG_GLOBAL,"Setting MYSELF as HEALER : "..tostring(infos)); |
||
250 | HA_GUI_Process_Version(HA_PlayerName,HA_VERSION); |
||
251 | end |
||
252 | end |
||
253 | end |
||
254 | |||
255 | local function _HA_AddRaider(name,tab) |
||
256 | HA_Raiders[name] = tab; |
||
257 | HA_RaidersByID[tab.id] = tab; |
||
258 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_AddRaider : Adding raider "..name.." with id="..tab.id); |
||
259 | if(name == HA_PlayerName) -- Myself |
||
260 | then |
||
261 | HA_MyselfRaider = tab; |
||
262 | HA_ChatDebug(HA_DEBUG_GLOBAL,"Setting MYSELF as RAIDER : "..tostring(tab)); |
||
263 | end |
||
264 | -- Call plugins |
||
265 | for _,pl in HA_ActivePlugins |
||
266 | do |
||
267 | if(pl.OnEvent) |
||
268 | then |
||
269 | pl.OnEvent(HA_EVENT_RAIDER_JOINED,{name}); |
||
270 | end |
||
271 | end |
||
272 | if(tab.class == "PRIEST" or tab.class == "DRUID" or tab.class == "PALADIN" or tab.class == "SHAMAN") |
||
273 | then |
||
274 | _HA_AddHealer(name); |
||
275 | end |
||
276 | end |
||
277 | |||
278 | local function _HA_RemoveHealer(pl_name) |
||
279 | if(HA_Healers[pl_name]) |
||
280 | then |
||
281 | -- Call plugins |
||
282 | for n,pl in HA_ActivePlugins |
||
283 | do |
||
284 | if(pl.OnEvent) |
||
285 | then |
||
286 | pl.OnEvent(HA_EVENT_HEALER_LEFT,{pl_name}); |
||
287 | end |
||
288 | end |
||
289 | HA_Healers[pl_name] = nil; |
||
290 | end |
||
291 | end |
||
292 | |||
293 | local function _HA_RemoveRaider(name) |
||
294 | local raider = HA_Raiders[name]; |
||
295 | if(raider) |
||
296 | then |
||
297 | HA_RaidersByID[raider.id] = nil; |
||
298 | end |
||
299 | HA_Raiders[name] = nil; |
||
300 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_RemoveRaider : Removed raider "..name); |
||
301 | -- Call plugins |
||
302 | for _,pl in HA_ActivePlugins |
||
303 | do |
||
304 | if(pl.OnEvent) |
||
305 | then |
||
306 | pl.OnEvent(HA_EVENT_RAIDER_LEFT,{name}); |
||
307 | end |
||
308 | end |
||
309 | _HA_RemoveHealer(name); -- Check for healer removal |
||
310 | end |
||
311 | |||
312 | local function _HA_AnalyseGroupRaidMembers() |
||
313 | local newmode = HA_MODE_NONE; |
||
314 | local new_raiders = {}; |
||
315 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_AnalyseGroupRaidMembers : Start Analyse"); |
||
316 | |||
317 | if(GetNumRaidMembers() ~= 0) -- In a raid |
||
318 | then |
||
319 | if(HA_CurrentGroupMode ~= HA_MODE_RAID) -- But was not |
||
320 | then |
||
321 | HealersAssistMainFrame:UnregisterEvent("PARTY_MEMBERS_CHANGED"); |
||
322 | end |
||
323 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_AnalyseGroupRaidMembers : I'm in a RAID"); |
||
324 | newmode = HA_MODE_RAID; |
||
325 | local count = GetNumRaidMembers(); |
||
326 | for i = 1, count do |
||
327 | local name,rank,subgrp = GetRaidRosterInfo(i); |
||
328 | if(name) |
||
329 | then |
||
330 | new_raiders[name] = _HA_CreateRaider(name); |
||
331 | _HA_SetMinimalRaiderVariables(new_raiders[name],"raid"..i,rank,subgrp); |
||
332 | end |
||
333 | end |
||
334 | else |
||
335 | if(HA_CurrentGroupMode == HA_MODE_RAID) -- Was in a RAID |
||
336 | then |
||
337 | HealersAssistMainFrame:RegisterEvent("PARTY_MEMBERS_CHANGED"); |
||
338 | end |
||
339 | new_raiders[HA_PlayerName] = _HA_CreateRaider(HA_PlayerName); |
||
340 | _HA_SetMinimalRaiderVariables(new_raiders[HA_PlayerName],"player",2,1); |
||
341 | if(GetNumPartyMembers() ~= 0) -- In a group |
||
342 | then |
||
343 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_AnalyseGroupRaidMembers : I'm in a GROUP"); |
||
344 | newmode = HA_MODE_GROUP; |
||
345 | for i = 1,4 do |
||
346 | local name = UnitName("party"..i); |
||
347 | if(name and (name ~= UNKNOWNOBJECT) and (name ~= UKNOWNBEING)) |
||
348 | then |
||
349 | new_raiders[name] = _HA_CreateRaider(name); |
||
350 | _HA_SetMinimalRaiderVariables(new_raiders[name],"party"..i,2,1); |
||
351 | end |
||
352 | end |
||
353 | else |
||
354 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_AnalyseGroupRaidMembers : I'm not grouped"); |
||
355 | newmode = HA_MODE_SOLO; |
||
356 | end |
||
357 | end |
||
358 | |||
359 | -- Update list of Raiders |
||
360 | for n,tab in HA_Raiders -- Remove old raiders |
||
361 | do |
||
362 | if(new_raiders[n] == nil) -- No longer in the raid |
||
363 | then |
||
364 | _HA_RemoveRaider(n); |
||
365 | end |
||
366 | end |
||
367 | |||
368 | HA_RaidersByID = {}; |
||
369 | for n,tab in new_raiders -- Add new raiders |
||
370 | do |
||
371 | local raider = HA_Raiders[n]; |
||
372 | if(raider == nil) -- New member |
||
373 | then |
||
374 | _HA_SetFullRaiderVariables(tab,tab.id,tab.rank,tab.subgrp); |
||
375 | _HA_AddRaider(n,tab); |
||
376 | else -- Was already here -> Update variables |
||
377 | _HA_SetMinimalRaiderVariables(raider,tab.id,tab.rank,tab.subgrp); |
||
378 | _HA_UpdateOtherVariables(raider); |
||
379 | end |
||
380 | end |
||
381 | |||
382 | if(HA_Config.Auto and newmode ~= HA_CurrentGroupMode) |
||
383 | then |
||
384 | if(newmode == HA_MODE_SOLO) |
||
385 | then |
||
386 | HealersAssistMainFrame:Hide(); |
||
387 | else |
||
388 | HealersAssistMainFrame:Show(); |
||
389 | end |
||
390 | end |
||
391 | HA_CurrentGroupMode = newmode; |
||
392 | |||
393 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_AnalyseGroupRaidMembers : Analyse Completed"); |
||
394 | end |
||
395 | |||
396 | local function _HA_GroupAnalyseCallback(event,param) |
||
397 | local infos; |
||
398 | if(event == GA_EVENT_INFOS_CHANGED) |
||
399 | then |
||
400 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_GroupAnalyseCallback : Start members data update"); |
||
401 | HA_RaidersByID = {}; |
||
402 | debugprofilestart(); |
||
403 | for name,member in GA_Members |
||
404 | do |
||
405 | infos = HA_Raiders[name]; |
||
406 | if(infos) |
||
407 | then |
||
408 | infos.id = member.unitid; |
||
409 | HA_RaidersByID[member.unitid] = infos; |
||
410 | infos.rank = member.rank; |
||
411 | infos.subgrp = member.subgrp; |
||
412 | infos.ischarmed = member.ischarmed; |
||
413 | infos.isconnected = member.isconnected; |
||
414 | _HA_UpdateOtherVariables(infos); |
||
415 | end |
||
416 | end |
||
417 | HA_PROFILE_AnalyseRaidersRoutine = debugprofilestop(); |
||
418 | HA_ChatDebug(HA_DEBUG_RAIDERS,"_HA_GroupAnalyseCallback : Update Completed"); |
||
419 | elseif(event == GA_EVENT_MEMBER_JOINED) |
||
420 | then |
||
421 | infos = _HA_CreateRaider(param); |
||
422 | local member = GA_Members[param]; |
||
423 | _HA_SetFullRaiderVariables(infos,member.unitid,member.rank,member.subgrp); |
||
424 | _HA_AddRaider(param,infos); |
||
425 | elseif(event == GA_EVENT_MEMBER_LEFT) |
||
426 | then |
||
427 | _HA_RemoveRaider(param); |
||
428 | elseif(event == GA_EVENT_GROUP_MODE_CHANGED) |
||
429 | then |
||
430 | HA_ChatDebug(HA_DEBUG_GLOBAL,"_HA_GroupAnalyseCallback : Group mode changed to "..param); |
||
431 | if(HA_Config.Auto) |
||
432 | then |
||
433 | if(param == GA_MODE_SOLO) |
||
434 | then |
||
435 | HealersAssistMainFrame:Hide(); |
||
436 | else |
||
437 | HealersAssistMainFrame:Show(); |
||
438 | end |
||
439 | end |
||
440 | HA_CurrentGroupMode = param; |
||
441 | end |
||
442 | end |
||
443 | |||
444 | local function _HA_CooldownUpdateScheduleRoutine() |
||
445 | local serv_time = GetTime(); |
||
446 | local tim = time(); |
||
447 | -- Update my cooldown status |
||
448 | if(HA_MyselfHealer) |
||
449 | then |
||
450 | for spell,infos in HA_SpellCooldowns |
||
451 | do |
||
452 | -- Update my cooldown |
||
453 | local startTime,cd_value = GetSpellCooldown(infos.id,"spell"); |
||
454 | local Cooldown = 0; |
||
455 | if(startTime ~= 0 and cd_value > 30) -- (Prevent global cooldown and silence spells to interfere) |
||
456 | then |
||
457 | Cooldown = floor((startTime+cd_value) - serv_time); |
||
458 | end |
||
459 | |||
460 | -- Check for update send |
||
461 | if(not HA_AFK_Mode and ((Cooldown == 0 and infos.last ~= 0) or -- Was in cooldown, but not anymore |
||
462 | (Cooldown ~= 0 and infos.last == 0) or -- Was up, but in cooldown now |
||
463 | (tim > (infos.lastSend+HA_COOLDOWN_SPELLS_UPDATE_DELAY)))) -- Delay expired |
||
464 | then |
||
465 | HA_GUI_Process_CooldownUpdate(HA_PlayerName,infos.ispell,Cooldown); |
||
466 | HA_COM_CooldownUpdate(infos.ispell,Cooldown); |
||
467 | infos.lastSend = tim; |
||
468 | infos.last = Cooldown; |
||
469 | end |
||
470 | end |
||
471 | -- Check for HA version send |
||
472 | if(not HA_AFK_Mode and (tim > (_HA_LastSendVersion+HA_VERSION_SEND_DELAY))) -- Delay expired |
||
473 | then |
||
474 | HA_ChatDebug(HA_DEBUG_GLOBAL,"Too long since last Version send"); |
||
475 | HA_COM_SendVersion(); |
||
476 | _HA_LastSendVersion = tim; |
||
477 | end |
||
478 | end |
||
479 | |||
480 | -- Update other cooldown status |
||
481 | for name,tab in HA_Healers |
||
482 | do |
||
483 | for spell,infos in tab.Cooldown |
||
484 | do |
||
485 | if(infos.Remain ~= 0) -- Player having a Cooldown spell |
||
486 | then |
||
487 | infos.Remain = infos.Remain - (serv_time - infos.Start); |
||
488 | if(infos.Remain <= 0) |
||
489 | then |
||
490 | infos.Remain = 0; |
||
491 | end |
||
492 | infos.Start = serv_time; |
||
493 | end |
||
494 | end |
||
495 | end |
||
496 | |||
497 | -- Re schedule |
||
498 | HASystem_Schedule(1,_HA_CooldownUpdateScheduleRoutine); |
||
499 | end |
||
500 | |||
501 | local function _HA_SetDefaultConfig(param,value) |
||
502 | if(HA_Config[param] == nil) |
||
503 | then |
||
504 | HA_Config[param] = value; |
||
505 | end |
||
506 | end |
||
507 | |||
508 | local function _HA_ScheduledInit() |
||
509 | HA_InitializeCooldownSpells(); |
||
510 | HASystem_Schedule(1,_HA_CooldownUpdateScheduleRoutine); -- Special cooldown routine |
||
511 | HASystem_Schedule(1,HA_OvertimeScheduleRoutine); -- Special overtime routine |
||
512 | HASystem_Schedule(1,HA_StatusScheduleRoutine); -- Special status routine |
||
513 | end |
||
514 | |||
515 | local function HA_StartupInitVars() |
||
516 | local playerName = UnitName("player"); |
||
517 | if((playerName) and (playerName ~= UNKNOWNOBJECT) and (playerName ~= UKNOWNBEING)) |
||
518 | then |
||
519 | -- Initialize Toon specific stuff |
||
520 | HA_PlayerName = playerName; |
||
521 | HA_NeedInit = false; |
||
522 | _HA_SetDefaultConfig("MinEmergencyPercent",90); |
||
523 | _HA_SetDefaultConfig("KeepValue",3); |
||
524 | _HA_SetDefaultConfig("ShowInstants",false); |
||
525 | _HA_SetDefaultConfig("ShowHoT",false); |
||
526 | _HA_SetDefaultConfig("ButtonPosition",190); |
||
527 | _HA_SetDefaultConfig("EmergencyGroups",{ true,true,true,true,true,true,true,true }); |
||
528 | _HA_SetDefaultConfig("EmergencyClasses",{ true,true,true,true,true,true,true,true }); |
||
529 | _HA_SetDefaultConfig("HealersClasses",{ true,true,true,true,true,true,true,true }); |
||
530 | _HA_SetDefaultConfig("AllowSpellRequest",{}); |
||
531 | _HA_SetDefaultConfig("HealersLines",10); |
||
532 | _HA_SetDefaultConfig("EmergLines",5); |
||
533 | _HA_SetDefaultConfig("Scale",100); |
||
534 | _HA_SetDefaultConfig("Alpha",100); |
||
535 | _HA_SetDefaultConfig("BackdropAlpha",100); |
||
536 | _HA_SetDefaultConfig("GUIRefresh",0.1); |
||
537 | _HA_SetDefaultConfig("Plugins",{}); |
||
538 | _HA_SetDefaultConfig("PluginOrder",{}); |
||
539 | _HA_SetDefaultConfig("PluginAuto",{}); |
||
540 | _HA_SetDefaultConfig("UseEstimatedHealth",true); |
||
541 | HA_CheckLoadPlugins(); |
||
542 | HA_SetNewLock(false); |
||
543 | HASystem_Schedule(5,_HA_ScheduledInit); |
||
544 | HA_MoveMinimapButton(); |
||
545 | -- Setup Default function |
||
546 | if(CastParty_OnClickByUnit and type(CastParty_OnClickByUnit) == "function") -- CastParty |
||
547 | then |
||
548 | HA_CustomOnClickFunction = CastParty_OnClickByUnit; |
||
549 | end |
||
550 | if(WatchDog_OnClick and type(WatchDog_OnClick) == "function") -- WatchDog |
||
551 | then |
||
552 | HA_CustomOnClickFunction = WatchDog_OnClick; |
||
553 | end |
||
554 | if(JC_CatchKeyBinding and type(JC_CatchKeyBinding) == "function") -- JustClick |
||
555 | then |
||
556 | HA_CustomOnClickFunction = JC_CatchKeyBinding; |
||
557 | end |
||
558 | end |
||
559 | end |
||
560 | |||
561 | function HA_PlayerHasBuf(texture) |
||
562 | for i=1,16 |
||
563 | do |
||
564 | local t = UnitBuff("player",i); |
||
565 | if(t == nil) then break; end; |
||
566 | if(t == texture) |
||
567 | then |
||
568 | return true; |
||
569 | end |
||
570 | end |
||
571 | return false; |
||
572 | end |
||
573 | |||
574 | local function HA_BuildRankString(ranknum) |
||
575 | local rankstr = ""; |
||
576 | |||
577 | if(ranknum and ranknum > 1) |
||
578 | then |
||
579 | for i=1,ranknum do |
||
580 | rankstr = rankstr.."I"; |
||
581 | end |
||
582 | end |
||
583 | |||
584 | return rankstr; |
||
585 | end |
||
586 | |||
587 | local function HA_Commands(command) |
||
588 | local i,j, cmd, param = string.find(command, "^([^ ]+) (.+)$"); |
||
589 | if(not cmd) then cmd = command; end |
||
590 | if(not cmd) then cmd = ""; end |
||
591 | if(not param) then param = ""; end |
||
592 | |||
593 | if((cmd == "") or (cmd == "help")) |
||
594 | then |
||
595 | local lock = "off"; |
||
596 | if(HA_Config.Lock) then lock = "on"; end |
||
597 | local auto = "off"; |
||
598 | if(HA_Config.Auto) then auto = "on"; end |
||
599 | HA_ChatPrint("Usage:"); |
||
600 | HA_ChatPrint(" |cffffffff/ha show|r - "..HA_CHAT_HELP_SHOW); |
||
601 | HA_ChatPrint(" |cffffffff/ha lock (on|off)|r |cff2040ff["..lock.."]|r - "..HA_CHAT_HELP_LOCK); |
||
602 | HA_ChatPrint(" |cffffffff/ha auto (on|off)|r |cff2040ff["..auto.."]|r - "..HA_CHAT_HELP_AUTO); |
||
603 | HA_ChatPrint(" |cffffffff/ha versions |r - "..HA_CHAT_HELP_VERSIONS); |
||
604 | HA_ChatPrint(" |cffffffff/ha msg <Msg to send>|r - "..HA_CHAT_HELP_MSG); |
||
605 | HA_ChatPrint(" ---- DEBUG ----"); |
||
606 | HA_ChatPrint(" |cffffffff/ha debug (on|off)|r - "..HA_CHAT_HELP_DEBUG); |
||
607 | elseif(cmd == "show") |
||
608 | then |
||
609 | HealersAssistMainFrame:Show(); |
||
610 | elseif(cmd == "lock") |
||
611 | then |
||
612 | if(param == "off") |
||
613 | then |
||
614 | HA_Config.Lock = nil; |
||
615 | elseif(param == "on") |
||
616 | then |
||
617 | HA_Config.Lock = true; |
||
618 | else |
||
619 | HA_ChatPrint(HA_CHAT_CMD_PARAM_ERROR.."lock"); |
||
620 | return; |
||
621 | end |
||
622 | HA_SetNewLock(true); |
||
623 | elseif(cmd == "auto") |
||
624 | then |
||
625 | if(param == "off") |
||
626 | then |
||
627 | HA_Config.Auto = nil; |
||
628 | elseif(param == "on") |
||
629 | then |
||
630 | HA_Config.Auto = true; |
||
631 | else |
||
632 | HA_ChatPrint(HA_CHAT_CMD_PARAM_ERROR.."auto"); |
||
633 | return; |
||
634 | end |
||
635 | elseif(cmd == "debug") |
||
636 | then |
||
637 | if(param == "off") |
||
638 | then |
||
639 | HA_DBG_SetDebugMode(0); |
||
640 | elseif(param == "on") |
||
641 | then |
||
642 | HA_DBG_SetDebugMode(1) |
||
643 | else |
||
644 | HA_ChatPrint(HA_CHAT_CMD_PARAM_ERROR.."debug"); |
||
645 | return; |
||
646 | end |
||
647 | elseif(cmd == "versions") |
||
648 | then |
||
649 | HA_ShowVersions(); |
||
650 | elseif(cmd == "msg" and param and param ~= "") |
||
651 | then |
||
652 | HA_GUI_Process_Announce(HA_PlayerName,param); |
||
653 | HA_COM_Announce(param); |
||
654 | else |
||
655 | HA_ChatPrint(HA_CHAT_CMD_UNKNOWN); |
||
656 | end |
||
657 | end |
||
658 | |||
659 | function CheckSpellTarget(FunctionHook) |
||
660 | if(SpellIsTargeting()) |
||
661 | then |
||
662 | HA_PotentialSpellTargetName = UnitName("mouseover"); |
||
663 | HA_ChatDebug(HA_DEBUG_ACTIONS,FunctionHook.." : PotentialTarget="..tostring(HA_PotentialSpellTargetName)); |
||
664 | elseif(UnitIsFriend("player","target")) |
||
665 | then |
||
666 | HA_SpellTargetName = UnitName("target"); |
||
667 | HA_ChatDebug(HA_DEBUG_ACTIONS,FunctionHook.." : Target="..tostring(HA_SpellTargetName)); |
||
668 | end |
||
669 | end |
||
670 | |||
671 | --------------- Hooked functions --------------- |
||
672 | |||
673 | function HealersAssist_SpellTargetUnit(unit) |
||
674 | if(SpellIsTargeting() or not HA_SpellTargetName) |
||
675 | then |
||
676 | HA_SpellTargetName = UnitName(unit); |
||
677 | HA_ChatDebug(HA_DEBUG_ACTIONS,"SpellTargetUnit : Target="..tostring(HA_SpellTargetName)); |
||
678 | end |
||
679 | return HA_Old_SpellTargetUnit(unit); |
||
680 | end |
||
681 | |||
682 | HA_Old_SpellTargetUnit = SpellTargetUnit; |
||
683 | SpellTargetUnit = HealersAssist_SpellTargetUnit; |
||
684 | |||
685 | -- |
||
686 | |||
687 | function HealersAssist_CastShapeshiftForm(index) |
||
688 | local ret_val = HA_Old_CastShapeshiftForm(index); |
||
689 | |||
690 | HA_ChatDebug(HA_DEBUG_ACTIONS,"CastShapeshiftForm : Index="..tostring(index)); |
||
691 | |||
692 | HA_CastingInstantSpell = nil; |
||
693 | HA_CastingInstantRank = 0; |
||
694 | return ret_val; |
||
695 | end |
||
696 | |||
697 | HA_Old_CastShapeshiftForm = CastShapeshiftForm; |
||
698 | CastShapeshiftForm = HealersAssist_CastShapeshiftForm; |
||
699 | |||
700 | -- |
||
701 | |||
702 | function HealersAssist_UseAction(id, val, onSelf) |
||
703 | HealersAssistTooltip:SetOwner(UIParent, "ANCHOR_NONE"); |
||
704 | HealersAssistTooltip:ClearLines(); |
||
705 | HealersAssistTooltip:SetAction(id); |
||
706 | local spellName = tostring(HealersAssistTooltipTextLeft1:GetText()); |
||
707 | local rank = HealersAssistTooltipTextRight1:GetText(); |
||
708 | local rankstr = ""; |
||
709 | HealersAssistTooltip:Hide(); |
||
710 | |||
711 | local ret_val = HA_Old_UseAction(id,val,onSelf); |
||
712 | |||
713 | if(rank and rank ~= "") |
||
714 | then |
||
715 | local _,_,ranknum = string.find(rank,HA_RANK.." (%d+)"); |
||
716 | rank = tonumber(ranknum,10); |
||
717 | elseif(HA_MaxRanks[spellName]) |
||
718 | then |
||
719 | rank = HA_MaxRanks[spellName]; |
||
720 | else |
||
721 | rank = 1; |
||
722 | end |
||
723 | |||
724 | -- Call plugins |
||
725 | for n,pl in HA_ActivePlugins |
||
726 | do |
||
727 | if(pl.OnEvent) |
||
728 | then |
||
729 | pl.OnEvent(HA_EVENT_USE_ACTION,{id,val,onSelf,spellName,rank}); |
||
730 | end |
||
731 | end |
||
732 | |||
733 | if(HA_Spells[spellName]) |
||
734 | then |
||
735 | CheckSpellTarget("UseAction"); |
||
736 | HA_ChatDebug(HA_DEBUG_ACTIONS,"UseAction : SpellName="..tostring(spellName).." Rank="..tostring(rank)); |
||
737 | HA_HookActionName = spellName; |
||
738 | HA_HookActionRank = rank; |
||
739 | end |
||
740 | |||
741 | if(HA_InstantSpells[spellName]) |
||
742 | then |
||
743 | CheckSpellTarget("UseAction"); |
||
744 | HA_CastingInstantSpell = spellName; |
||
745 | HA_CastingInstantRank = rank; |
||
746 | end |
||
747 | |||
748 | -- If onSelf |
||
749 | if(onSelf and onSelf == 1) |
||
750 | then |
||
751 | HA_SpellTargetName = HA_PlayerName; |
||
752 | HA_ChatDebug(HA_DEBUG_ACTIONS,"UseAction on Self : Target="..tostring(HA_SpellTargetName)); |
||
753 | end |
||
754 | return ret_val; |
||
755 | end |
||
756 | |||
757 | HA_Old_UseAction = UseAction; |
||
758 | UseAction = HealersAssist_UseAction; |
||
759 | |||
760 | -- |
||
761 | |||
762 | function HealersAssist_CastSpell(id,spellBook) |
||
763 | local ret_val = HealersAssist_Old_CastSpell(id,spellBook); |
||
764 | |||
765 | local spellName,rank = GetSpellName(id,spellBook); |
||
766 | |||
767 | if(rank and rank ~= "") |
||
768 | then |
||
769 | local _,_,ranknum = string.find(rank,HA_RANK.." (%d+)"); |
||
770 | rank = tonumber(ranknum,10); |
||
771 | elseif(HA_MaxRanks[spellName]) |
||
772 | then |
||
773 | rank = HA_MaxRanks[spellName]; |
||
774 | else |
||
775 | rank = 1; |
||
776 | end |
||
777 | |||
778 | -- Call plugins |
||
779 | for n,pl in HA_ActivePlugins |
||
780 | do |
||
781 | if(pl.OnEvent) |
||
782 | then |
||
783 | pl.OnEvent(HA_EVENT_CAST_SPELL,{id,spellBook,spellName,rank}); |
||
784 | end |
||
785 | end |
||
786 | |||
787 | if(HA_Spells[spellName]) |
||
788 | then |
||
789 | CheckSpellTarget("CastSpell"); |
||
790 | HA_ChatDebug(HA_DEBUG_ACTIONS,"CastSpell : SpellName="..tostring(spellName).." Rank="..tostring(rank)); |
||
791 | HA_HookActionName = spellName; |
||
792 | HA_HookActionRank = rank; |
||
793 | end |
||
794 | |||
795 | if(HA_InstantSpells[spellName]) |
||
796 | then |
||
797 | CheckSpellTarget("CastSpell"); |
||
798 | HA_CastingInstantSpell = spellName; |
||
799 | HA_CastingInstantRank = rank; |
||
800 | end |
||
801 | return ret_val; |
||
802 | end |
||
803 | |||
804 | HealersAssist_Old_CastSpell = CastSpell; |
||
805 | CastSpell = HealersAssist_CastSpell; |
||
806 | |||
807 | function HealersAssist_CastSpellByName(spell, onSelf) |
||
808 | local ret_val = HealersAssist_Old_CastSpellByName(spell, onSelf); |
||
809 | |||
810 | if(spell) |
||
811 | then |
||
812 | local _,_,spellName,rank = string.find(spell,"(.+)%("..HA_RANK.." (%d+)%)"); |
||
813 | if(spellName == nil) -- Spell without rank |
||
814 | then |
||
815 | spellName = spell; |
||
816 | end |
||
817 | |||
818 | if(rank) |
||
819 | then |
||
820 | rank = tonumber(rank,10); |
||
821 | elseif(HA_MaxRanks[spellName]) |
||
822 | then |
||
823 | rank = HA_MaxRanks[spellName]; |
||
824 | else |
||
825 | rank = 1; |
||
826 | end |
||
827 | |||
828 | -- Call plugins |
||
829 | for n,pl in HA_ActivePlugins |
||
830 | do |
||
831 | if(pl.OnEvent) |
||
832 | then |
||
833 | pl.OnEvent(HA_EVENT_CAST_SPELL_BY_NAME,{spell,onSelf,spellName,rank}); |
||
834 | end |
||
835 | end |
||
836 | |||
837 | if(HA_Spells[spellName]) |
||
838 | then |
||
839 | CheckSpellTarget("CastSpellByName"); |
||
840 | HA_ChatDebug(HA_DEBUG_ACTIONS,"CastSpellByName : SpellName="..tostring(spellName).." Rank="..tostring(rank)); |
||
841 | HA_HookActionName = spellName; |
||
842 | HA_HookActionRank = rank; |
||
843 | end |
||
844 | |||
845 | if(HA_InstantSpells[spellName]) |
||
846 | then |
||
847 | CheckSpellTarget("CastSpellByName"); |
||
848 | HA_CastingInstantSpell = spellName; |
||
849 | HA_CastingInstantRank = rank; |
||
850 | end |
||
851 | end |
||
852 | -- If onSelf |
||
853 | if(onSelf and onSelf == 1) |
||
854 | then |
||
855 | HA_SpellTargetName = HA_PlayerName; |
||
856 | HA_ChatDebug(HA_DEBUG_ACTIONS,"CastSpellByName on Self : Target="..tostring(HA_SpellTargetName)); |
||
857 | end |
||
858 | return ret_val; |
||
859 | end |
||
860 | |||
861 | HealersAssist_Old_CastSpellByName = CastSpellByName; |
||
862 | CastSpellByName = HealersAssist_CastSpellByName; |
||
863 | |||
864 | -- |
||
865 | |||
866 | local function _HA_GetISpell(SpellName) |
||
867 | if(HA_Spells[SpellName]) |
||
868 | then |
||
869 | return HA_Spells[SpellName].iname; |
||
870 | elseif(HA_InstantSpells[SpellName]) |
||
871 | then |
||
872 | return HA_InstantSpells[SpellName].iname; |
||
873 | end |
||
874 | return nil; |
||
875 | end |
||
876 | |||
877 | function HA_UnitHasBlessingOfLight(TargetName) |
||
878 | local id = nil; |
||
879 | if(TargetName) |
||
880 | then |
||
881 | if(HA_Raiders[TargetName] and HA_Raiders[TargetName].id) |
||
882 | then |
||
883 | id = HA_Raiders[TargetName].id; |
||
884 | elseif(UnitName("target") == TargetName) |
||
885 | then |
||
886 | id = "target"; |
||
887 | end |
||
888 | end |
||
889 | if(id) |
||
890 | then |
||
891 | for i=1,16 |
||
892 | do |
||
893 | local t = UnitBuff(id,i,1); |
||
894 | if(t == nil) then break; end; |
||
895 | if(t == HA_BLESSING_OF_LIGHT_TEXTURE or t == HA_GREATER_BLESSING_OF_LIGHT_TEXTURE) |
||
896 | then |
||
897 | return true; |
||
898 | end |
||
899 | end |
||
900 | end |
||
901 | return false; |
||
902 | end |
||
903 | |||
904 | local function _HA_GetEstimated(ISpell,IHookName,HookRank,TargetName,CastTime) |
||
905 | local estimated = 0; |
||
906 | local spiritadd = 0; |
||
907 | local willcrit = false; |
||
908 | |||
909 | if(IHookName and HookRank and ISpell == IHookName and HA_SpellRanks[ISpell] and HA_SpellRanks[ISpell][HookRank]) |
||
910 | then |
||
911 | local infos = HA_SpellRanks[ISpell][HookRank]; |
||
912 | |||
913 | estimated = infos.base; |
||
914 | |||
915 | -- Add Talent values |
||
916 | local tinfos = HA_SpellTalents[ISpell]; |
||
917 | if(tinfos) |
||
918 | then |
||
919 | if(tinfos.ratios) -- Ratio |
||
920 | then |
||
921 | --[[ -- Old code (if talent bonus are applied one after another, and not all at once) |
||
922 | for _,tid in tinfos.ratios |
||
923 | do |
||
924 | if(HA_Talents[tid] and HA_Talents[tid].rank) -- Talent found, and player's rank set |
||
925 | then |
||
926 | if(HA_Talents[tid].rankratio) -- Direct ratios |
||
927 | then |
||
928 | estimated = estimated * HA_Talents[tid].rankratio[HA_Talents[tid].rank]; |
||
929 | elseif(HA_Talents[tid].spiritratio) -- Spirit based ratios |
||
930 | then |
||
931 | spiritadd = HA_Talents[tid].spiritratio[HA_Talents[tid].rank] * UnitStat("player",5); |
||
932 | end |
||
933 | end |
||
934 | end |
||
935 | ]] |
||
936 | local total_percent = 1.0; |
||
937 | for _,tid in tinfos.ratios |
||
938 | do |
||
939 | if(HA_Talents[tid] and HA_Talents[tid].rank) -- Talent found, and player's rank set |
||
940 | then |
||
941 | if(HA_Talents[tid].rankratio) -- Direct ratios |
||
942 | then |
||
943 | total_percent = total_percent + HA_Talents[tid].rankratio[HA_Talents[tid].rank]; |
||
944 | elseif(HA_Talents[tid].spiritratio) -- Spirit based ratios |
||
945 | then |
||
946 | spiritadd = HA_Talents[tid].spiritratio[HA_Talents[tid].rank] * UnitStat("player",5); |
||
947 | end |
||
948 | end |
||
949 | end |
||
950 | estimated = estimated * total_percent; |
||
951 | end |
||
952 | end |
||
953 | |||
954 | -- Add +heal values |
||
955 | local itembonus; |
||
956 | if(_HA_UseBonusScannerAddon) |
||
957 | then |
||
958 | itembonus = tonumber(BonusScanner.bonuses["HEAL"]); |
||
959 | else |
||
960 | itembonus = tonumber(HA_BonusScanner_bonuses["HEAL"]); |
||
961 | end |
||
962 | if(itembonus) |
||
963 | then |
||
964 | if(HA_LibramItem) -- Check for librams |
||
965 | then |
||
966 | if(ISpell == HA_SPELL_FLASH_OF_LIGHT and HA_LibramItem == 23201) -- Libram of Divinity |
||
967 | then |
||
968 | itembonus = itembonus + 53; |
||
969 | elseif(ISpell == HA_SPELL_FLASH_OF_LIGHT and HA_LibramItem == 23006) -- Libram of Light |
||
970 | then |
||
971 | itembonus = itembonus + 83; |
||
972 | elseif(ISpell == HA_SPELL_LESSER_HEALING_WAVE and HA_LibramItem == 23200) -- Totem of Sustaining |
||
973 | then |
||
974 | itembonus = itembonus + 53; |
||
975 | elseif(ISpell == HA_SPELL_LESSER_HEALING_WAVE and HA_LibramItem == 22396) -- Totem of Life |
||
976 | then |
||
977 | itembonus = itembonus + 80; |
||
978 | elseif(ISpell == HA_SPELL_REJUVENATION and HA_LibramItem == 22398) -- Idol of Rejuvenation |
||
979 | then |
||
980 | itembonus = itembonus + 62.5; -- Real value is 50, but this value will be 80% applied below, but the game does not apply the 80% rule on the idol |
||
981 | end |
||
982 | end |
||
983 | estimated = estimated + itembonus * infos.castratio * infos.levelratio; |
||
984 | end |
||
985 | |||
986 | -- Add + Blessing of light value |
||
987 | if(HA_SpellTalents[ISpell] and HA_SpellTalents[ISpell].blessing) -- Check for Blessing of light |
||
988 | then |
||
989 | if(HA_UnitHasBlessingOfLight(TargetName)) |
||
990 | then |
||
991 | estimated = estimated + HA_SpellTalents[ISpell].blessing; |
||
992 | end |
||
993 | end |
||
994 | |||
995 | -- Check for WillCrit |
||
996 | local index = 0; |
||
997 | local texture; |
||
998 | while(GetPlayerBuffTexture(index)) |
||
999 | do |
||
1000 | texture = GetPlayerBuffTexture(index); |
||
1001 | applications = GetPlayerBuffApplications(index); |
||
1002 | if(texture == HA_DIVINE_FAVOR_TEXTURE) |
||
1003 | then |
||
1004 | willcrit = true; |
||
1005 | elseif(texture == HA_UNSTABLE_POWER_TEXTURE) |
||
1006 | then |
||
1007 | estimated = estimated + (70 * applications * infos.castratio * infos.levelratio); |
||
1008 | elseif(texture == HA_HEALING_OF_THE_AGES_TEXTURE) |
||
1009 | then |
||
1010 | estimated = estimated + (350 * infos.castratio * infos.levelratio); |
||
1011 | end |
||
1012 | index = index + 1; |
||
1013 | end |
||
1014 | |||
1015 | if(willcrit) |
||
1016 | then |
||
1017 | estimated = estimated * 1.5; |
||
1018 | end |
||
1019 | end |
||
1020 | |||
1021 | return floor(estimated+spiritadd),willcrit; |
||
1022 | end |
||
1023 | |||
1024 | local function _HA_GetDuration(ISpell) |
||
1025 | local duration = 0; |
||
1026 | |||
1027 | if(HA_SpellOvertime[ISpell]) |
||
1028 | then |
||
1029 | local infos = HA_SpellOvertime[ISpell]; |
||
1030 | |||
1031 | duration = infos.duration; |
||
1032 | |||
1033 | -- Add Talent values for duration |
||
1034 | -- Add armor values for duration |
||
1035 | |||
1036 | end |
||
1037 | |||
1038 | return duration; |
||
1039 | end |
||
1040 | |||
1041 | local function _HA_DoStop(resetSpell,msg) |
||
1042 | HA_ChatDebug(HA_DEBUG_ACTIONS,"HA_DoStop : Event="..msg.." CmdSend="..tostring(HA_StopCommandSent).." LastTime="..HA_StopCommandLastTime.." CurTime="..HA_CurrentTime); |
||
1043 | if(not HA_StopCommandSent and (HA_StopCommandLastTime+0.10 < HA_CurrentTime)) |
||
1044 | then |
||
1045 | HA_GUI_Process_SpellStop(HA_PlayerName); |
||
1046 | HA_COM_SpellStop(); |
||
1047 | HA_StopCommandSent = true; |
||
1048 | HA_StopCommandLastTime = HA_CurrentTime; |
||
1049 | if(resetSpell) |
||
1050 | then |
||
1051 | HA_CastingSpell = nil; |
||
1052 | end |
||
1053 | end |
||
1054 | end |
||
1055 | |||
1056 | local function _HA_RegExpr_CallBack(event, Source, Target, SpellName, Value, Crit) |
||
1057 | -- Check for HoT Ticks |
||
1058 | if(event == "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS" or |
||
1059 | event == "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS" or |
||
1060 | event == "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS") |
||
1061 | then |
||
1062 | local ispell = HA_HotSpells[SpellName]; |
||
1063 | if(ispell) |
||
1064 | then |
||
1065 | HA_ChatDebug(HA_DEBUG_SPELLS,"Callback HOT : Source="..tostring(Source).." Target="..tostring(Target).." Spell="..tostring(SpellName).." ("..ispell..") Value="..tostring(Value)); |
||
1066 | HA_GUI_Process_SpellHotTick(Source,ispell,Target,Value); |
||
1067 | HA_COM_SpellHotTick(ispell,Target,Value); |
||
1068 | end |
||
1069 | |||
1070 | else -- Ok, check for direct heal spells |
||
1071 | local spell = HA_Spells[SpellName]; |
||
1072 | local instaspell = false; |
||
1073 | if(spell == nil) -- Not casted, check instant |
||
1074 | then |
||
1075 | spell = HA_InstantSpells[SpellName]; |
||
1076 | instaspell = true; |
||
1077 | end |
||
1078 | if(spell) |
||
1079 | then |
||
1080 | if(event == "CHAT_MSG_SPELL_SELF_BUFF") -- Heal from self |
||
1081 | then |
||
1082 | local ispell = _HA_GetISpell(SpellName); |
||
1083 | if(not instaspell) |
||
1084 | then |
||
1085 | _HA_DoStop(true,"HIT"); |
||
1086 | end |
||
1087 | HA_GUI_Process_SpellHit(Source,ispell,Target,Value,Crit); |
||
1088 | HA_COM_SpellComplete(ispell,Target,Value,Crit); |
||
1089 | -- Special HA_SPELL_REGROWTH case |
||
1090 | if(ispell == HA_SPELL_REGROWTH) |
||
1091 | then |
||
1092 | ispell = HA_SPELL_REGROWTH_HOT; |
||
1093 | local estimated = _HA_GetEstimated(ispell,ispell,HA_LastRegrowthRank,Target,0); |
||
1094 | local duration = _HA_GetDuration(ispell); |
||
1095 | if(duration ~= 0) |
||
1096 | then |
||
1097 | HA_GUI_Process_SpellOvertime(HA_PlayerName,ispell,Target,duration,estimated,HA_LastRegrowthRank); |
||
1098 | HA_COM_SpellOvertime(ispell,Target,duration,estimated,HA_LastRegrowthRank); |
||
1099 | end |
||
1100 | end |
||
1101 | else -- Heal from other |
||
1102 | if(not spell.group) |
||
1103 | then |
||
1104 | local ispell = _HA_GetISpell(SpellName); |
||
1105 | HA_GUI_Process_SpellHit(Source,ispell,Target,Value,Crit); |
||
1106 | end |
||
1107 | end |
||
1108 | end |
||
1109 | end |
||
1110 | end |
||
1111 | |||
1112 | local function _HA_CheckRegenModeFromCast() |
||
1113 | local healer = HA_MyselfHealer; |
||
1114 | if(healer and healer.State == HA_STATE_RESTING) |
||
1115 | then |
||
1116 | HA_SetRegenMode(false); |
||
1117 | end |
||
1118 | end |
||
1119 | |||
1120 | local function _HA_ScanScheduleRoutine() |
||
1121 | HA_ChatDebug(HA_DEBUG_GLOBAL,"_HA_ScanScheduleRoutine : Scanning bonuses"); |
||
1122 | -- Check for Items bonuses |
||
1123 | if(not _HA_UseBonusScannerAddon) |
||
1124 | then |
||
1125 | HA_ChatDebug(HA_DEBUG_GLOBAL,"_HA_ScanScheduleRoutine : Not using BonusScanner addon - Scanning equipment !"); |
||
1126 | HA_BonusScanner_ScanAll(); |
||
1127 | end |
||
1128 | -- Check for Relic |
||
1129 | local libramlink = GetInventoryItemLink("player",18); |
||
1130 | if(libramlink) |
||
1131 | then |
||
1132 | for iItemId, iEnchantId, iPropertieId, sItemName in string.gfind(libramlink, "|c%x+|Hitem:(%d+):(%d+):(%d+):%d+|h%[(.-)%]|h|r") |
||
1133 | do |
||
1134 | HA_LibramItem = tonumber(iItemId); |
||
1135 | end |
||
1136 | else |
||
1137 | HA_LibramItem = nil; |
||
1138 | end |
||
1139 | -- Ok done |
||
1140 | _HA_BonusScanScheduled = false; |
||
1141 | end |
||
1142 | |||
1143 | local function _HA_GetReasonCode(Reason) |
||
1144 | for i,n in HA_FailReasons |
||
1145 | do |
||
1146 | if(Reason == n) |
||
1147 | then |
||
1148 | return i,""; |
||
1149 | end |
||
1150 | end |
||
1151 | return 0,Reason; |
||
1152 | end |
||
1153 | |||
1154 | local function _HA_CheckForBonusScan() |
||
1155 | if(not _HA_BonusScanScheduled) |
||
1156 | then |
||
1157 | _HA_BonusScanScheduled = true; |
||
1158 | HASystem_Schedule(2,_HA_ScanScheduleRoutine); -- Schedule scan in 2 sec |
||
1159 | end |
||
1160 | end |
||
1161 | |||
1162 | local function _HA_RegisterEvents() |
||
1163 | HealersAssistMainFrame:RegisterEvent("UNIT_INVENTORY_CHANGED"); |
||
1164 | end |
||
1165 | |||
1166 | local function _HA_UnregisterEvents() |
||
1167 | HealersAssistMainFrame:UnregisterEvent("UNIT_INVENTORY_CHANGED"); |
||
1168 | end |
||
1169 | |||
1170 | local function _HA_CheckLifeUpdates(raider,new_hp) |
||
1171 | if(HA_Config.UseEstimatedHealth) |
||
1172 | then |
||
1173 | local estim = raider.hp_real; |
||
1174 | local updates = raider.life_updates; |
||
1175 | |||
1176 | --[[if(updates[1] == nil and new_hp == estim) |
||
1177 | then |
||
1178 | HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_HEALTH Diff OK : NewHP="..new_hp.." - Got no updates"); |
||
1179 | end]] |
||
1180 | |||
1181 | while(updates[1]) |
||
1182 | do |
||
1183 | estim = estim + updates[1].value; |
||
1184 | table.remove(updates,1); |
||
1185 | if(estim == new_hp) |
||
1186 | then |
||
1187 | --HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_HEALTH Diff Matching ("..table.getn(updates).." remaning updates) : NewHP="..new_hp); |
||
1188 | break; |
||
1189 | end |
||
1190 | end |
||
1191 | if(estim > raider.hpmax) then estim = raider.hpmax; end |
||
1192 | if(new_hp ~= estim) |
||
1193 | then |
||
1194 | --HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_HEALTH Diff Error : NewHP="..new_hp.." Ignoring next Wound Event"); |
||
1195 | raider.ignore_next_wound = HA_CurrentTime; |
||
1196 | end |
||
1197 | end |
||
1198 | raider.hp_estim = new_hp; |
||
1199 | end |
||
1200 | |||
1201 | -- Currently don't handle "STOP because of failure" for casted request-spell |
||
1202 | local function _HA_CheckSpellRequestSuccess(spell,instant) |
||
1203 | if(HA_SpellRequest and HA_SpellRequest.spell == spell) |
||
1204 | then |
||
1205 | HA_ChatDebug(HA_DEBUG_ACTIONS,"_HA_CheckSpellRequestSuccess : SpellRequest successfully casted (or stopped for casted ones) : "..tostring(spell).." : "..tostring(instant)); |
||
1206 | HA_SpellRequest = nil; |
||
1207 | StaticPopup_Hide("HA_REQUEST_FOR_SPELL"); |
||
1208 | end |
||
1209 | end |
||
1210 | |||
1211 | local function _HA_CheckSpellRequestFailed(spell,reason) |
||
1212 | if(HA_SpellRequest and HA_SpellRequest.spell == spell) |
||
1213 | then |
||
1214 | HA_ChatDebug(HA_DEBUG_ACTIONS,"_HA_CheckSpellRequestFailed : SpellRequest failed for "..tostring(spell).." : "..tostring(reason)); |
||
1215 | HA_SpellRequest.failure = reason; |
||
1216 | end |
||
1217 | end |
||
1218 | |||
1219 | local function _HA_ProcessEvent_SpellCastStart() |
||
1220 | _HA_CheckRegenModeFromCast(); |
||
1221 | if(HA_Spells[arg1]) |
||
1222 | then |
||
1223 | _HA_DoStop(false,"START"); |
||
1224 | HA_CastingSpell = arg1; |
||
1225 | HA_StopCommandSent = false; -- Set *waiting for stop* state |
||
1226 | HA_StopCommandLastTime = HA_CurrentTime; -- And reset time |
||
1227 | if(HA_SpellTargetName == nil) |
||
1228 | then |
||
1229 | HA_SpellTargetName = HA_PotentialSpellTargetName; |
||
1230 | HA_ChatDebug(HA_DEBUG_ACTIONS,"SPELLCAST_START : Target="..tostring(HA_SpellTargetName)); |
||
1231 | end |
||
1232 | local casttime = tonumber(arg2,10) |
||
1233 | local target = HA_SpellTargetName; |
||
1234 | local ispell = _HA_GetISpell(HA_CastingSpell); |
||
1235 | local ihook = _HA_GetISpell(HA_HookActionName); |
||
1236 | local estimated,willcrit = _HA_GetEstimated(ispell,ihook,HA_HookActionRank,target,casttime); |
||
1237 | HA_GUI_Process_SpellStart(HA_PlayerName,ispell,target,casttime,estimated,willcrit,HA_HookActionRank); |
||
1238 | HA_COM_SpellStart(ispell,target,casttime,estimated,willcrit,HA_HookActionRank); |
||
1239 | -- Special HA_SPELL_REGROWTH case |
||
1240 | if(ispell == HA_SPELL_REGROWTH) |
||
1241 | then |
||
1242 | HA_LastRegrowthRank = HA_HookActionRank; |
||
1243 | end |
||
1244 | end |
||
1245 | HA_SpellTargetName = nil; |
||
1246 | end |
||
1247 | |||
1248 | local function _HA_ProcessEvent_SpellCastStop() |
||
1249 | _HA_CheckRegenModeFromCast(); |
||
1250 | if(HA_CastingInstantSpell) -- An instant spell ? |
||
1251 | then |
||
1252 | if(HA_SpellTargetName == nil) |
||
1253 | then |
||
1254 | HA_SpellTargetName = HA_PotentialSpellTargetName; |
||
1255 | HA_ChatDebug(HA_DEBUG_ACTIONS,"SPELLCAST_STOP (INSTANT SPELL) : Target="..tostring(HA_SpellTargetName)); |
||
1256 | end |
||
1257 | local target = HA_SpellTargetName; |
||
1258 | local ispell = _HA_GetISpell(HA_CastingInstantSpell); |
||
1259 | if(HA_InstantSpells[HA_CastingInstantSpell].cooldown) -- A cooldown instant spell |
||
1260 | then |
||
1261 | HA_GUI_Process_SpellCooldown(HA_PlayerName,ispell,target); |
||
1262 | HA_COM_SpellCooldown(ispell,target); |
||
1263 | elseif(HA_InstantSpells[HA_CastingInstantSpell].nonheal) -- A non-heal spell |
||
1264 | then |
||
1265 | HA_GUI_Process_SpellInstant(HA_PlayerName,ispell,target,HA_CastingInstantRank); |
||
1266 | HA_COM_SpellInstant(ispell,target,HA_CastingInstantRank); |
||
1267 | else |
||
1268 | local estimated = _HA_GetEstimated(ispell,ispell,HA_CastingInstantRank,target,0); |
||
1269 | local duration = _HA_GetDuration(ispell); |
||
1270 | if(duration ~= 0) |
||
1271 | then |
||
1272 | HA_GUI_Process_SpellOvertime(HA_PlayerName,ispell,target,duration,estimated,HA_CastingInstantRank); |
||
1273 | HA_COM_SpellOvertime(ispell,target,duration,estimated,HA_CastingInstantRank); |
||
1274 | end |
||
1275 | end |
||
1276 | _HA_CheckSpellRequestSuccess(HA_CastingInstantSpell,true); |
||
1277 | HA_CastingInstantSpell = nil; |
||
1278 | elseif(HA_CastingSpell) |
||
1279 | then |
||
1280 | HA_ChatDebug(HA_DEBUG_ACTIONS,"SPELLCAST_STOP : Spell="..tostring(HA_CastingSpell)); |
||
1281 | _HA_CheckSpellRequestSuccess(HA_CastingSpell,false); |
||
1282 | _HA_DoStop(false,"STOP"); |
||
1283 | end |
||
1284 | HA_SpellTargetName = nil; |
||
1285 | end |
||
1286 | |||
1287 | |||
1288 | --------------- Shared functions --------------- |
||
1289 | |||
1290 | function HA_GetSpellIDFromName(spellName,spellRank) |
||
1291 | local i = 1; |
||
1292 | local name,rank = GetSpellName(i,BOOKTYPE_SPELL); |
||
1293 | local searched; |
||
1294 | |||
1295 | if(spellRank) -- With rank |
||
1296 | then |
||
1297 | if(type(spellRank) == "number") -- Number |
||
1298 | then |
||
1299 | searched = spellName.."("..HA_RANK.." "..tostring(spellRank)..")"; |
||
1300 | else -- String |
||
1301 | searched = spellName.."("..spellRank..")"; |
||
1302 | end |
||
1303 | else -- No rank |
||
1304 | searched = spellName; |
||
1305 | end |
||
1306 | |||
1307 | while(name) |
||
1308 | do |
||
1309 | local current; |
||
1310 | if(rank ~= "") -- With rank |
||
1311 | then |
||
1312 | current = name.."("..rank..")"; |
||
1313 | else -- No rank |
||
1314 | current = name; |
||
1315 | end |
||
1316 | if(searched == current) -- Found |
||
1317 | then |
||
1318 | return i; |
||
1319 | end |
||
1320 | i = i + 1; |
||
1321 | name,rank = GetSpellName(i,BOOKTYPE_SPELL); |
||
1322 | end |
||
1323 | return 0; |
||
1324 | end |
||
1325 | |||
1326 | local function HA_CheckForEmergencyListUpdate() |
||
1327 | -- Update Emergency every 30 msec |
||
1328 | if(HA_CurrentTime > (_HA_LastTimeEmergency+0.030)) |
||
1329 | then |
||
1330 | HA_UpdateListEmergency(); |
||
1331 | _HA_LastTimeEmergency = HA_CurrentTime; |
||
1332 | end |
||
1333 | end |
||
1334 | |||
1335 | --------------- XML functions --------------- |
||
1336 | |||
1337 | function HA_OnEvent() |
||
1338 | if(event == "VARIABLES_LOADED") |
||
1339 | then |
||
1340 | if(HA_NeedInit) |
||
1341 | then |
||
1342 | HA_StartupInitVars(); |
||
1343 | end |
||
1344 | return; |
||
1345 | elseif(event == "PLAYER_LOGIN") |
||
1346 | then |
||
1347 | HA_MaxRanks = _HA_GetMaxSpellRanks(); |
||
1348 | elseif(event == "PLAYER_ENTERING_WORLD") |
||
1349 | then |
||
1350 | _HA_AnalyseGroupRaidMembers(); -- Force group analyse now |
||
1351 | HA_CurrentZone = GetRealZoneText(); -- Get it here too, because when you /reloadui the ZONE_CHANGED is not called - Thanks blizzard |
||
1352 | _HA_RegisterEvents(); |
||
1353 | _HA_CheckForBonusScan(); |
||
1354 | HA_CurrentTarget = nil |
||
1355 | if(HA_Config.Auto and HA_CurrentGroupMode ~= HA_MODE_SOLO) |
||
1356 | then |
||
1357 | HealersAssistMainFrame:Show(); |
||
1358 | end |
||
1359 | elseif(event == "PLAYER_LEAVING_WORLD") |
||
1360 | then |
||
1361 | _HA_UnregisterEvents(); |
||
1362 | elseif(event == "ZONE_CHANGED_NEW_AREA") |
||
1363 | then |
||
1364 | HA_CurrentZone = GetRealZoneText(); |
||
1365 | end |
||
1366 | |||
1367 | if(event == "UNIT_COMBAT") |
||
1368 | then |
||
1369 | if(HA_Config.UseEstimatedHealth) |
||
1370 | then |
||
1371 | local raider = HA_RaidersByID[arg1]; |
||
1372 | if(raider and arg1 ~= "target") |
||
1373 | then |
||
1374 | if(arg2 == "WOUND") |
||
1375 | then |
||
1376 | if(HA_CurrentTime > (raider.ignore_next_wound+0.5)) |
||
1377 | then |
||
1378 | --HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_COMBAT '"..tostring(arg1).."' ("..tostring(raider.name)..") : DEGATS : "..tostring(arg4).." : UnitHealth="..UnitHealth(arg1).." hp="..raider.hp_real); |
||
1379 | raider.hp_estim = raider.hp_estim - arg4; |
||
1380 | if(raider.hp_estim < 0) then raider.hp_estim = 0; end |
||
1381 | tinsert(raider.life_updates,{ value=-arg4; stamp=HA_CurrentTime }); |
||
1382 | --[[else |
||
1383 | HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_COMBAT '"..tostring(arg1).."' ("..tostring(raider.name)..") : DEGATS : "..tostring(arg4).." : UnitHealth="..UnitHealth(arg1).." hp="..raider.hp_real.." - IGNORED");]] |
||
1384 | end |
||
1385 | raider.ignore_next_wound = 0; |
||
1386 | elseif(arg2 == "HEAL") |
||
1387 | then |
||
1388 | --HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_COMBAT '"..tostring(arg1).."' ("..tostring(raider.name)..") : SOINS : "..tostring(arg4)); |
||
1389 | tinsert(raider.heal_updates,{ value=arg4, oldhp=raider.hp_estim }); -- Store health before applying heal |
||
1390 | raider.hp_estim = raider.hp_estim + arg4; |
||
1391 | if(raider.hp_estim > raider.hpmax) then raider.hp_estim = raider.hpmax; end |
||
1392 | tinsert(raider.life_updates,{ value=arg4; stamp=HA_CurrentTime }); |
||
1393 | if(getn(raider.heal_updates) > HA_MAX_HEAL_UPDATES) -- Remove a heal update, if too many in the array |
||
1394 | then |
||
1395 | table.remove(raider.heal_updates,1); |
||
1396 | end |
||
1397 | else |
||
1398 | --HA_ChatDebug(HA_DEBUG_GLOBAL,"UNIT_COMBAT '"..tostring(arg1).."' ("..tostring(raider.name)..") : "..tostring(arg2).." : "..tostring(arg4).." : "..tostring(arg3)); |
||
1399 | end |
||
1400 | raider.hp = raider.hp_estim; -- Update HP value |
||
1401 | end |
||
1402 | end |
||
1403 | return; |
||
1404 | |||
1405 | -- Health/Mana events |
||
1406 | elseif(event == "UNIT_HEALTH") |
||
1407 | then |
||
1408 | local raider = HA_RaidersByID[arg1]; |
||
1409 | if(raider) |
||
1410 | then |
||
1411 | local new_hp = UnitHealth(arg1); |
||
1412 | if(arg1 ~= "target") |
||
1413 | then |
||
1414 | _HA_CheckLifeUpdates(raider,new_hp); -- Parse "updates" array, and update hp_estim to 'new_hp' value |
||
1415 | end |
||
1416 | raider.hp_real = new_hp; |
||
1417 | raider.hp = new_hp; |
||
1418 | raider.percent = floor(raider.hp / raider.hpmax * 100); |
||
1419 | HA_CheckForEmergencyListUpdate(); |
||
1420 | end |
||
1421 | return; |
||
1422 | elseif(event == "UNIT_MAXHEALTH") |
||
1423 | then |
||
1424 | local raider = HA_RaidersByID[arg1]; |
||
1425 | if(raider) |
||
1426 | then |
||
1427 | raider.hpmax = UnitHealthMax(arg1); |
||
1428 | raider.percent = floor(raider.hp / raider.hpmax * 100); |
||
1429 | HA_CheckForEmergencyListUpdate(); |
||
1430 | end |
||
1431 | return; |
||
1432 | elseif(event == "UNIT_MANA") |
||
1433 | then |
||
1434 | local raider = HA_RaidersByID[arg1]; |
||
1435 | if(raider and raider.ishealer) |
||
1436 | then |
||
1437 | raider.mp = UnitMana(arg1); |
||
1438 | raider.mppercent = floor(raider.mp / raider.mpmax * 100); |
||
1439 | end |
||
1440 | return; |
||
1441 | elseif(event == "UNIT_MAXMANA") |
||
1442 | then |
||
1443 | local raider = HA_RaidersByID[arg1]; |
||
1444 | if(raider and raider.ishealer) |
||
1445 | then |
||
1446 | raider.mpmax = UnitManaMax(arg1); |
||
1447 | raider.mppercent = floor(raider.mp / raider.mpmax * 100); |
||
1448 | end |
||
1449 | return; |
||
1450 | elseif(event == "PLAYER_AURAS_CHANGED") |
||
1451 | then |
||
1452 | if(HA_MyselfHealer and not HA_RaiderInfused(HA_PlayerName) and HA_PlayerHasBuf(HA_POWER_INFUSION_TEXTURE)) |
||
1453 | then |
||
1454 | HA_GUI_Process_GotPowerInfusion(HA_PlayerName); |
||
1455 | HA_COM_GotPowerInfusion(); |
||
1456 | end |
||
1457 | return; |
||
1458 | end |
||
1459 | |||
1460 | -- Group events |
||
1461 | if(event == "PARTY_MEMBERS_CHANGED" or event == "RAID_ROSTER_UPDATE") |
||
1462 | then |
||
1463 | HA_ChatDebug(HA_DEBUG_RAIDERS,event.." : Party members changed. Analysing Raiders..."); |
||
1464 | debugprofilestart(); |
||
1465 | _HA_AnalyseGroupRaidMembers(); |
||
1466 | HA_PROFILE_AnalyseRaidersRoutine = debugprofilestop(); |
||
1467 | return; |
||
1468 | end |
||
1469 | |||
1470 | -- Inventory events |
||
1471 | if(HA_NeedInit == false and event == "UNIT_INVENTORY_CHANGED") |
||
1472 | then |
||
1473 | _HA_CheckForBonusScan(); |
||
1474 | return; |
||
1475 | end |
||
1476 | |||
1477 | -- Mouse over event - Get target |
||
1478 | if(event == "UPDATE_MOUSEOVER_UNIT") |
||
1479 | then |
||
1480 | if(SpellIsTargeting() and UnitIsFriend("player", "mouseover")) |
||
1481 | then |
||
1482 | HA_PotentialSpellTargetName = UnitName("mouseover"); |
||
1483 | HA_ChatDebug(HA_DEBUG_ACTIONS,"MouseOverUpdate : PotentialTarget="..tostring(HA_PotentialSpellTargetName)); |
||
1484 | end |
||
1485 | return; |
||
1486 | end |
||
1487 | |||
1488 | -- Target changed |
||
1489 | if(event == "PLAYER_TARGET_CHANGED" ) |
||
1490 | then |
||
1491 | if(UnitExists("target") and UnitIsFriend("player","target")) -- Add target if don't exist |
||
1492 | then |
||
1493 | local name = UnitName("target"); |
||
1494 | local raider = HA_Raiders[name]; |
||
1495 | if(raider == nil) -- Don't exist, add it as subgrp 0 |
||
1496 | then |
||
1497 | raider = _HA_CreateRaider(name); |
||
1498 | HA_Raiders[name] = raider; |
||
1499 | _HA_SetFullRaiderVariables(raider,"target",0,0); |
||
1500 | HA_UpdateListEmergency(); |
||
1501 | -- Call plugins |
||
1502 | for n,pl in HA_ActivePlugins |
||
1503 | do |
||
1504 | if(pl.OnEvent) |
||
1505 | then |
||
1506 | pl.OnEvent(HA_EVENT_RAIDER_JOINED,{name}); |
||
1507 | end |
||
1508 | end |
||
1509 | end |
||
1510 | HA_RaidersByID["target"] = raider; |
||
1511 | HA_CurrentTarget = name; |
||
1512 | else -- No valid target |
||
1513 | HA_RaidersByID["target"] = nil; |
||
1514 | HA_CurrentTarget = nil |
||
1515 | end |
||
1516 | HA_PotentialSpellTargetName = HA_CurrentTarget; |
||
1517 | return; |
||
1518 | end |
||
1519 | |||
1520 | -- System events |
||
1521 | if(event == "CHAT_MSG_SYSTEM") |
||
1522 | then |
||
1523 | if(arg1 == MARKED_AFK or string.find(arg1,string.format(MARKED_AFK_MESSAGE,".*"))) |
||
1524 | then |
||
1525 | HA_AFK_Mode = true; |
||
1526 | end |
||
1527 | if(arg1 == CLEARED_AFK) |
||
1528 | then |
||
1529 | HA_AFK_Mode = false; |
||
1530 | end |
||
1531 | elseif(event == "CHAT_MSG_ADDON" and (arg3 == "RAID" or arg3 == "PARTY") and arg1 == HA_ADDON_PREFIX) |
||
1532 | then |
||
1533 | HA_COM_ParseMessage(arg4,arg2); |
||
1534 | |||
1535 | -- Spell Events |
||
1536 | elseif(event == "SPELLCAST_START") |
||
1537 | then |
||
1538 | _HA_ProcessEvent_SpellCastStart(); |
||
1539 | elseif(event == "SPELLCAST_STOP") |
||
1540 | then |
||
1541 | _HA_ProcessEvent_SpellCastStop(); |
||
1542 | elseif(event == "SPELLCAST_DELAYED") |
||
1543 | then |
||
1544 | if(HA_CastingSpell) |
||
1545 | then |
||
1546 | HA_GUI_Process_SpellDelayed(HA_PlayerName,arg1); |
||
1547 | HA_COM_SpellDelayed(arg1); |
||
1548 | end |
||
1549 | elseif(event == "CHAT_MSG_SPELL_FAILED_LOCALPLAYER") |
||
1550 | then |
||
1551 | local _,_,spell,reason = string.find(arg1,HA_PARSE_SPELL_FAILED_REASON); |
||
1552 | if(reason == nil) then reason = "???"; end; |
||
1553 | HA_ChatDebug(HA_DEBUG_ACTIONS,"SPELLCAST_FAILED : ParsedSpell="..tostring(spell).." Casting="..tostring(HA_CastingSpell).." Instant="..tostring(HA_CastingInstantSpell).." Reason="..reason); |
||
1554 | if(reason ~= SPELL_FAILED_SPELL_IN_PROGRESS and HA_CastingSpell and HA_CastingSpell == spell) |
||
1555 | then |
||
1556 | local ispell = _HA_GetISpell(HA_CastingSpell); |
||
1557 | local ireason,sreason = _HA_GetReasonCode(reason); |
||
1558 | _HA_DoStop(true,"FAILED"); |
||
1559 | if(HA_StopCommandSent) |
||
1560 | then |
||
1561 | HA_GUI_Process_SpellFailed(HA_PlayerName,ispell,ireason,sreason); |
||
1562 | HA_COM_SpellFailed(ispell,ireason,sreason); |
||
1563 | end |
||
1564 | end |
||
1565 | _HA_CheckSpellRequestFailed(spell,reason); |
||
1566 | HA_CastingInstantSpell = nil; |
||
1567 | else |
||
1568 | HA_findEventMatch(event,_HA_RegExpr_CallBack); -- Check remaing events |
||
1569 | end |
||
1570 | end |
||
1571 | |||
1572 | --------------- Exported functions --------------- |
||
1573 | |||
1574 | --[[ |
||
1575 | Function HA_QuerySpell |
||
1576 | - SpellName : String - Spell to request. |
||
1577 | - PlayerName : String - Player to request spell to. |
||
1578 | Sends a request for spell to this player. |
||
1579 | Returns true is spell was found, ready, and queried. False otherwise. |
||
1580 | ]] |
||
1581 | function HA_QuerySpell(SpellName,PlayerName) |
||
1582 | local healer = HA_Healers[PlayerName]; |
||
1583 | if(healer) |
||
1584 | then |
||
1585 | local spell = healer.Cooldown[SpellName]; |
||
1586 | if(spell and spell.Remain == 0) |
||
1587 | then |
||
1588 | HA_COM_SpellRequest(spell.ispell,PlayerName); |
||
1589 | return true; |
||
1590 | else |
||
1591 | if(spell == nil) |
||
1592 | then |
||
1593 | HA_ChatPrint("HA_QuerySpell Failed : "..SpellName.." is not in "..PlayerName.."'s list of spells"); |
||
1594 | else |
||
1595 | HA_ChatPrint("HA_QuerySpell Failed : "..SpellName.." is not ready ("..spell.Remain.." sec remaining)"); |
||
1596 | end |
||
1597 | end |
||
1598 | else |
||
1599 | HA_ChatPrint("HA_QuerySpell Failed : "..PlayerName.." is not in my group/raid"); |
||
1600 | end |
||
1601 | return false; |
||
1602 | end |
||
1603 | |||
1604 | --[[ |
||
1605 | Function HA_ShowVersions |
||
1606 | Prints HA's version for all Healers in your group/raid (if available). |
||
1607 | ]] |
||
1608 | function HA_ShowVersions() |
||
1609 | for name,raider in HA_Raiders |
||
1610 | do |
||
1611 | if(raider.Version) |
||
1612 | then |
||
1613 | HA_ChatPrint(name.." : "..raider.Version); |
||
1614 | end |
||
1615 | end |
||
1616 | end |
||
1617 | |||
1618 | |||
1619 | --------------- Init functions --------------- |
||
1620 | |||
1621 | local function _HA_CheckSpellCooldown(spell,ispell,rank) |
||
1622 | local id = HA_GetSpellIDFromName(spell,rank); |
||
1623 | if(id == 0 and type(rank) == "number") |
||
1624 | then |
||
1625 | while(id == 0) |
||
1626 | do |
||
1627 | rank = rank - 1; |
||
1628 | if(rank == 0) -- Really don't have this spell |
||
1629 | then |
||
1630 | break; |
||
1631 | end |
||
1632 | id = HA_GetSpellIDFromName(spell,rank); |
||
1633 | end |
||
1634 | end |
||
1635 | if(id ~= 0) |
||
1636 | then |
||
1637 | HA_SpellCooldowns[spell] = { ispell=ispell; id=id; last=0; lastSend=0 }; |
||
1638 | HA_ChatDebug(HA_DEBUG_SPELLS,"_HA_CheckSpellCooldown : Found spell "..spell.." rank "..tostring(rank).." as ID "..id); |
||
1639 | return true; |
||
1640 | end |
||
1641 | return false; |
||
1642 | end |
||
1643 | |||
1644 | local function _HA_CheckTalents(talentids) |
||
1645 | local numTabs = GetNumTalentTabs(); |
||
1646 | for t=1, numTabs |
||
1647 | do |
||
1648 | local numTalents = GetNumTalents(t); |
||
1649 | for i=1, numTalents |
||
1650 | do |
||
1651 | local name,icon,x,y,rank,max = GetTalentInfo(t,i); |
||
1652 | for _,tid in talentids |
||
1653 | do |
||
1654 | if(HA_Talents[tid] and HA_Talents[tid].texture == icon) |
||
1655 | then |
||
1656 | HA_Talents[tid].rank = rank; |
||
1657 | HA_ChatDebug(HA_DEBUG_SPELLS,"_HA_CheckTalents : Found talent "..name.." at rank "..rank.."/"..max); |
||
1658 | end |
||
1659 | end |
||
1660 | end |
||
1661 | end |
||
1662 | end |
||
1663 | |||
1664 | function HA_InitializeCooldownSpells() |
||
1665 | -- Reset infos |
||
1666 | HA_SpellCooldowns = {}; |
||
1667 | for id,tab in HA_Talents |
||
1668 | do |
||
1669 | tab.rank = nil; |
||
1670 | end |
||
1671 | |||
1672 | -- Fill infos |
||
1673 | local _,clas = UnitClass("player"); |
||
1674 | if(clas == "DRUID") |
||
1675 | then |
||
1676 | _HA_CheckSpellCooldown(HA_INNERVATE,HA_SPELL_INNERVATE); |
||
1677 | _HA_CheckSpellCooldown(HA_REBIRTH,HA_SPELL_REBIRTH,5); |
||
1678 | _HA_CheckTalents({HA_TALENT_GIF_OF_NATURE,HA_TALENT_IMPROVED_REJUVINATION}); |
||
1679 | elseif(clas == "PALADIN") |
||
1680 | then |
||
1681 | _HA_CheckSpellCooldown(HA_DIVINE_INTERVENTION,HA_SPELL_DIVINE_INTERVENTION); |
||
1682 | _HA_CheckSpellCooldown(HA_BLESSING_OF_PROTECTION,HA_SPELL_BLESSING_OF_PROTECTION,3); |
||
1683 | _HA_CheckTalents({HA_TALENT_HEALING_LIGHT}); |
||
1684 | elseif(clas == "SHAMAN") |
||
1685 | then |
||
1686 | _HA_CheckSpellCooldown(HA_REINCARNATION,HA_SPELL_REINCARNATION,HA_PASSIVE); |
||
1687 | _HA_CheckSpellCooldown(HA_MANA_TIDE,HA_SPELL_MANA_TIDE,2); |
||
1688 | _HA_CheckTalents({HA_TALENT_PURIFICATION}); |
||
1689 | elseif(clas == "PRIEST") |
||
1690 | then |
||
1691 | _HA_CheckSpellCooldown(HA_LIGHTWELL,HA_SPELL_LIGHTWELL,3); |
||
1692 | _HA_CheckSpellCooldown(HA_POWER_INFUSION,HA_SPELL_POWER_INFUSION); |
||
1693 | _HA_CheckTalents({HA_TALENT_SPIRITUAL_HEALING,HA_TALENT_IMPROVED_RENEW,HA_TALENT_SPIRITUAL_GUIDANCE}); |
||
1694 | end |
||
1695 | end |
||
1696 | |||
1697 | function HA_OnLoad() |
||
1698 | -- Print init message |
||
1699 | HA_ChatPrint("Version "..HA_VERSION.." "..HA_CHAT_MISC_LOADED); |
||
1700 | |||
1701 | -- Register events |
||
1702 | this:RegisterEvent("VARIABLES_LOADED"); |
||
1703 | this:RegisterEvent("PLAYER_LOGIN"); |
||
1704 | this:RegisterEvent("PLAYER_ENTERING_WORLD"); |
||
1705 | this:RegisterEvent("PLAYER_LEAVING_WORLD"); |
||
1706 | this:RegisterEvent("ZONE_CHANGED_NEW_AREA"); |
||
1707 | |||
1708 | this:RegisterEvent("UNIT_COMBAT"); |
||
1709 | this:RegisterEvent("UNIT_HEALTH"); |
||
1710 | this:RegisterEvent("UNIT_MAXHEALTH"); |
||
1711 | this:RegisterEvent("UNIT_MANA"); |
||
1712 | this:RegisterEvent("UNIT_MAXMANA"); |
||
1713 | this:RegisterEvent("PLAYER_AURAS_CHANGED"); |
||
1714 | this:RegisterEvent("UPDATE_MOUSEOVER_UNIT"); |
||
1715 | this:RegisterEvent("PLAYER_TARGET_CHANGED"); |
||
1716 | |||
1717 | this:RegisterEvent("CHAT_MSG_SYSTEM"); |
||
1718 | this:RegisterEvent("CHAT_MSG_ADDON"); |
||
1719 | |||
1720 | this:RegisterEvent("SPELLCAST_START"); |
||
1721 | this:RegisterEvent("SPELLCAST_STOP"); |
||
1722 | this:RegisterEvent("SPELLCAST_DELAYED"); |
||
1723 | this:RegisterEvent("CHAT_MSG_SPELL_SELF_BUFF"); |
||
1724 | this:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF"); |
||
1725 | this:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF"); |
||
1726 | this:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF"); |
||
1727 | this:RegisterEvent("CHAT_MSG_SPELL_FAILED_LOCALPLAYER"); |
||
1728 | this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"); -- Self hots |
||
1729 | this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS"); -- Group hots |
||
1730 | this:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS"); -- Raid hots |
||
1731 | |||
1732 | HealersAssistTitle:SetText("HealersAssist v"..HA_VERSION); |
||
1733 | -- Initialize Slash commands |
||
1734 | SLASH_HA1 = "/ha"; |
||
1735 | SlashCmdList["HA"] = function(msg) |
||
1736 | HA_Commands(msg); |
||
1737 | end |
||
1738 | |||
1739 | tinsert(UISpecialFrames, "HAConfFrame"); |
||
1740 | |||
1741 | -- Initialiaze RegExprs |
||
1742 | HA_CreateRegexFromGlobals(); |
||
1743 | |||
1744 | -- Build ISpell structure |
||
1745 | HA_BuildLocalNames(); |
||
1746 | |||
1747 | -- Check for GroupAnalyse AddOn |
||
1748 | if(GA_RegisterForEvents ~= nil) |
||
1749 | then |
||
1750 | GA_RegisterForEvents(_HA_GroupAnalyseCallback); |
||
1751 | else |
||
1752 | this:RegisterEvent("PARTY_MEMBERS_CHANGED"); |
||
1753 | this:RegisterEvent("RAID_ROSTER_UPDATE"); |
||
1754 | end |
||
1755 | -- Check for BonusScanner AddOn |
||
1756 | if(BonusScanner and BONUSSCANNER_VERSION and BONUSSCANNER_VERSION >= "v1.0") |
||
1757 | then |
||
1758 | _HA_UseBonusScannerAddon = true; |
||
1759 | end |
||
1760 | end |
||
1761 | |||
1762 | |||
1763 | --/script HA_RequestSpell("Blessing of Protection") |
||
1764 | --/script SendAddonMessage("HealAss","<HA7>09"..'\30'.."16"..'\30'.."Kiki","RAID") |