vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Healers Assist by Kiki of European Cho'gall (Alliance)
3 Process channel events
4  
5 ]]
6  
7  
8 --------------- Constantes ---------------
9  
10 HA_STATE_CASTING = 1;
11 HA_STATE_HEALED = 2;
12 HA_STATE_STOP = 3;
13 HA_STATE_FAILED = 4;
14 HA_STATE_RESTING = 5;
15 HA_STATE_NOTHING = 6;
16 HA_STATE_DEAD = 7;
17  
18 HA_GUI_MAX_HEALERS = 16;
19 HA_GUI_MAX_EMERG = 6;
20  
21 local MAX_COOLDOWN_SPELLS = 2;
22 local MAX_OVERTIME_SPELLS=4;
23 local HA_SPELL_REQUEST_CODE_DENIED_DENIED = 1;
24 local HA_SPELL_REQUEST_CODE_DENIED_BLOCKED = 2;
25 local HA_SPELL_REQUEST_CODE_DENIED_BUSY = 3;
26 local HA_START_SLOT = 1;
27 local HA_END_SLOT = 120;
28  
29  
30 --------------- Shared variables ---------------
31  
32 HA_CustomOnClickFunction = nil;
33 HA_SpellRequest = nil;
34 HA_EmergList = {};
35  
36 -- Profiling
37 HA_PROFILE_StatusRoutine = 0;
38 HA_PROFILE_OvertimeRoutine = 0;
39 HA_PROFILE_RaidersInfosRoutine = 0;
40 HA_PROFILE_GUIRoutine = 0;
41 HA_PROFILE_AnalyseRaidersRoutine = 0;
42  
43  
44 --------------- Local variables ---------------
45  
46 local _HA_LastTimeGUI = 0;
47 local _HA_LastTimeHPMP = 0;
48 local _HA_CurrentTarget = nil;
49 local _HA_SortByName = false;
50 local _HA_CurrentWindowAlpha = 1.0;
51 local _HA_CurrentUIRefresh = 0.1;
52 local _HA_NewVersionNotice = false;
53  
54 --------------- Internal functions ---------------
55  
56 local function _HA_ResetRaiderState(raider)
57 raider.count = 0;
58 raider.estimates = {};
59 raider.estimate_ratio = 1;
60 raider.overtime = {};
61 end
62  
63 local function _HA_ResetHealerEstimate(healer)
64 local raider = HA_Raiders[healer.TargetName];
65 if(raider)
66 then
67 if(raider.estimates[healer.Name] and raider.count > 0)
68 then
69 raider.count = raider.count - 1;
70 end
71 raider.estimates[healer.Name] = nil;
72 end
73 end
74  
75 local function _HA_ResetHealerState(healer,reset_warn)
76 if(healer.State == HA_STATE_CASTING) -- If was casting, reset estimates
77 then
78 _HA_ResetHealerEstimate(healer);
79 if(reset_warn and HA_Config.Debug) -- Should issue a warning
80 then
81 --HA_ChatWarning("_HA_ResetHealerState : Was in CASTING state on "..tostring(healer.TargetName).." with spell "..tostring(healer.SpellName)..", but should not !");
82 end
83 end
84 if(healer.NextResetState)
85 then
86 healer.State = healer.NextResetState;
87 else
88 healer.State = HA_STATE_NOTHING;
89 end
90 healer.NextResetState = nil;
91 healer.SpellCode = nil;
92 healer.NonHeal = nil;
93 healer.SpellName = nil;
94 healer.SpellRank = nil;
95 healer.ShortSpellName = nil;
96 healer.TargetName = nil;
97 healer.Estimate = 0;
98 healer.CastTime = nil;
99 healer.StartTime = 0;
100 healer.EndTime = nil;
101 healer.OverHealed = nil;
102 healer.OverHealPercent = 0;
103 healer.EstimateRatio = 1;
104 healer.GroupHeal = nil;
105 end
106  
107 local function _HA_CheckForResetStates()
108 for name,tab in HA_Healers do
109 if((tab.State == HA_STATE_HEALED) or (tab.State == HA_STATE_FAILED) or (tab.State == HA_STATE_STOP))
110 then
111 if(HA_CurrentTime > tab.EndTime)
112 then
113 _HA_ResetHealerState(tab,false);
114 end
115 end
116 end
117 end
118  
119 -- (Duration and Estimated) ~= 0 -> Healing spell (Show Heal/Duration in 'Casting column')
120 local function _HA_Process_SpellHitInstant(healer,raider,SpellCode,SpellName,Duration,Estimated,SpellRank)
121 -- Call plugins
122 for n,pl in HA_ActivePlugins
123 do
124 if(pl.OnSpellHitInstant)
125 then
126 pl.OnSpellHitInstant(healer,raider,SpellCode,SpellName,Duration,Estimated,SpellRank);
127 end
128 end
129 if((Duration ~= 0 and HA_Config.ShowHoT and SpellCode ~= HA_SPELL_REGROWTH_HOT)
130 or (Duration == 0 and HA_Config.ShowInstants))
131 then
132 healer.State = HA_STATE_HEALED;
133 healer.SpellCode = SpellCode;
134 healer.NonHeal = HA_InstantSpells[SpellName].nonheal;
135 healer.SpellName = SpellName;
136 healer.SpellRank = SpellRank;
137 healer.TargetName = raider.name;
138 healer.ShortSpellName = HA_InstantSpells[SpellName].short;
139 healer.EndTime = HA_CurrentTime + HA_Config.KeepValue;
140 healer.Value = Estimated;
141 healer.Duration = Duration;
142 healer.Crit = false;
143 healer.HoT = true;
144 healer.GroupHeal = HA_InstantSpells[SpellName].group;
145 end
146 end
147  
148 local function _HA_EatHoT(healer,raider)
149 local rejuvName = HA_GetLocalName(HA_SPELL_REJUVENATION);
150 local regrowName = HA_GetLocalName(HA_SPELL_REGROWTH_HOT);
151  
152 local spell = raider.overtime[rejuvName];
153 if(spell) -- Rejuv has priority over regrowth
154 then
155 HA_ChatDebug(HA_DEBUG_SPELLS,"_HA_EatHoT : Eat HoT "..rejuvName.." from "..healer.Name.." to "..raider.name);
156 -- Call plugins
157 for n,pl in HA_ActivePlugins
158 do
159 if(pl.OnEatHot)
160 then
161 pl.OnEatHot(HA_SPELL_REJUVENATION,raider,spell.From,spell.Start,spell.Duration);
162 end
163 end
164 raider.overtime[rejuvName] = nil;
165 return;
166 end
167  
168 spell = raider.overtime[regrowName];
169 if(spell)
170 then
171 HA_ChatDebug(HA_DEBUG_SPELLS,"_HA_EatHoT : Eat HoT "..regrowName.." from "..healer.Name.." to "..raider.name);
172 -- Call plugins
173 for n,pl in HA_ActivePlugins
174 do
175 if(pl.OnEatHot)
176 then
177 pl.OnEatHot(HA_SPELL_REGROWTH_HOT,raider,spell.From,spell.Start,spell.Duration);
178 end
179 end
180 raider.overtime[regrowName] = nil;
181 return;
182 end
183 end
184  
185 local function _HA_GetRaiderHealthBeforeHeal(raider,Value,healer)
186 for i,tab in raider.heal_updates
187 do
188 if(tab.value == Value) -- Found it
189 then
190 local val = tab.oldhp;
191 HA_ChatDebug(HA_DEBUG_SPELLS,"_HA_GetRaiderHealthBeforeHeal : Heal value ("..tostring(Value)..") found from "..tostring(healer.Name).." to "..raider.name.." : HP before="..tostring(val).." : Array size="..tostring(getn(raider.heal_updates)));
192 table.remove(raider.heal_updates,i);
193 return val;
194 end
195 end
196 if(HA_Config.Debug and HA_Config.UseEstimatedHealth and getn(raider.heal_updates) == HA_MAX_HEAL_UPDATES) -- Estim health algo used, but value not found
197 then
198 HA_ChatWarning("_HA_GetRaiderHealthBeforeHeal : Heal value ("..tostring(Value)..") not found from "..tostring(healer.Name).." to "..raider.name.." : Array size="..tostring(getn(raider.heal_updates)));
199 end
200 return raider.hp;
201 end
202  
203 local function _HA_Process_SpellHit(healer,SpellCode,SpellName,raider,Value,Crit,InstantSpell)
204 -- Traitement
205 if(raider)
206 then
207 if(Crit)
208 then
209 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellHit CRIT from "..healer.Name.." to "..raider.name.." with "..SpellName.." for "..tostring(Value).." hp.");
210 else
211 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellHit from "..healer.Name.." to "..raider.name.." with "..SpellName.." for "..tostring(Value).." hp.");
212 end
213  
214 -- Check overhealed status
215 local new_hp = _HA_GetRaiderHealthBeforeHeal(raider,Value,healer) + Value;
216 local overhealed = 0;
217 if(new_hp > raider.hpmax)
218 then
219 overhealed = new_hp - raider.hpmax;
220 healer.OverHealed = overhealed / Value;
221 end
222  
223 if(SpellCode == HA_SPELL_SWIFTMEND)
224 then
225 _HA_EatHoT(healer,raider);
226 end
227  
228 -- Call plugins
229 for n,pl in HA_ActivePlugins
230 do
231 if(pl.OnSpellHit)
232 then
233 pl.OnSpellHit(healer,raider,SpellCode,SpellName,Value,Crit,overhealed,InstantSpell);
234 end
235 end
236 end
237  
238 if(healer.State == HA_STATE_STOP and healer.SpellCode == SpellCode) -- Added SpellCode check, to prevent an instant heal (like SwiftMend) to come before a casted spell
239 then
240 -- Reset data
241 healer.State = HA_STATE_HEALED;
242 healer.EndTime = HA_CurrentTime + HA_Config.KeepValue;
243 healer.Value = Value;
244 healer.Crit = Crit;
245 healer.HoT = false;
246 end
247 end
248  
249 local function _HA_GetCurrentInfos()
250 for name,infos in HA_Raiders
251 do
252 local healer = HA_Healers[name];
253 local death_state_changed = false;
254 infos.isconnected = UnitIsConnected(infos.id);
255 if(infos.isconnected and (infos.subgrp ~= 0 or (HA_CurrentTarget and name == HA_CurrentTarget))) -- If a special "Target" raider, must be current target
256 then
257 -- Update infos
258 infos.isdead = UnitIsDeadOrGhost(infos.id);
259 infos.ischarmed = UnitIsCharmed(infos.id);
260 -- Check Raider death state
261 if(infos.isdead and not infos.oldisdead) -- was alive, is now dead
262 then
263 death_state_changed = true;
264 _HA_ResetRaiderState(infos);
265 -- Call plugins
266 for n,pl in HA_ActivePlugins
267 do
268 if(pl.OnEvent)
269 then
270 pl.OnEvent(HA_EVENT_RAIDER_DIED,{name});
271 end
272 end
273 elseif(infos.oldisdead and not infos.isdead) -- Was dead, got rez
274 then
275 death_state_changed = true;
276 -- Call plugins
277 for n,pl in HA_ActivePlugins
278 do
279 if(pl.OnEvent)
280 then
281 pl.OnEvent(HA_EVENT_RAIDER_RESURRECTED,{name});
282 end
283 end
284 end
285 infos.oldisdead = infos.isdead;
286 -- Check Raider is a Healer
287 if(infos.ishealer)
288 then
289 if(death_state_changed)
290 then
291 if(infos.isdead) -- Was alive, is now dead
292 then
293 _HA_ResetHealerState(healer,false);
294 -- Call plugins
295 for n,pl in HA_ActivePlugins
296 do
297 if(pl.OnEvent)
298 then
299 pl.OnEvent(HA_EVENT_HEALER_DIED,{name});
300 end
301 end
302 HA_Healers[name].State = HA_STATE_DEAD;
303 else -- Was dead, got resurrection
304 _HA_ResetHealerState(healer,false);
305 -- Call plugins
306 for n,pl in HA_ActivePlugins
307 do
308 if(pl.OnEvent)
309 then
310 pl.OnEvent(HA_EVENT_HEALER_RESURRECTED,{name});
311 end
312 end
313 end
314 end
315 end
316 end
317 -- Check for a possible Estimates reset of Raider
318 if(not infos.isconnected) -- Offline, reset estimates
319 then
320 _HA_ResetRaiderState(infos);
321 if(infos.ishealer and healer)
322 then
323 _HA_ResetHealerState(healer,false);
324 end
325 end
326 end
327 _HA_LastTimeHPMP = HA_CurrentTime;
328 end
329  
330 local function _HA_WillOverHeal(healer)
331 local raider = HA_Raiders[healer.TargetName];
332 local my_end_time = healer.StartTime + healer.CastTime;
333  
334 if(raider and (raider.subgrp ~= 0 or healer.TargetName == HA_PlayerName))
335 then
336 local hp = raider.hp;
337 -- Check all other healers, casting on the same target than me, if their spell will hit before me, forcing me to overheal
338 for name,tab in HA_Healers
339 do
340 if(name ~= HA_PlayerName and tab.State == HA_STATE_CASTING and tab.TargetName == healer.TargetName and (tab.StartTime+tab.CastTime) < my_end_time)
341 then
342 hp = hp + tab.Estimate * tab.EstimateRatio * raider.estimate_ratio;
343 if(hp >= raider.hpmax)
344 then
345 healer.OverHealPercent = 100; -- My spell will overheal at 100%
346 return;
347 end
348 end
349 end
350 -- Nobody will force me to overheal at 100%, check how much my spell will overheal
351 local my_estim = healer.Estimate * healer.EstimateRatio * raider.estimate_ratio;
352 local my_spell = hp + my_estim;
353 if(my_spell > raider.hpmax)
354 then
355 healer.OverHealPercent = (my_spell-raider.hpmax) / my_estim * 100;
356 return;
357 end
358 end
359 healer.OverHealPercent = 0;
360 end
361  
362 local function HA_ScanDebufName(unitid,i)
363 HealersAssistTooltip:SetOwner(UIParent, "ANCHOR_NONE");
364 HealersAssistTooltip:ClearLines();
365 HealersAssistTooltip:SetUnitDebuff(unitid,i);
366 local debuffName = tostring(HealersAssistTooltipTextLeft1:GetText());
367 HealersAssistTooltip:Hide();
368 --HA_ChatPrint("HA_ScanDebufName : Unit="..unitid.." i="..i.." Name="..debuffName);
369 return debuffName;
370 end
371  
372 function HA_ShowDebuf()
373 for i=1,16
374 do
375 local texture,count = UnitDebuff("target",i);
376 if(texture == nil) then break; end;
377 HA_ChatPrint("DebufName : i="..i.." Name="..HA_ScanDebufName("target",i));
378 if(count == nil or count == 0) then count = 1; end;
379 local debuf = HA_HealDebuffs[texture];
380 if(debuf)
381 then
382 if(debuf.malus) -- No zone check
383 then
384 HA_ChatPrint("Found GLOBAL debuff ("..i..") with malus="..debuf.malus.." count="..count.." : "..texture);
385 ret = ret * (1 - count * debuf.malus);
386 elseif(debuf.zones)
387 then
388 local malus = debuf.zones[HA_CurrentZone];
389 if(malus)
390 then
391 if(type(malus) == "table")
392 then
393 else
394 HA_ChatPrint("Found Zone ("..HA_CurrentZone..")debuff ("..i..") with malus="..malus.." count="..count.." : "..texture);
395 ret = ret * (1 - count * malus);
396 end
397 else
398 HA_ChatPrint("Debuf texture found ("..texture.."), but malus for this zone : "..HA_CurrentZone);
399 end
400 end
401 end
402 end
403 end
404  
405 function HA_UnitHasHealDebuf(unitid)
406 local malus;
407 local names;
408 local ret = 1;
409 local texture;
410 local count;
411 local debuf;
412  
413 for i=1,16
414 do
415 texture,count = UnitDebuff(unitid,i);
416 if(texture == nil) then break; end;
417 if(count == nil or count == 0) then count = 1; end;
418 debuf = HA_HealDebuffs[texture];
419 if(debuf)
420 then
421 if(debuf.malus) -- No zone check
422 then
423 ret = ret * (1 - count * debuf.malus);
424 elseif(debuf.zones)
425 then
426 malus = debuf.zones[HA_CurrentZone];
427 if(malus)
428 then
429 if(type(malus) == "table")
430 then
431 names = malus.names;
432 if(names)
433 then
434 malus = names[HA_ScanDebufName(unitid,i)];
435 if(malus)
436 then
437 ret = ret * (1 - count * malus);
438 end
439 end
440 else
441 ret = ret * (1 - count * malus);
442 end
443 end
444 end
445 end
446 end
447 return ret;
448 end
449  
450 function HA_StatusScheduleRoutine()
451 debugprofilestart();
452 -- First, check my overheal status
453 local healer = HA_MyselfHealer;
454 if(healer and healer.State == HA_STATE_CASTING)
455 then
456 _HA_WillOverHeal(healer);
457 end
458  
459 -- Second, check estimates debufs (for mortal strike or other)
460 for name,tab in HA_Raiders
461 do
462 tab.estimate_ratio = 1; -- Reset value
463 if(tab.count ~= 0) -- Someone casting, time to check ratio
464 then
465 tab.estimate_ratio = HA_UnitHasHealDebuf(tab.id);
466 end
467 end
468  
469 -- Third, check estimates bufs
470 for name,tab in HA_Healers
471 do
472 tab.EstimateRatio = 1; -- Reset value
473 if(HA_RaiderInfused(name)) -- Got infused with power ?
474 then
475 tab.EstimateRatio = tab.EstimateRatio * 1.2;
476 end
477 end
478  
479 HA_PROFILE_StatusRoutine = debugprofilestop();
480 -- Finally reschedule
481 HASystem_Schedule(0.10,HA_StatusScheduleRoutine);
482 end
483  
484 function HA_OvertimeScheduleRoutine()
485 debugprofilestart();
486 local serv_time = GetTime();
487  
488 -- Check overtime timers
489 for name,tab in HA_Raiders
490 do
491 for spell,infos in tab.overtime
492 do
493 if(serv_time > (infos.Start + infos.Duration)) -- Expired
494 then
495 tab.overtime[spell] = nil;
496 end
497 end
498 end
499  
500 -- Check IsRegen state
501 local raider = HA_MyselfRaider;
502 local healer = HA_MyselfHealer;
503 if(healer and raider and healer.State == HA_STATE_RESTING)
504 then
505 if(raider.isdead or raider.mp == raider.mpmax) -- I'm dead, or my mana is full
506 then
507 HA_SetRegenMode(false);
508 end
509 end
510  
511 HA_PROFILE_OvertimeRoutine = debugprofilestop();
512 -- Re schedule
513 HASystem_Schedule(1,HA_OvertimeScheduleRoutine);
514 end
515  
516 local function _HA_ConvertToMinSec(val)
517 local minutes = floor(val / 60);
518 local secondes = val - (minutes*60);
519 return minutes.." min "..secondes.." sec";
520 end
521  
522 -- Range code from decursive
523 local function _HA_FindActionSlot(texture,SpellName)
524 local i = 0;
525 for i = HA_START_SLOT, HA_END_SLOT
526 do
527 if(HasAction(i))
528 then
529 icon = GetActionTexture(i);
530 if(icon == texture)
531 then
532 return i; -- Don't check the spell name
533 end
534 end
535 end
536 return 0;
537 end
538  
539 local function _HA_UnitInRange(id,ISpell)
540 if(not UnitIsVisible(id))
541 then
542 return false;
543 end
544 local SpellName = HA_GetLocalName(ISpell);
545 local cdspell = HA_Cooldown[ISpell];
546 if(SpellName and cdspell and not cdspell.norange)
547 then
548 if(cdspell.longrange)
549 then
550 local Range_Slot = _HA_FindActionSlot(cdspell.texture,SpellName);
551 if(Range_Slot ~= 0)
552 then
553 local ret_val = false;
554 TargetUnit(id);
555 if(UnitIsUnit("target",id))
556 then
557 ret_val = (IsActionInRange(Range_Slot) == 1);
558 end
559 return ret_val;
560 end
561 else
562 if(CheckInteractDistance(id,4))
563 then
564 return true;
565 else
566 return false;
567 end
568 end
569 end
570 return true;
571 end
572  
573 function HA_GUI_GetHealersLines()
574 local healerslines = HA_Config.HealersLines;
575 if(HA_Config.HealersCollapsed) then healerslines = 1; end;
576  
577 return healerslines;
578 end
579  
580 function HA_GUI_GetHealersHeight()
581 return 16+2 + HA_GUI_GetHealersLines() * 16;
582 end
583  
584 function HA_GUI_GetEmergencyHeight()
585 local emerg_height = 0;
586 if(HA_Config.EmergLines ~= 0)
587 then
588 emerg_height = 16+2 + HA_Config.EmergLines * 16;
589 end
590 return emerg_height;
591 end
592  
593 function HA_GUI_GetMainHeight()
594 return 25+10+10 + HA_GUI_GetHealersHeight() + HA_GUI_GetEmergencyHeight();
595 end
596  
597 local _ha_first_show = true;
598 function HA_SetWidgetSizeAndPosition()
599 local healerslines = HA_GUI_GetHealersLines();
600 local healers_height = HA_GUI_GetHealersHeight();
601 local emerg_height = HA_GUI_GetEmergencyHeight();
602 local main_height = HA_GUI_GetMainHeight();
603 local scale = HA_Config.Scale / 100;
604 local back_alpha = HA_Config.BackdropAlpha / 100;
605 _HA_CurrentWindowAlpha = HA_Config.Alpha / 100;
606 _HA_CurrentUIRefresh = HA_Config.GUIRefresh / 1000;
607  
608 if scale < 0.3 then
609 scale = 0.3;
610 elseif scale > 1.5 then
611 scale = 1.5;
612 end
613  
614 -- Hide non-used Healers
615 for i=healerslines+1,HA_GUI_MAX_HEALERS
616 do
617 getglobal("HAItem_"..i):Hide();
618 end
619  
620 -- Hide non-used emerg
621 for i=HA_Config.EmergLines+1,HA_GUI_MAX_EMERG
622 do
623 getglobal("HAItemEmergency_"..i):Hide();
624 end
625  
626 if(HA_Config.EmergLines ~= 0)
627 then
628 -- Set emergency position
629 HAEmergencyFrame:Show();
630 HAEmergencyFrame:SetHeight(emerg_height);
631 HAEmergencyFrame:SetPoint("TOPLEFT","HAItem_"..healerslines,"BOTTOMLEFT",0,-10);
632 else
633 HAEmergencyFrame:Hide();
634 end
635  
636 -- Set main window anchor and height
637 if(HA_Config.GrowUpwards)
638 then
639 local i = HealersAssistMainFrame:GetBottom();
640 local j = HealersAssistMainFrame:GetLeft();
641 if(i and j)
642 then
643 if(not _ha_first_show)
644 then
645 HealersAssistMainFrame:ClearAllPoints();
646 HealersAssistMainFrame:SetPoint("TOPLEFT","UIParent","BOTTOMLEFT",j,i+main_height);
647 end
648 end
649 end
650 HealersAssistMainFrame:SetHeight(main_height);
651 HealersAssistMainFrame:SetScale(scale);
652 HealersAssistMainFrame:SetAlpha(_HA_CurrentWindowAlpha);
653 HealersAssistMainFrame:SetBackdropColor(1,1,1,back_alpha);
654 HealersAssistMainFrame:SetBackdropBorderColor(1,1,1,back_alpha);
655 if(healerslines >= 4)
656 then
657 HAItemScrollFrame:SetHeight(healerslines * 16);
658 else
659 HAItemScrollFrame:SetHeight(4 * 16);
660 end
661  
662 -- Call plugins
663 for n,pl in HA_ActivePlugins
664 do
665 if(pl.OnEvent)
666 then
667 pl.OnEvent(HA_EVENT_WINDOW_SIZED,{healerslines,HA_Config.EmergLines,healers_height,emerg_height,main_height,scale,_HA_CurrentWindowAlpha,back_alpha});
668 end
669 end
670 _ha_first_show = false;
671 end
672  
673 --------------- Shared functions ---------------
674  
675 function HA_IsPlayerCasting()
676 local healer = HA_MyselfHealer;
677 if(healer and healer.State == HA_STATE_CASTING)
678 then
679 return true;
680 end;
681 return false;
682 end
683  
684 function HA_RaiderInfused(Name)
685 local raider = HA_Raiders[Name];
686 if(raider)
687 then
688 for ispell,tab in raider.overtime
689 do
690 if(ispell == HA_POWER_INFUSION)
691 then
692 return true;
693 end
694 end
695 end
696 return false;
697 end
698  
699  
700 --------------- XML functions ---------------
701  
702 function HA_Collapse_Healers_Click(state)
703 if(state)
704 then
705 HA_Config.HealersCollapsed = true;
706 else
707 HA_Config.HealersCollapsed = false;
708 end
709 HA_SetWidgetSizeAndPosition();
710 end
711  
712 function HA_SelectEmergency(pos)
713 local infos = HA_EmergList[pos];
714  
715 if(infos and infos.raider)
716 then
717 TargetUnit(infos.raider.id);
718 else
719 ClearTarget();
720 end
721 end
722  
723 function HAHeader_SortByName(byname)
724 _HA_SortByName = byname;
725 end
726  
727 function HA_OnShow()
728 HealersAssistMainFrameCollapseHealers:SetChecked(HA_Config.HealersCollapsed);
729 HA_SetWidgetSizeAndPosition();
730 _HA_CheckForResetStates();
731 HA_UpdateList();
732 HA_UpdateListEmergency();
733 -- Call plugins
734 for n,pl in HA_ActivePlugins
735 do
736 if(pl.OnEvent)
737 then
738 pl.OnEvent(HA_EVENT_WINDOW_SHOW);
739 end
740 end
741 end
742  
743 function HA_OnHide()
744 -- Call plugins
745 for n,pl in HA_ActivePlugins
746 do
747 if(pl.OnEvent)
748 then
749 pl.OnEvent(HA_EVENT_WINDOW_HIDE);
750 end
751 end
752 end
753  
754 function HA_CheckGetCurrentInfos()
755 -- Update Raider infos every 0.25 sec
756 if(HA_CurrentTime > (_HA_LastTimeHPMP+0.25))
757 then
758 debugprofilestart();
759 _HA_GetCurrentInfos();
760 HA_PROFILE_RaidersInfosRoutine = debugprofilestop();
761 end
762 end
763  
764 function HA_OnUpdate(arg1)
765 -- Update GUI every 0.10 sec
766 if(HA_CurrentTime > (_HA_LastTimeGUI+_HA_CurrentUIRefresh))
767 then
768 debugprofilestart();
769 _HA_CheckForResetStates();
770 HA_UpdateList();
771 HA_UpdateListEmergency();
772 _HA_LastTimeGUI = HA_CurrentTime;
773 HA_PROFILE_GUIRoutine = debugprofilestop();
774 end
775 end
776  
777 function HASetColumnWidth( width, frame )
778 if ( not frame ) then
779 frame = this;
780 end
781 frame:SetWidth(width);
782 getglobal(frame:GetName().."Middle"):SetWidth(width - 9);
783 end
784  
785 local function _HA_SortHealersByAlphabetic(a,b)
786 return a.Name < b.Name; -- Return alphabetic order
787 end
788  
789 local function _HA_SortByCastingTime(a,b)
790 return (a.StartTime+a.CastTime) < (b.StartTime+b.CastTime);
791 end
792  
793 local _HA_NextSortingFunction = {};
794 _HA_NextSortingFunction[HA_STATE_HEALED] = _HA_SortHealersByAlphabetic;
795 _HA_NextSortingFunction[HA_STATE_STOP] = _HA_SortHealersByAlphabetic;
796 _HA_NextSortingFunction[HA_STATE_CASTING] = _HA_SortByCastingTime;
797 _HA_NextSortingFunction[HA_STATE_FAILED] = _HA_SortHealersByAlphabetic;
798 _HA_NextSortingFunction[HA_STATE_RESTING] = _HA_SortHealersByAlphabetic;
799 _HA_NextSortingFunction[HA_STATE_NOTHING] = _HA_SortHealersByAlphabetic;
800 _HA_NextSortingFunction[HA_STATE_DEAD] = _HA_SortHealersByAlphabetic;
801  
802 local function _HA_SortHealersByState(a,b)
803 if(a.State == b.State)
804 then
805 return _HA_NextSortingFunction[a.State](a,b);
806 end
807 return a.State < b.State;
808 end
809  
810 local function _HA_SortHealersList(a,b)
811 if(a.Name == HA_PlayerName) -- Put myself on top of the list
812 then
813 return true;
814 end
815 if(b.Name == HA_PlayerName) -- Put myself on top of the list
816 then
817 return false;
818 end
819 if(_HA_SortByName)
820 then
821 return _HA_SortHealersByAlphabetic(a,b);
822 end
823 if(_HA_CurrentTarget) -- I have a target
824 then
825 if(tostring(a.TargetName) == _HA_CurrentTarget) -- 'a' has the same target
826 then
827 if(tostring(b.TargetName) == _HA_CurrentTarget) -- 'b' has too, check from state (can not be dead)
828 then
829 return _HA_SortHealersByState(a,b);
830 else -- 'b' doesn't, 'a' before 'b'
831 return true;
832 end
833 else -- 'a' doesn't have the same target, check if 'b' has
834 if(tostring(b.TargetName) == _HA_CurrentTarget) -- 'b' has, 'b' before 'a'
835 then
836 return false;
837 else -- Else, check from State
838 return _HA_SortHealersByState(a,b);
839 end
840 end
841 end
842 return _HA_SortHealersByState(a,b); -- I don't have a target, return from State
843 end
844  
845 function HA_DefaultFilter_Healer(healer)
846 if(healer.Raider and healer.Raider.ishealer and (healer.Name == HA_PlayerName or HA_Config.HealersClasses[healer.Raider.classid]))
847 then
848 return true;
849 end
850 return false;
851 end
852  
853 local function HA_GetList()
854 local UIList = {};
855 local get_done = false;
856 local sort_done = false;
857  
858 -- Call plugins
859 for n,pl in HA_ActivePlugins
860 do
861 if(pl.OnGetHealersList)
862 then
863 UIList = pl.OnGetHealersList();
864 get_done = true;
865 break;
866 end
867 end
868 if(not get_done)
869 then
870 for name,tab in HA_Healers
871 do
872 if(HA_DefaultFilter_Healer(tab))
873 then
874 tinsert(UIList, tab);
875 end
876 end
877 _HA_CurrentTarget = nil;
878 if(HA_MyselfHealer)
879 then
880 _HA_CurrentTarget = HA_MyselfHealer.TargetName;
881 end
882 end
883  
884 -- Call plugins
885 for n,pl in HA_ActivePlugins
886 do
887 if(pl.SortHealers)
888 then
889 table.sort(UIList,pl.SortHealers);
890 sort_done = true;
891 break;
892 end
893 end
894 if(not sort_done)
895 then
896 table.sort(UIList,_HA_SortHealersList);
897 end
898 return UIList;
899 end
900  
901 local function _HA_SortEmergencyList(a,b)
902 if(a.raider.count == 0) -- Nobody on 'a'
903 then
904 if(b.raider.count == 0) -- Nobody on 'b' -> Sort by %
905 then
906 return a.raider.percent < b.raider.percent;
907 -- Everything else, sort by remain
908 end
909 end
910 return ((a.raider.hpmax-a.raider.hp)-a.total) > ((b.raider.hpmax-b.raider.hp)-b.total); -- Compares a.remain - b.remain (remain = deficit-totalHeal)
911 end
912  
913 function HA_DefaultFilter_Raider(raider)
914 if(raider.percent < HA_Config.MinEmergencyPercent and -- percent < Config
915 raider.isconnected and not raider.isdead and not raider.ischarmed and UnitIsVisible(raider.id) and -- Connected, not dead, is not charmed, is visible
916 -- Check for filter
917 (raider == HA_MyselfRaider or -- Always show myself
918 ((raider.subgrp ~= 0 or (HA_CurrentTarget and raider.name == HA_CurrentTarget)) and -- If a special "Target" raider, must be current target
919 (HA_CurrentGroupMode ~= HA_MODE_RAID or raider.subgrp == 0 or HA_Config.EmergencyGroups[raider.subgrp]) and -- Not Group filtered
920 HA_Config.EmergencyClasses[raider.classid])) and -- Not class filtered
921 (not HA_Config.FilterRange or CheckInteractDistance(raider.id,4))) -- Not range filtered
922 then
923 return true;
924 end
925 return false;
926 end
927  
928 function HA_ComputeIncomingHeals(raider)
929 local total = 0;
930 local healer;
931  
932 for name,value in raider.estimates
933 do
934 heal_ratio = 1;
935 healer = HA_Healers[name];
936 if(healer)
937 then
938 heal_ratio = healer.EstimateRatio;
939 end
940 total = total + value*heal_ratio;
941 end
942 return floor(total * raider.estimate_ratio); -- Apply ratio
943 end
944  
945 local function HA_GetListEmergency()
946 local ret_vals = {};
947 local temp = {};
948 local heal_ratio;
949 local healer;
950 local get_done = false;
951 local sort_done = false;
952  
953 -- Call plugins
954 for n,pl in HA_ActivePlugins
955 do
956 if(pl.OnGetEmergencyList)
957 then
958 temp = pl.OnGetEmergencyList();
959 get_done = true;
960 break;
961 end
962 end
963 if(not get_done)
964 then
965 local total;
966 for name,tab in HA_Raiders
967 do
968 if(HA_DefaultFilter_Raider(tab))
969 then
970 total = HA_ComputeIncomingHeals(tab);
971 tinsert(temp, { raider = tab; total = total });
972 end
973 end
974 end
975  
976 -- Call plugins
977 for n,pl in HA_ActivePlugins
978 do
979 if(pl.SortEmergency)
980 then
981 table.sort(temp,pl.SortEmergency);
982 sort_done = true;
983 break;
984 end
985 end
986 if(not sort_done)
987 then
988 table.sort(temp,_HA_SortEmergencyList);
989 end
990  
991 if(HA_Config.EmergLines ~= 0)
992 then
993 local pos = 1;
994 for i=1,HA_Config.EmergLines
995 do
996 if(temp[i])
997 then
998 ret_vals[pos] = { raider = temp[i].raider; deficit = temp[i].raider.hpmax-temp[i].raider.hp; total = temp[i].total };
999 getglobal("HAItemEmergency_"..pos.."ClickFrame").unitid = temp[i].raider.id;
1000 pos = pos + 1;
1001 end
1002 end
1003  
1004 if(pos <= HA_Config.EmergLines)
1005 then
1006 for i=pos,HA_Config.EmergLines
1007 do
1008 ret_vals[i] = {};
1009 end
1010 end
1011 end
1012 HA_EmergList = ret_vals;
1013 return ret_vals;
1014 end
1015  
1016 local function _HA_SetTargetHealth(prefix,TargetName)
1017 if(TargetName ~= nil)
1018 then
1019 local percent = nil;
1020 if(HA_Raiders[TargetName]) -- Target is in the raid
1021 then
1022 local infos = HA_Raiders[TargetName];
1023 percent = infos.percent;
1024 elseif(UnitName("target") == TargetName) -- My target is the person I'm tyrying to heal
1025 then
1026 percent = floor(UnitHealth("target") / UnitHealthMax("target") * 100);
1027 end
1028 if(percent ~= nil)
1029 then
1030 if(percent > 100) then percent = 100; end;
1031 getglobal(prefix.."HPBar"):Show();
1032 getglobal(prefix.."HPBar"):SetValue(percent);
1033 return;
1034 end
1035 end
1036 getglobal(prefix.."HPBar"):Hide();
1037 end
1038  
1039 local function _HA_SetHealerMana(prefix,PlayerName,State)
1040 local infos = HA_Raiders[PlayerName];
1041 if(infos)
1042 then
1043 local percent = infos.mppercent;
1044 if(percent ~= nil)
1045 then
1046 -- Draw MP bar
1047 if(percent > 100) then percent = 100; end;
1048 local powertype = UnitPowerType(infos.id);
1049 if(powertype ~= 0) -- Check powertype for druids
1050 then
1051 percent = 0;
1052 if(powertype == 1) -- Bear
1053 then
1054 getglobal(prefix.."MPBarBG"):SetVertexColor(1, 0, 0, 0.2);
1055 else -- Cat
1056 getglobal(prefix.."MPBarBG"):SetVertexColor(1, 1, 0, 0.2);
1057 end
1058 else
1059 getglobal(prefix.."MPBarBG"):SetVertexColor(0, 0, 1, 0.2);
1060 end
1061 getglobal(prefix.."MPBar"):Show();
1062 getglobal(prefix.."MPBar"):SetValue(percent);
1063 -- Check for MP bar flashing
1064 if(State == HA_STATE_RESTING)
1065 then
1066 local cur_alpha = getglobal(prefix.."MPBar"):GetAlpha();
1067 cur_alpha = cur_alpha + _HA_CurrentWindowAlpha/10;
1068 if(cur_alpha >= _HA_CurrentWindowAlpha)
1069 then
1070 cur_alpha = _HA_CurrentWindowAlpha/3;
1071 end
1072 getglobal(prefix.."MPBar"):SetAlpha(cur_alpha);
1073 else
1074 getglobal(prefix.."MPBar"):SetAlpha(_HA_CurrentWindowAlpha);
1075 end
1076 return;
1077 end
1078 end
1079 getglobal(prefix.."MPBar"):Hide();
1080 end
1081  
1082 function HA_UpdateList()
1083 if(not HealersAssistMainFrame:IsVisible()) then
1084 return;
1085 end
1086 local list = HA_GetList();
1087 local size = table.getn(list);
1088 local target_raider;
1089 local estim_ratio;
1090 local isdead;
1091 local healer;
1092  
1093 local offset = FauxScrollFrame_GetOffset(HAItemScrollFrame);
1094 local healerslines = HA_Config.HealersLines;
1095 if(HA_Config.HealersCollapsed) then healerslines = 1; end;
1096 numButtons = healerslines;
1097 i = 1;
1098 while (i <= numButtons) do
1099 local j = i + offset
1100 local prefix = "HAItem_"..i;
1101 local button = getglobal(prefix);
1102  
1103 if (j <= size) then
1104 healer = list[j];
1105 getglobal("HAItem_"..i.."ClickFrame").unitid = healer.Raider.id;
1106 button.infos = healer;
1107 isdead = false;
1108 if(healer.State == HA_STATE_DEAD)
1109 then
1110 getglobal(prefix.."MPBarText"):SetTextColor(1, 0.1, 0.1);
1111 isdead = true;
1112 else
1113 local colors = RAID_CLASS_COLORS[healer.Raider.class];
1114 if(colors)
1115 then
1116 getglobal(prefix.."MPBarText"):SetTextColor(colors.r, colors.g, colors.b);
1117 end
1118 end
1119 getglobal(prefix.."MPBarText"):SetText(healer.Name);
1120 _HA_SetHealerMana(prefix,healer.Name,healer.State);
1121 if(healer.State == HA_STATE_CASTING or healer.State == HA_STATE_STOP)
1122 then
1123 getglobal(prefix.."State"):SetTextColor(0,0.9,0);
1124 getglobal(prefix.."State"):SetText(healer.ShortSpellName);
1125 if(healer.OverHealPercent ~= 0) -- Overhealing
1126 then
1127 local col = 1.0 - (healer.OverHealPercent / 100);
1128 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, col, col, 0.8);
1129 else
1130 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, 1.0, 1.0, 0.8);
1131 end
1132 getglobal(prefix.."HPBarText"):SetText(healer.TargetName);
1133 local percent = (HA_CurrentTime - healer.StartTime) / healer.CastTime * 100;
1134 if(percent > 100)
1135 then
1136 percent = 100;
1137 end;
1138 getglobal(prefix.."CTBar"):Show();
1139 getglobal(prefix.."CTBar"):SetValue(percent);
1140 getglobal(prefix.."CTBarText"):SetTextColor(0,0.8,0);
1141 if(healer.Estimate ~= 0)
1142 then
1143 target_raider = HA_Raiders[healer.TargetName];
1144 estim_ratio = 1;
1145 if(target_raider)
1146 then
1147 estim_ratio = target_raider.estimate_ratio;
1148 end
1149 getglobal(prefix.."CTBarText"):SetText("("..tostring(floor(healer.Estimate*healer.EstimateRatio*estim_ratio))..")");
1150 else
1151 getglobal(prefix.."CTBarText"):SetText("");
1152 end
1153 _HA_SetTargetHealth(prefix,healer.TargetName);
1154 elseif(healer.State == HA_STATE_FAILED)
1155 then
1156 getglobal(prefix.."State"):SetTextColor(0.8,0,0);
1157 getglobal(prefix.."State"):SetText(healer.Reason);
1158 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, 1.0, 1.0, 0.8);
1159 getglobal(prefix.."HPBarText"):SetText(healer.TargetName);
1160 getglobal(prefix.."CTBar"):Hide();
1161 _HA_SetTargetHealth(prefix,healer.TargetName);
1162 elseif(healer.State == HA_STATE_HEALED)
1163 then
1164 getglobal(prefix.."State"):SetTextColor(0.1,0.4,0.1);
1165 getglobal(prefix.."State"):SetText(healer.ShortSpellName);
1166 if(healer.OverHealed) -- Overhealing
1167 then
1168 local col = 1.0 - healer.OverHealed;
1169 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, col, col, 0.8);
1170 else
1171 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, 1.0, 1.0, 0.8);
1172 end
1173 getglobal(prefix.."HPBarText"):SetText(healer.TargetName);
1174 getglobal(prefix.."CTBar"):Show();
1175 getglobal(prefix.."CTBar"):SetValue(0);
1176 if(healer.HoT) -- A HoT spell (or instant)
1177 then
1178 if(healer.Duration == 0) -- Instant
1179 then
1180 getglobal(prefix.."CTBarText"):SetText("");
1181 else -- HoT
1182 getglobal(prefix.."CTBarText"):SetText(tostring(healer.Value).."/"..tostring(healer.Duration).."s");
1183 getglobal(prefix.."CTBarText"):SetTextColor(0,0.9,0);
1184 end
1185 else -- Casted spell
1186 if(healer.Value == 0) -- Non-heal spell (rez ?)
1187 then
1188 getglobal(prefix.."CTBarText"):SetText("");
1189 elseif(healer.Crit)
1190 then
1191 getglobal(prefix.."CTBarText"):SetText("C:+"..tostring(healer.Value));
1192 getglobal(prefix.."CTBarText"):SetTextColor(0,1,0);
1193 else
1194 getglobal(prefix.."CTBarText"):SetText("+"..tostring(healer.Value));
1195 getglobal(prefix.."CTBarText"):SetTextColor(0,0.9,0);
1196 end
1197 end
1198 _HA_SetTargetHealth(prefix,healer.TargetName);
1199 else -- All other cases (NOTHING/DEAD/RESTING)
1200 if(healer.State == HA_STATE_RESTING)
1201 then
1202 getglobal(prefix.."State"):SetTextColor(0.2,0.2,1.0);
1203 getglobal(prefix.."State"):SetText(HA_GUI_RESTING_STATE);
1204 if(HA_CurrentGroupMode == HA_MODE_RAID)
1205 then
1206 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, 1.0, 1.0, 1.0);
1207 getglobal(prefix.."HPBarText"):SetText("Grp "..healer.Raider.subgrp);
1208 getglobal(prefix.."HPBar"):SetValue(0);
1209 getglobal(prefix.."HPBar"):Show();
1210 else
1211 getglobal(prefix.."HPBar"):Hide();
1212 end
1213 else
1214 getglobal(prefix.."State"):SetText("");
1215 getglobal(prefix.."HPBar"):Hide();
1216 end
1217 getglobal(prefix.."CTBar"):Hide();
1218 end
1219 -- Cooldown receiver status
1220 local under_Cooldown = {};
1221 local cur_specific = 1;
1222 for spell,tab in healer.Raider.overtime
1223 do
1224 if(cur_specific > MAX_COOLDOWN_SPELLS)
1225 then
1226 break;
1227 end
1228 if(HA_Cooldown[tab.ispell]) -- I'm under a Cooldown spell
1229 then
1230 getglobal(prefix.."ClassSpecific"..cur_specific):Show();
1231 getglobal(prefix.."ClassSpecific"..cur_specific.."Texture"):SetVertexColor(HA_Cooldown[tab.ispell].flash_r,HA_Cooldown[tab.ispell].flash_g,HA_Cooldown[tab.ispell].flash_b);
1232 getglobal(prefix.."ClassSpecific"..cur_specific.."Texture"):SetTexture(HA_Cooldown[tab.ispell].texture);
1233 local cur_alpha = getglobal(prefix.."ClassSpecific"..cur_specific):GetAlpha();
1234 cur_alpha = cur_alpha + _HA_CurrentWindowAlpha/10;
1235 if(cur_alpha >= _HA_CurrentWindowAlpha)
1236 then
1237 cur_alpha = _HA_CurrentWindowAlpha/3;
1238 end
1239 getglobal(prefix.."ClassSpecific"..cur_specific):SetAlpha(cur_alpha);
1240 getglobal(prefix.."ClassSpecific"..cur_specific).cooldown = nil;
1241 getglobal(prefix.."ClassSpecific"..cur_specific).spell = spell;
1242 getglobal(prefix.."ClassSpecific"..cur_specific).ispell = tab.ispell;
1243 getglobal(prefix.."ClassSpecific"..cur_specific).from = tab.From;
1244 getglobal(prefix.."ClassSpecific"..cur_specific).me = nil;
1245 cur_specific = cur_specific + 1;
1246 under_Cooldown[spell] = true;
1247 end
1248 end
1249 -- Cooldown owner status
1250 for spell,cdinfos in healer.Cooldown
1251 do
1252 if(HA_Cooldown[cdinfos.ispell])
1253 then
1254 if(cur_specific > MAX_COOLDOWN_SPELLS)
1255 then
1256 break;
1257 end
1258 if(under_Cooldown[spell] == nil) -- I'm not under a Cooldown spell myself, show my Cooldown status
1259 then
1260 if(cdinfos.Remain > 0 or isdead) -- Still in cooldown, or dead
1261 then
1262 getglobal(prefix.."ClassSpecific"..cur_specific):SetAlpha(_HA_CurrentWindowAlpha/5);
1263 else
1264 getglobal(prefix.."ClassSpecific"..cur_specific):SetAlpha(_HA_CurrentWindowAlpha);
1265 end
1266 getglobal(prefix.."ClassSpecific"..cur_specific.."Texture"):SetVertexColor(1,1,1);
1267 getglobal(prefix.."ClassSpecific"..cur_specific.."Texture"):SetTexture(HA_Cooldown[cdinfos.ispell].texture);
1268 getglobal(prefix.."ClassSpecific"..cur_specific):Show();
1269 getglobal(prefix.."ClassSpecific"..cur_specific).cooldown = cdinfos.Remain;
1270 getglobal(prefix.."ClassSpecific"..cur_specific).spell = spell;
1271 getglobal(prefix.."ClassSpecific"..cur_specific).ispell = cdinfos.ispell;
1272 getglobal(prefix.."ClassSpecific"..cur_specific).me = healer.Name;
1273 getglobal(prefix.."ClassSpecific"..cur_specific).isdead = isdead;
1274 cur_specific = cur_specific + 1;
1275 end
1276 end
1277 end
1278 for k=cur_specific,MAX_COOLDOWN_SPELLS
1279 do
1280 getglobal(prefix.."ClassSpecific"..k):Hide();
1281 end
1282 button:Show();
1283 else
1284 button.infos = nil;
1285 button:Hide();
1286 end
1287  
1288 i = i + 1;
1289 end
1290  
1291 FauxScrollFrame_Update(HAItemScrollFrame, size, healerslines, 1);
1292  
1293 -- Call plugins
1294 for n,pl in HA_ActivePlugins
1295 do
1296 if(pl.OnEvent)
1297 then
1298 pl.OnEvent(HA_EVENT_GUI_UPDATED_HEALERS);
1299 end
1300 end
1301 end
1302  
1303 function HA_UpdateListEmergency()
1304 local list = HA_GetListEmergency();
1305 if(not HealersAssistMainFrame:IsVisible()) then
1306 return;
1307 end
1308 local size = table.getn(list);
1309 local healer = HA_MyselfHealer;
1310 local raider;
1311  
1312 for i,infos in list
1313 do
1314 local prefix = "HAItemEmergency_"..i;
1315 local button = getglobal(prefix);
1316 raider = infos.raider;
1317 if(raider)
1318 then
1319 local colors = RAID_CLASS_COLORS[raider.class];
1320 if(colors)
1321 then
1322 getglobal(prefix.."Name"):SetTextColor(colors.r, colors.g, colors.b);
1323 end
1324 getglobal(prefix.."Name"):SetText(raider.name);
1325 if(raider.subgrp == 0) -- Current Target
1326 then
1327 getglobal(prefix.."HPBarText"):SetText(raider.percent.."%");
1328 else
1329 getglobal(prefix.."HPBarText"):SetText("-"..tostring(infos.deficit));
1330 end
1331 if(healer and healer.State == HA_STATE_CASTING and healer.TargetName == raider.name)
1332 then
1333 getglobal(prefix.."HPBarText"):SetVertexColor(0.4, 0.4, 1.0, 0.9);
1334 else
1335 getglobal(prefix.."HPBarText"):SetVertexColor(1.0, 1.0, 1.0, 0.9);
1336 end
1337 getglobal(prefix.."HPBar"):SetValue(tostring(raider.percent));
1338 getglobal(prefix.."Count"):SetText(tostring(raider.count));
1339 if(infos.total == 0)
1340 then
1341 getglobal(prefix.."Total"):SetText("-");
1342 else
1343 getglobal(prefix.."Total"):SetText(tostring(infos.total));
1344 end
1345 -- Update overtime
1346 local pos = 1;
1347 for spell,tab in raider.overtime
1348 do
1349 if(HA_Cooldown[tab.ispell] == nil) -- Don't show cooldown spells
1350 then
1351 if(HA_InstantSpells[spell] and HA_SpellOvertime[tab.ispell]) -- A changer, on accede direct sans le iname coté serveur
1352 then
1353 getglobal(prefix.."Overtime"..pos.."Texture"):SetTexture(HA_SpellOvertime[tab.ispell].texture);
1354 getglobal(prefix.."Overtime"..pos):Show();
1355 -- Break if too many spells
1356 pos = pos + 1;
1357 if(pos > MAX_OVERTIME_SPELLS)
1358 then
1359 break;
1360 end
1361 end
1362 end
1363 end
1364 for k=pos,MAX_OVERTIME_SPELLS
1365 do
1366 getglobal(prefix.."Overtime"..k):Hide();
1367 end
1368 button.infos = raider;
1369 button.unitid = raider.id;
1370 button:Show();
1371 else
1372 button.infos = nil;
1373 button.unitid = nil;
1374 button:Hide();
1375 end
1376 end
1377  
1378 -- Call plugins
1379 for n,pl in HA_ActivePlugins
1380 do
1381 if(pl.OnEvent)
1382 then
1383 pl.OnEvent(HA_EVENT_GUI_UPDATED_EMERGENCY);
1384 end
1385 end
1386 end
1387  
1388 function HA_RequestSpell(SpellName)
1389 local request_name = nil;
1390 local spell_code = HA_GetSpellCode(SpellName);
1391 local spell_class = HA_GetSpellClass(spell_code);
1392  
1393 if(HA_Cooldown[spell_code] == nil or not HA_Cooldown[spell_code].can_request)
1394 then
1395 HA_ChatPrint(string.format(HA_GUI_REQUEST_SEARCH_INVALID_SPELL,SpellName));
1396 return;
1397 end
1398  
1399 for name,healer in HA_Healers do
1400 if(not healer.isdead and healer.Raider and spell_class == healer.Raider.class)
1401 then
1402 for spell,cdinfos in healer.Cooldown
1403 do
1404 if(cdinfos.ispell == spell_code and cdinfos.Remain == 0) -- Found somebody
1405 then
1406 request_name = name; -- Store the name to fallback in case nobody in range
1407 if(CheckInteractDistance(healer.id,4) and UnitPowerType(healer.id) == 0) -- In range and not a druid in feral form, stop checking
1408 then
1409 break;
1410 end
1411 end
1412 end
1413 end
1414 end
1415 if(request_name) -- Found someone
1416 then
1417 HA_COM_SpellRequest(spell_code,request_name);
1418 HA_ChatPrint(string.format(HA_GUI_REQUEST_SEARCH_OK,SpellName,request_name));
1419 else
1420 HA_ChatPrint(string.format(HA_GUI_REQUEST_SEARCH_FAILED,SpellName));
1421 end
1422 end
1423  
1424 function HA_GUI_ClassSpecificTooltip(spell,from,cooldown)
1425 GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
1426 GameTooltip:ClearLines();
1427 if(cooldown == nil) -- Receiver
1428 then
1429 GameTooltip:AddLine(string.format(HA_GUI_TOOLTIP_GOT_SPELL,spell,from));
1430 else
1431 if(cooldown == 0)
1432 then
1433 GameTooltip:AddLine(string.format(HA_GUI_TOOLTIP_READY,spell));
1434 else
1435 GameTooltip:AddLine(string.format(HA_GUI_TOOLTIP_COOLDOWN,spell));
1436 GameTooltip:AddLine(_HA_ConvertToMinSec(floor(cooldown)));
1437 end
1438 end
1439 GameTooltip:Show();
1440 end
1441  
1442 function HA_GUI_ClassSpecificClick(SpellCode,PlayerName,cooldown)
1443 if(cooldown == nil or cooldown ~= 0 or PlayerName == nil or HA_Cooldown[SpellCode] == nil or not HA_Cooldown[SpellCode].can_request) -- Under this spell, or spell not ready, or spell cannot be requested
1444 then
1445 return;
1446 end
1447 local SpellName = HA_GetLocalName(SpellCode);
1448 local spellinfos = HA_Spells[SpellName];
1449 if(spellinfos == nil) then spellinfos = HA_InstantSpells[SpellName]; end
1450 if(spellinfos)
1451 then
1452 if(UnitIsDeadOrGhost("player") and not spellinfos.rez) -- I'm dead
1453 then
1454 HA_ChatPrint(HA_GUI_REQUEST_YOU_ARE_DEAD);
1455 return;
1456 elseif(not UnitIsDeadOrGhost("player") and spellinfos.rez) -- Not dead
1457 then
1458 HA_ChatPrint(HA_GUI_REQUEST_NOT_DEAD_YET);
1459 return;
1460 end
1461 end
1462 if(PlayerName == HA_PlayerName)
1463 then
1464 HA_GUI_Process_SpellRequest(PlayerName,SpellCode);
1465 else
1466 HA_COM_SpellRequest(SpellCode,PlayerName);
1467 end
1468 end
1469  
1470 StaticPopupDialogs["HA_REQUEST_FOR_SPELL"] = {
1471 text = TEXT(""),
1472 button1 = TEXT(OKAY),
1473 button2 = TEXT(CANCEL),
1474 OnShow = function()
1475 local TargetName = HA_SpellRequest.target;
1476 local SpellName = HA_SpellRequest.spell;
1477 HA_ChatDebug(HA_DEBUG_ACTIONS,"StaticPopup : SpellRequest show for "..tostring(HA_SpellRequest.spell));
1478 if(SpellName)
1479 then
1480 if(HA_SpellRequest.failure)
1481 then
1482 getglobal(this:GetName().."Text"):SetText(format(HA_GUI_POPUP_REQUEST_FOR_SPELL_WITH_FAILURE,TargetName,SpellName,HA_SpellRequest.failure));
1483 else
1484 getglobal(this:GetName().."Text"):SetText(format(HA_GUI_POPUP_REQUEST_FOR_SPELL,TargetName,SpellName));
1485 end
1486 else
1487 getglobal(this:GetName().."Text"):SetText("HealersAssist Spell Request Error !\nPlease inform kiki.");
1488 end
1489 if(_HA_UnitInRange(HA_SpellRequest.id,HA_SpellRequest.ispell))
1490 then
1491 getglobal(this:GetName().."Button1"):Enable();
1492 HA_SpellRequest.WasEnabled = true;
1493 else
1494 getglobal(this:GetName().."Button1"):Disable();
1495 HA_SpellRequest.WasEnabled = false;
1496 end
1497 HA_SpellRequest.LastTime = HA_CurrentTime;
1498 this.FirstUpdate = true;
1499 end,
1500 OnUpdate = function()
1501 if(this.FirstUpdate)
1502 then
1503 local bb = getglobal(this:GetName().."Button1");
1504 this:SetHeight(this:GetTop() - bb:GetBottom() + 20);
1505 this.FirstUpdate = nil;
1506 end
1507 if(HA_SpellRequest and HA_SpellRequest.LastTime and (HA_CurrentTime > (HA_SpellRequest.LastTime+0.2)))
1508 then
1509 HA_SpellRequest.LastTime = HA_CurrentTime;
1510 if(this and getglobal(this:GetName().."Button1"))
1511 then
1512 local new_state = _HA_UnitInRange(HA_SpellRequest.id,HA_SpellRequest.ispell);
1513 if(new_state ~= HA_SpellRequest.WasEnabled)
1514 then
1515 if(new_state)
1516 then
1517 getglobal(this:GetName().."Button1"):Enable();
1518 else
1519 getglobal(this:GetName().."Button1"):Disable();
1520 end
1521 HA_SpellRequest.WasEnabled = new_state;
1522 end
1523 end
1524 end
1525 end,
1526 OnAccept = function()
1527 if(HA_SpellRequest)
1528 then
1529 local TargetName = HA_SpellRequest.target;
1530 local unitid = HA_SpellRequest.id;
1531 local SpellName = HA_GetLocalName(HA_SpellRequest.ispell);
1532 if(SpellName)
1533 then
1534 HA_ChatDebug(HA_DEBUG_ACTIONS,"StaticPopup : SpellRequest accepted for "..tostring(HA_SpellRequest.spell));
1535 if(not HA_Cooldown[HA_SpellRequest.ispell].norange)
1536 then
1537 TargetUnit(unitid);
1538 end
1539 SpellStopCasting();
1540 HA_SpellTargetName = TargetName;
1541 CastSpellByName(SpellName);
1542 end
1543 end
1544 end,
1545 OnCancel = function()
1546 if(HA_SpellRequest)
1547 then
1548 local TargetName = HA_SpellRequest.target;
1549 local SpellCode = HA_SpellRequest.ispell;
1550 HA_ChatDebug(HA_DEBUG_ACTIONS,"StaticPopup : SpellRequest denied for "..tostring(HA_SpellRequest.spell).." : "..tostring(HA_SpellRequest.failure));
1551 HA_COM_SpellRequestDenied(SpellCode,TargetName,HA_SPELL_REQUEST_CODE_DENIED_DENIED);
1552 end
1553 HA_SpellRequest = nil;
1554 end,
1555 OnHide = function()
1556 if(HA_SpellRequest ~= nil)
1557 then
1558 StaticPopup_Show("HA_REQUEST_FOR_SPELL");
1559 end
1560 end,
1561 whileDead = 0,
1562 hideOnEscape = 1,
1563 timeout = 0
1564 };
1565  
1566 function HA_SetRegenMode(state)
1567 local healer = HA_MyselfHealer;
1568 if(healer)
1569 then
1570 if(state)
1571 then
1572 healer.NextResetState = HA_STATE_RESTING;
1573 HA_COM_RegenMode(true);
1574 HealersAssistMainFrameSetResting:SetChecked(1);
1575 if(healer.State == HA_STATE_NOTHING) -- Was doing nothing, change the state now
1576 then
1577 _HA_ResetHealerState(healer,false);
1578 end
1579 else
1580 healer.NextResetState = nil;
1581 if(healer.State == HA_STATE_RESTING) -- Was already in regen state, reset the state
1582 then
1583 _HA_ResetHealerState(healer,false);
1584 end
1585 HA_COM_RegenMode(false);
1586 HealersAssistMainFrameSetResting:SetChecked(0);
1587 end
1588 end
1589 end
1590  
1591  
1592 --------------- Process functions ---------------
1593  
1594 --[[
1595 HA_GUI_Process_SpellStart function :
1596 - From : String -- Source player
1597 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1598 - TargetName : String -- Target of the heal
1599 - CastTime : Int -- Casttime of the spell
1600 - Estimated : Int -- Estimated spell value (can be 0)
1601 - WillCrit : Bool -- If you are sure the spell will crit (Estimated is crit value)
1602 - SpellRank : Int -- Rank of the spell (can be 0)
1603 ]]
1604 function HA_GUI_Process_SpellStart(From,SpellCode,TargetName,CastTime,Estimated,WillCrit,SpellRank)
1605 local SpellName = HA_GetLocalName(SpellCode);
1606 local healer = HA_Healers[From];
1607 if(healer and SpellName)
1608 then
1609 local spell = HA_Spells[SpellName];
1610 if(spell)
1611 then
1612 if(SpellRank == nil) then SpellRank = 0; end
1613 _HA_ResetHealerState(healer,true);
1614 healer.SpellCode = SpellCode;
1615 healer.NonHeal = spell.nonheal;
1616 healer.SpellName = SpellName;
1617 healer.SpellRank = SpellRank;
1618 healer.ShortSpellName = spell.short;
1619 healer.TargetName = TargetName;
1620 healer.Estimate = Estimated;
1621 healer.WillCrit = WillCrit;
1622 healer.GroupHeal = spell.group;
1623 if(CastTime == nil)
1624 then
1625 HA_ChatWarning("SPELLCAST_START : CastTime is nil : "..tostring(arg2));
1626 healer.CastTime = 1;
1627 else
1628 healer.CastTime = CastTime / 1000;
1629 end
1630 healer.StartTime = HA_CurrentTime;
1631 local raider = HA_Raiders[TargetName];
1632 if(raider and Estimated ~= 0 and raider.estimates[From] == nil and not spell.group)
1633 then
1634 raider.count = raider.count + 1;
1635 raider.estimates[From] = healer.Estimate;
1636 end
1637 healer.State = HA_STATE_CASTING;
1638 if(raider)
1639 then
1640 -- Call plugins
1641 for n,pl in HA_ActivePlugins
1642 do
1643 if(pl.OnSpellStart)
1644 then
1645 pl.OnSpellStart(healer,raider,SpellCode,SpellName,CastTime,Estimated,WillCrit,SpellRank);
1646 end
1647 end
1648 end
1649 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellStart from "..From.." to "..tostring(TargetName).." with "..SpellName.." ("..tostring(SpellRank)..") for "..tostring(CastTime));
1650 end
1651 end
1652 end
1653  
1654 --[[
1655 HA_GUI_Process_SpellStop function :
1656 - From : String -- Source player
1657 ]]
1658 function HA_GUI_Process_SpellStop(From)
1659 local healer = HA_Healers[From];
1660 if(healer)
1661 then
1662 -- Remove estimate value
1663 _HA_ResetHealerEstimate(healer);
1664 -- Set STOP state
1665 healer.EndTime = HA_CurrentTime + HA_Config.KeepValue;
1666 healer.State = HA_STATE_STOP;
1667 if(healer.CastTime == nil)
1668 then
1669 healer.CastTime = 1;
1670 end
1671 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellStop from "..From);
1672 end
1673 end
1674  
1675 --[[
1676 HA_GUI_Process_SpellHit function :
1677 - From : String -- Source player
1678 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1679 - TargetName : String -- Target of the heal
1680 - Value : Int -- Healed value
1681 - Crit : Bool -- Heal has crit
1682 ]]
1683 function HA_GUI_Process_SpellHit(From,SpellCode,TargetName,Value,Crit)
1684 local SpellName = HA_GetLocalName(SpellCode);
1685 local healer = HA_Healers[From];
1686 local spell = HA_Spells[SpellName];
1687 local raider = HA_Raiders[TargetName];
1688  
1689 if(healer)
1690 then
1691 if(spell) -- Casted spell
1692 then
1693 _HA_Process_SpellHit(healer,SpellCode,SpellName,raider,Value,Crit,false);
1694 elseif(HA_InstantSpells[SpellName])
1695 then
1696 _HA_Process_SpellHit(healer,SpellCode,SpellName,raider,Value,Crit,true);
1697 end
1698 end
1699 end
1700  
1701 --[[
1702 HA_GUI_Process_SpellFailed function :
1703 - From : String -- Source player
1704 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1705 - IReason : Int -- Reason code of failure
1706 - Reason : String -- Reason text of failure (nil if IReason ~= 0)
1707 ]]
1708 function HA_GUI_Process_SpellFailed(From,SpellCode,IReason,Reason)
1709 local SpellName = HA_GetLocalName(SpellCode);
1710 local healer = HA_Healers[From];
1711 local spell = HA_Spells[SpellName];
1712 if(healer and spell)
1713 then
1714 if(IReason ~= 0)
1715 then
1716 if(IReason == HA_SPELL_FAILED_OUT_OF_SIGHT)
1717 then
1718 Reason = HA_FAILED_TEXT_OUT_OF_SIGHT;
1719 elseif(IReason == HA_SPELL_FAILED_OUT_OF_RANGE)
1720 then
1721 Reason = HA_FAILED_TEXT_TOO_FAR;
1722 elseif(IReason == HA_SPELL_FAILED_TARGET_DIED)
1723 then
1724 Reason = HA_FAILED_TEXT_DEAD;
1725 else
1726 Reason = HA_GetLocalReason(IReason);
1727 end
1728 end
1729 local raider = HA_Raiders[healer.TargetName];
1730 if(raider)
1731 then
1732 -- Call plugins
1733 for n,pl in HA_ActivePlugins
1734 do
1735 if(pl.OnSpellFailed)
1736 then
1737 pl.OnSpellFailed(healer,raider,SpellCode,IReason,Reason);
1738 end
1739 end
1740 end
1741 -- Set failed mode, if not currently casting
1742 if(healer.State == HA_STATE_STOP)
1743 then
1744 healer.State = HA_STATE_FAILED;
1745 healer.EndTime = HA_CurrentTime + HA_Config.KeepValue;
1746 healer.Reason = Reason;
1747 end
1748 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellFailed from "..healer.Name.." with "..tostring(SpellName).." : "..Reason);
1749 end
1750 end
1751  
1752 --[[
1753 HA_GUI_Process_SpellDelayed function :
1754 - From : String -- Source player
1755 - Value : Int -- Delayed value in msec
1756 ]]
1757 function HA_GUI_Process_SpellDelayed(From,Value)
1758 local healer = HA_Healers[From];
1759 if(healer)
1760 then
1761 if(healer.State == HA_STATE_CASTING)
1762 then
1763 healer.StartTime = healer.StartTime + Value/1000;
1764 -- Call plugins
1765 for n,pl in HA_ActivePlugins
1766 do
1767 if(pl.OnSpellDelayed)
1768 then
1769 pl.OnSpellDelayed(healer,Value);
1770 end
1771 end
1772 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellDelayed from "..From.." for "..Value);
1773 end
1774 end
1775 end
1776  
1777 --[[
1778 HA_GUI_Process_SpellCooldown function :
1779 - From : String -- Source player
1780 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1781 - TargetName : String -- Target
1782 ]]
1783 function HA_GUI_Process_SpellCooldown(From,SpellCode,TargetName)
1784 local SpellName = HA_GetLocalName(SpellCode);
1785 local healer = HA_Healers[From];
1786  
1787 if(healer and SpellName)
1788 then
1789 local raider = HA_Raiders[TargetName];
1790 if(raider)
1791 then
1792 if(SpellCode == HA_SPELL_INNERVATE) -- Druid's Innervate
1793 then
1794 raider.overtime[HA_INNERVATE] = { From = healer.Name; Start = GetTime(); Duration = 20; ispell = SpellCode };
1795 if(raider.name == HA_PlayerName and healer.Name ~= HA_PlayerName)
1796 then
1797 HA_ChatPrint(HA_CHAT_MSG_INNERVATED);
1798 PlaySoundFile("Sound\\interface\\levelup2.wav");
1799 end
1800 elseif(SpellCode == HA_SPELL_BLESSING_OF_PROTECTION) -- Paladin's BoP
1801 then
1802 raider.overtime[HA_BLESSING_OF_PROTECTION] = { From = healer.Name; Start = GetTime(); Duration = 10; ispell = SpellCode };
1803 elseif(SpellCode == HA_SPELL_DIVINE_INTERVENTION) -- Paladin's Divine Intervention
1804 then
1805 raider.overtime[HA_DIVINE_INTERVENTION] = { From = healer.Name; Start = GetTime(); Duration = 180; ispell = SpellCode };
1806 elseif(SpellCode == HA_SPELL_POWER_INFUSION) -- Priest's Power Infusion
1807 then
1808 if(HA_RaiderInfused(TargetName))
1809 then
1810 raider.overtime[HA_POWER_INFUSION].From = healer.Name;
1811 else
1812 raider.overtime[HA_POWER_INFUSION] = { From = healer.Name; Start = GetTime(); Duration = 15; ispell = SpellCode };
1813 if(raider.name == HA_PlayerName and healer.Name ~= HA_PlayerName)
1814 then
1815 HA_ChatPrint(HA_CHAT_MSG_INFUSED);
1816 PlaySoundFile("Sound\\Doodad\\HornGoober.wav");
1817 end
1818 end
1819 end
1820 -- Call plugins
1821 for n,pl in HA_ActivePlugins
1822 do
1823 if(pl.OnSpellCooldown)
1824 then
1825 pl.OnSpellCooldown(healer,raider,SpellCode,SpellName);
1826 end
1827 end
1828 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellCooldown "..SpellName.." from "..healer.Name.." to "..tostring(raider.name));
1829 end
1830 end
1831 end
1832  
1833 --[[
1834 HA_GUI_Process_CooldownUpdate function :
1835 - From : String -- Source player
1836 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1837 - Cooldown : Int -- Cooldown in sec (0 = up)
1838 ]]
1839 function HA_GUI_Process_CooldownUpdate(From,SpellCode,Cooldown)
1840 local SpellName = HA_GetLocalName(SpellCode);
1841 local healer = HA_Healers[From];
1842 if(healer and SpellName and HA_Cooldown[SpellCode])
1843 then
1844 healer.Cooldown[SpellName] = { Start = GetTime(); Remain = Cooldown; ispell = SpellCode };
1845 -- Call plugins
1846 for n,pl in HA_ActivePlugins
1847 do
1848 if(pl.OnCooldownUpdate)
1849 then
1850 pl.OnCooldownUpdate(healer,SpellCode,SpellName,Cooldown);
1851 end
1852 end
1853 HA_ChatDebug(HA_DEBUG_SPELLS,SpellName.." cooldown of "..From.." is "..Cooldown);
1854 end
1855 end
1856  
1857 --[[
1858 HA_GUI_Process_SpellOvertime function :
1859 - From : String -- Source player
1860 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1861 - TargetName : String -- Target of the heal
1862 - Duration : Int -- Duration over time
1863 - Estimated : Int -- Estimated spell value (can be 0)
1864 - SpellRank : Int -- Rank of the spell (can be 0)
1865 ]]
1866 function HA_GUI_Process_SpellOvertime(From,SpellCode,TargetName,Duration,Estimated,SpellRank)
1867 local SpellName = HA_GetLocalName(SpellCode);
1868 local healer = HA_Healers[From];
1869 if(healer and SpellName)
1870 then
1871 if(HA_InstantSpells[SpellName])
1872 then
1873 if(SpellRank == nil) then SpellRank = 0; end
1874 local raider = HA_Raiders[TargetName];
1875 if(raider and HA_SpellOvertime[HA_InstantSpells[SpellName].iname])
1876 then
1877 raider.overtime[SpellName] = { From = From; Start = GetTime(); Duration = Duration; ispell = SpellCode; Estimated = Estimated };
1878 _HA_Process_SpellHitInstant(healer,raider,SpellCode,SpellName,Duration,Estimated,SpellRank);
1879 end
1880 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellOvertime from "..From.." to "..tostring(TargetName).." with "..SpellName.." ("..tostring(SpellRank)..") for "..Duration.." secondes (Estimated "..Estimated..")");
1881 end
1882 end
1883 end
1884  
1885 --[[
1886 HA_GUI_Process_SpellInstant function :
1887 - From : String -- Source player
1888 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1889 - TargetName : String -- Target of the spell
1890 - SpellRank : Int -- Rank of the spell (can be 0)
1891 ]]
1892 function HA_GUI_Process_SpellInstant(From,SpellCode,TargetName,SpellRank)
1893 local SpellName = HA_GetLocalName(SpellCode);
1894 local healer = HA_Healers[From];
1895 if(healer and SpellName)
1896 then
1897 if(HA_InstantSpells[SpellName])
1898 then
1899 if(SpellRank == nil) then SpellRank = 0; end
1900 local raider = HA_Raiders[TargetName];
1901 if(raider)
1902 then
1903 _HA_Process_SpellHitInstant(healer,raider,SpellCode,SpellName,0,0,SpellRank);
1904 if(HA_SpellOvertime[HA_InstantSpells[SpellName].iname]) -- Is it a spell over time ?
1905 then
1906 raider.overtime[SpellName] = { From = From; Start = GetTime(); Duration = HA_SpellOvertime[HA_InstantSpells[SpellName].iname].duration; ispell = SpellCode };
1907 end
1908 end
1909 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellInstant from "..From.." to "..tostring(TargetName).." with "..SpellName.." ("..tostring(SpellRank)..")");
1910 end
1911 end
1912 end
1913  
1914 --[[
1915 HA_GUI_Process_SpellRequest function :
1916 - From : String -- Source player
1917 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1918 ]]
1919 function HA_GUI_Process_SpellRequest(From,SpellCode)
1920 local SpellName = HA_GetLocalName(SpellCode);
1921 if(SpellName and HA_Raiders[From])
1922 then
1923 HA_ChatDebug(HA_DEBUG_SPELLS,"HA_GUI_Process_SpellRequest from "..From.." for "..SpellName);
1924 if(HA_Config.AllowSpellRequest[SpellName] and HA_SpellRequest == nil) -- I allow this spell to be auto-casted, and I'm not currently under a request
1925 then
1926 HA_SpellRequest = { spell=SpellName; ispell=SpellCode; target=From; id=HA_Raiders[From].id };
1927 StaticPopup_Show("HA_REQUEST_FOR_SPELL");
1928 else
1929 if(HA_Config.AllowSpellRequest[SpellName] == nil)
1930 then
1931 HA_ChatDebug(HA_DEBUG_SPELLS,"HA_GUI_Process_SpellRequest : Automatically denying request !");
1932 HA_COM_SpellRequestDenied(SpellCode,From,HA_SPELL_REQUEST_CODE_DENIED_BLOCKED);
1933 else
1934 HA_ChatDebug(HA_DEBUG_SPELLS,"HA_GUI_Process_SpellRequest : Denying request, already got one !");
1935 HA_COM_SpellRequestDenied(SpellCode,From,HA_SPELL_REQUEST_CODE_DENIED_BUSY);
1936 end
1937 end
1938 end
1939 end
1940  
1941 --[[
1942 HA_GUI_Process_SpellRequestDenied function :
1943 - From : String -- Source player
1944 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
1945 - ReasonCode : Int -- Reason
1946 ]]
1947 function HA_GUI_Process_SpellRequestDenied(From,SpellCode,ReasonCode)
1948 local SpellName = HA_GetLocalName(SpellCode);
1949 if(SpellName)
1950 then
1951 HA_ChatDebug(HA_DEBUG_SPELLS,"HA_GUI_Process_SpellRequestDenied from "..From.." for "..SpellName);
1952 HA_ChatPrint(string.format(HA_SpellRequestDenied[ReasonCode],SpellName,From));
1953 end
1954 end
1955  
1956 --[[
1957 HA_GUI_Process_RegenMode function :
1958 - From : String -- Source player
1959 - IsInRegen : Bool -- If I go in regen mode
1960 ]]
1961 function HA_GUI_Process_RegenMode(From,IsInRegen)
1962 local healer = HA_Healers[From];
1963 if(healer and HA_Raiders[From])
1964 then
1965 if(IsInRegen)
1966 then
1967 healer.NextResetState = HA_STATE_RESTING;
1968 if(HA_Config.NotifyRegen)
1969 then
1970 HA_ChatPrint(string.format(HA_CHAT_MSG_IN_REGEN,From));
1971 end
1972 if(healer.State == HA_STATE_NOTHING) -- Was doing nothing, change the state now
1973 then
1974 _HA_ResetHealerState(healer,false);
1975 end
1976 else
1977 healer.NextResetState = nil;
1978 if(healer.State == HA_STATE_RESTING) -- Was already in regen state, reset the state
1979 then
1980 _HA_ResetHealerState(healer,false);
1981 end
1982 if(HA_Config.NotifyRegen)
1983 then
1984 HA_ChatPrint(string.format(HA_CHAT_MSG_OUT_OF_REGEN,From));
1985 end
1986 end
1987 HA_ChatDebug(HA_DEBUG_SPELLS,"HA_GUI_Process_RegenMode from "..From.." : "..tostring(IsInRegen));
1988 end
1989 end
1990  
1991 --[[
1992 HA_GUI_Process_GotPowerInfusion function :
1993 - From : String -- Source player
1994 ]]
1995 function HA_GUI_Process_GotPowerInfusion(From)
1996 local raider = HA_Raiders[From];
1997  
1998 if(raider)
1999 then
2000 if(not HA_RaiderInfused(From))
2001 then
2002 raider.overtime[HA_POWER_INFUSION] = { From = "???"; Start = GetTime(); Duration = 15; ispell = HA_SPELL_POWER_INFUSION };
2003 if(From == HA_PlayerName)
2004 then
2005 HA_ChatPrint(HA_CHAT_MSG_INFUSED);
2006 PlaySoundFile("Sound\\Doodad\\HornGoober.wav");
2007 end
2008 HA_ChatDebug(HA_DEBUG_SPELLS,"HA_GUI_Process_GotPowerInfusion : Processing since I didn't get the SpellCooldown message yet");
2009 end
2010 end
2011 end
2012  
2013 --[[
2014 HA_GUI_Process_Announce function :
2015 - From : String -- Source player
2016 - Message : String -- Message to show
2017 ]]
2018 function HA_GUI_Process_Announce(From,Message)
2019 local raider = HA_Raiders[From];
2020  
2021 if(raider)
2022 then
2023 RaidWarningFrame:AddMessage("[HA] "..Message, 0.2, 0.8, 0.2, 1.0);
2024 DEFAULT_CHAT_FRAME:AddMessage("[HA Warning] "..From..": "..Message, 0.2, 0.8, 0.2, 1.0);
2025 PlaySound("RaidWarning");
2026 end
2027 end
2028  
2029  
2030 --[[
2031 HA_GUI_Process_Version function :
2032 - From : String -- Source player
2033 - Version : String -- Player's HA Version
2034 ]]
2035 function HA_GUI_Process_Version(From,Version)
2036 local raider = HA_Raiders[From];
2037 if(raider)
2038 then
2039 raider.Version = Version;
2040 end
2041 if(_HA_NewVersionNotice == false and Version > HA_VERSION)
2042 then
2043 _HA_NewVersionNotice = true;
2044 HA_ChatPrint(HA_TEXT_MINOR_VERSION);
2045 end
2046 end
2047  
2048 --[[
2049 HA_GUI_Process_SpellHotTick function :
2050 - From : String -- Source player
2051 - SpellCode : Int -- International Spell Code (use HA_GetLocalName to get local name)
2052 - TargetName : String -- Target of the heal
2053 - Value : Int -- Healed value
2054 ]]
2055 function HA_GUI_Process_SpellHotTick(From,SpellCode,TargetName,Value)
2056 local SpellName = HA_GetLocalName(SpellCode);
2057 local healer = HA_Healers[From];
2058 local spell = HA_InstantSpells[SpellName];
2059  
2060 if(healer and spell)
2061 then
2062 HA_ChatDebug(HA_DEBUG_SPELLS,"SpellHotTick from "..From.." to "..TargetName.." with "..SpellName.." for "..tostring(Value).." hp.");
2063 local raider = HA_Raiders[TargetName];
2064 if(raider)
2065 then
2066 -- Check overhealed status
2067 local new_hp = _HA_GetRaiderHealthBeforeHeal(raider,Value,healer) + Value;
2068 local overhealed = 0;
2069 if(new_hp > raider.hpmax)
2070 then
2071 overhealed = new_hp - raider.hpmax;
2072 end
2073  
2074 -- Call plugins
2075 for n,pl in HA_ActivePlugins
2076 do
2077 if(pl.OnSpellHotTick)
2078 then
2079 pl.OnSpellHotTick(healer,raider,SpellCode,SpellName,Value,overhealed);
2080 end
2081 end
2082 end
2083 end
2084 end
2085