vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | SH_SMARTHEAL_VERSION= SH_SMARTHEAL.." "..SMARTHEAL_CURRENT_VERSION |
2 | |||
3 | function SmartHeal:Init() |
||
4 | |||
5 | -- Hook the UseAction function and backup original UseAction |
||
6 | SMARTHEAL_ORIG_USEACTION=UseAction; |
||
7 | UseAction = function(slot,arg1,onself) SmartHeal:UseAction(slot,arg1,onself); end; |
||
8 | |||
9 | -- set slash command |
||
10 | SlashCmdList["SMARTHEAL"] = function(arg1) SmartHeal:SlashCmd(arg1); end; |
||
11 | SLASH_SMARTHEAL1 = "/smartheal"; |
||
12 | SLASH_SMARTHEAL2 = "/smh"; |
||
13 | |||
14 | -- get realm and player name |
||
15 | SmartHeal.realmName=GetRealmName(); |
||
16 | SmartHeal.playerName=UnitName("player"); |
||
17 | |||
18 | |||
19 | --local _,_,large_version,small_version,release_version=string.find(SmartHeal_Version,"^(%d+)%.(%d+)%.?(%d*)"); |
||
20 | |||
21 | --if(not SmartHeal_Config['version'] or tonumber(SmartHeal_Config['version'])<tonumber(SMARTHEAL_CURRENT_VERSION)) then |
||
22 | -- SmartHeal_Config={} |
||
23 | --end |
||
24 | |||
25 | SmartHeal_Config['version']=SMARTHEAL_CURRENT_VERSION |
||
26 | |||
27 | -- set realm record in save file |
||
28 | if (not SmartHeal_Config[SmartHeal.realmName]) then |
||
29 | SmartHeal_Config[SmartHeal.realmName]={}; |
||
30 | end |
||
31 | |||
32 | -- set default settings for player if no record in save file |
||
33 | if (not SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName]) then |
||
34 | SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName]={}; |
||
35 | SmartHeal.InitializeSave=1 |
||
36 | end |
||
37 | |||
38 | end |
||
39 | |||
40 | function SmartHeal:InitMiniMapButton() |
||
41 | |||
42 | local MinimapDefaultSettings=SmartHeal.default['minimapbutton'] |
||
43 | |||
44 | MinimapDefaultSettings.left = function() SH_OptionsFrame:Show() end |
||
45 | MinimapDefaultSettings.right = function() ScriptErrors:Hide() end |
||
46 | |||
47 | MyMinimapButton:Create('SmartHeal',SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName]['minimapbutton'],MinimapDefaultSettings) |
||
48 | |||
49 | end |
||
50 | |||
51 | function SmartHeal:isActive() |
||
52 | return SmartHeal.active; |
||
53 | end |
||
54 | |||
55 | function SmartHeal:setDefault(defaultOption) |
||
56 | |||
57 | if(not defaultOption) then |
||
58 | for option in SmartHeal.default do |
||
59 | |||
60 | if (type(SmartHeal.default[option])=="table") then |
||
61 | |||
62 | local module=option |
||
63 | for option2,value in SmartHeal.default[module] do |
||
64 | SmartHeal:setConfig(option2,value,module); |
||
65 | end |
||
66 | |||
67 | else |
||
68 | SmartHeal:setConfig(option,SmartHeal.default[option]); |
||
69 | end |
||
70 | |||
71 | end |
||
72 | else |
||
73 | for i,option in defaultOption do |
||
74 | |||
75 | if (type(SmartHeal.default[option])=="table") then |
||
76 | |||
77 | local module=option |
||
78 | for option2,value in SmartHeal.default[module] do |
||
79 | SmartHeal:setConfig(option2,value,module); |
||
80 | end |
||
81 | |||
82 | else |
||
83 | SmartHeal:setConfig(option,SmartHeal.default[option]); |
||
84 | end |
||
85 | end |
||
86 | |||
87 | end |
||
88 | |||
89 | end |
||
90 | |||
91 | function SmartHeal:setConfig(option,value,module) |
||
92 | |||
93 | if(not SmartHeal:isActive()) then return end |
||
94 | |||
95 | if (value==nil) then value=false end |
||
96 | |||
97 | if (module and module~="" and option and option~="") then |
||
98 | |||
99 | if (not SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName][module]) then |
||
100 | SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName][module]={} |
||
101 | end |
||
102 | |||
103 | SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName][module][option]=value; |
||
104 | |||
105 | |||
106 | else |
||
107 | if (option and option~="") then |
||
108 | SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName][option]=value; |
||
109 | end |
||
110 | end |
||
111 | |||
112 | end |
||
113 | |||
114 | function SmartHeal:getConfig(option,module) |
||
115 | |||
116 | if(not SmartHeal:isActive()) then return end |
||
117 | |||
118 | if (module) then |
||
119 | |||
120 | local moduleConfig=SmartHeal:getConfig(module) |
||
121 | if(moduleConfig) then |
||
122 | return moduleConfig[option] |
||
123 | end |
||
124 | |||
125 | else |
||
126 | if(SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName][option]~=nil) then |
||
127 | return SmartHeal_Config[SmartHeal.realmName][SmartHeal.playerName][option]; |
||
128 | else |
||
129 | return |
||
130 | end |
||
131 | end |
||
132 | end |
||
133 | |||
134 | function SmartHeal:SlashCmd(arg1) |
||
135 | |||
136 | if (not SmartHeal:isActive()) then |
||
137 | SmartHeal:ErrorMsg(SH_IS_NOT_ACTIVE_CLASS) |
||
138 | return; |
||
139 | end; |
||
140 | |||
141 | if(not SH_OptionsFrame:IsShown()) then |
||
142 | SH_OptionsFrame:Show() |
||
143 | end |
||
144 | |||
145 | end |
||
146 | |||
147 | function SmartHeal:doCast(spell,rank) |
||
148 | |||
149 | if (not spell) then return; end; |
||
150 | |||
151 | local spell_with_rank=spell; |
||
152 | SmartHeal.CastedSpell=spell; |
||
153 | |||
154 | if (rank and rank~="") then |
||
155 | spell_with_rank=spell.."("..SH_RANK.." "..rank..")" |
||
156 | SmartHeal.CastedRank=rank; |
||
157 | end |
||
158 | |||
159 | SmartHeal.CacheUnitId=SmartHeal:TargetUnitId() |
||
160 | |||
161 | if (SmartHeal.selfCast==1) then SmartHeal.CacheUnitId="player" end |
||
162 | |||
163 | CastSpellByName(spell_with_rank,SmartHeal.selfCast); |
||
164 | |||
165 | SmartHeal.selfCast=nil |
||
166 | |||
167 | end |
||
168 | |||
169 | function SmartHeal:TargetUnitId() |
||
170 | |||
171 | local targetunitId |
||
172 | |||
173 | if (not UnitExists("target")) then |
||
174 | return |
||
175 | end |
||
176 | |||
177 | if(UnitInRaid("target")) then |
||
178 | |||
179 | for i=1,40 do |
||
180 | if UnitIsUnit("raid"..i,"target") then |
||
181 | targetunitId="raid"..i |
||
182 | break |
||
183 | end |
||
184 | end |
||
185 | |||
186 | elseif(UnitInParty("target") and not UnitIsUnit("player","target")) then |
||
187 | |||
188 | for i=1,4 do |
||
189 | if UnitIsUnit("party"..i,"target") then |
||
190 | targetunitId="party"..i |
||
191 | break |
||
192 | end |
||
193 | end |
||
194 | |||
195 | elseif (UnitIsUnit("target","player")) then |
||
196 | |||
197 | targetunitId="player" |
||
198 | |||
199 | end |
||
200 | |||
201 | return targetunitId |
||
202 | |||
203 | end |
||
204 | |||
205 | function SmartHeal:PlayerHasSpell(spell) |
||
206 | |||
207 | local HasSpell=false |
||
208 | local i = 1 |
||
209 | while true do |
||
210 | local sName , sRank = GetSpellName(i, BOOKTYPE_SPELL) |
||
211 | if not sName then |
||
212 | do break end |
||
213 | else |
||
214 | if (sName==spell) then |
||
215 | HasSpell=true |
||
216 | break |
||
217 | end |
||
218 | end |
||
219 | |||
220 | i = i + 1 |
||
221 | end |
||
222 | |||
223 | return HasSpell; |
||
224 | end |
||
225 | |||
226 | function SmartHeal:Cast(spell_fullname,ForceTarget) |
||
227 | |||
228 | |||
229 | local _,_,spell,rankCap=string.find(spell_fullname,"(.+)%("..SH_RANK.." (%d+)%)") |
||
230 | |||
231 | if (not spell) then |
||
232 | spell=spell_fullname |
||
233 | end |
||
234 | |||
235 | if (not SmartHeal:isActive()) then |
||
236 | SmartHeal:ErrorMsg(SH_IS_NOT_ACTIVE_CLASS) |
||
237 | return |
||
238 | end; |
||
239 | |||
240 | if ( not SmartHeal:getConfig("enable") or spell=="" or not spell) then |
||
241 | return |
||
242 | end |
||
243 | |||
244 | if (not SmartHeal.selfCast) then |
||
245 | SmartHeal.selfCast=SmartHeal:isSelfCast(spell) |
||
246 | if (IsAltKeyDown() and SmartHeal:getConfig("altselfcast")) then |
||
247 | SmartHeal.selfCast=1 |
||
248 | elseif(SmartHeal.HotkeyMouseButton=="RightButton" and SmartHeal:getConfig("RClickHotKeySelfCast")) then |
||
249 | SmartHeal.selfCast=1 |
||
250 | elseif ( |
||
251 | --SmartHeal.selfCast==1 and not SmartHeal:getConfig("autoselfcast") or |
||
252 | ((UnitCanAttack("player","target") and ForceTarget)) |
||
253 | |||
254 | ) then |
||
255 | SmartHeal.selfCast=0 |
||
256 | SmartHeal:doCast(spell,rankCap) |
||
257 | return |
||
258 | end |
||
259 | end |
||
260 | |||
261 | local rank |
||
262 | |||
263 | if (SmartHeal.buffList[spell]~=nil) then |
||
264 | SmartHeal.isBuff=true |
||
265 | SmartHeal.isHeal=false |
||
266 | rank=SmartHeal:buffRank(spell) |
||
267 | elseif (SmartHeal.spellList[spell]~=nil) then |
||
268 | SmartHeal.isBuff=false |
||
269 | SmartHeal.isHeal=true |
||
270 | rank=SmartHeal:healRank(spell) |
||
271 | else |
||
272 | SmartHeal:doCast(spell,rankCap) |
||
273 | end |
||
274 | |||
275 | if (spell==SH_LESSER_GREATER_HEALS) then |
||
276 | if (rank<=3) then |
||
277 | spell=SH_LESSER_HEAL |
||
278 | elseif (rank<=7) then |
||
279 | spell=SH_HEAL |
||
280 | rank=rank-3 |
||
281 | else |
||
282 | spell=SH_GREATER_HEAL |
||
283 | rank=rank-7 |
||
284 | end |
||
285 | end |
||
286 | |||
287 | if(rankCap) then |
||
288 | rank=min(rank,tonumber(rankCap)) |
||
289 | end |
||
290 | |||
291 | SmartHeal:doCast(spell,rank); |
||
292 | end |
||
293 | |||
294 | function SmartHeal:healRank(spell) |
||
295 | |||
296 | local SpellStats=SmartHeal.spellList[spell]; |
||
297 | |||
298 | local target="target"; |
||
299 | if(SmartHeal.selfCast==1) then |
||
300 | target="player"; |
||
301 | end |
||
302 | |||
303 | local ignoreMana=false |
||
304 | if (UnitIsDead("player")) then ignoreMana=true end |
||
305 | |||
306 | local maxrank=SmartHeal:SpellMaxRank(spell,ignoreMana) |
||
307 | if (not maxrank) then return end |
||
308 | |||
309 | -- target max acceptable rank or optimal rank whichever is lower |
||
310 | local rank = min(SmartHeal:targetRank(target,spell),maxrank) |
||
311 | |||
312 | if ( SpellStats.HoT==1 |
||
313 | or (not UnitInParty(target) and not UnitInRaid(target) and not UnitIsUnit("player",target)) |
||
314 | or (SmartHeal:ClickHeal_IsOverdrive()) -- overdrive mode ignore hp deficit |
||
315 | ) then |
||
316 | |||
317 | if(SpellStats.HoT~=1) then |
||
318 | SmartHeal.HealedValue=SmartHeal:AdjustHealValue(spell,rank) |
||
319 | end |
||
320 | |||
321 | return rank |
||
322 | end |
||
323 | |||
324 | -- find the best spell rank for the health deficit |
||
325 | local hpDeficit=0; |
||
326 | local TotalHeal=0 |
||
327 | local rank2=1 |
||
328 | if (SpellStats.group==1) then |
||
329 | for i=1,4 do |
||
330 | hpDeficit=max(hpDeficit,UnitHealthMax("party"..i)-UnitHealth("party"..i)); |
||
331 | end |
||
332 | hpDeficit=max(hpDeficit, (UnitHealthMax("player")-UnitHealth("player")) ) |
||
333 | else |
||
334 | hpDeficit=UnitHealthMax(target)-UnitHealth(target); |
||
335 | end |
||
336 | |||
337 | |||
338 | for r=1,table.getn(SpellStats.value) do |
||
339 | |||
340 | rank2=r |
||
341 | TotalHeal=SmartHeal:AdjustHealValue(spell,r) |
||
342 | if (TotalHeal>hpDeficit*SmartHeal:getConfig('overheal')/100) then |
||
343 | SmartHeal.HealedValue=TotalHeal |
||
344 | break |
||
345 | end |
||
346 | |||
347 | end |
||
348 | |||
349 | return min(rank,rank2) |
||
350 | |||
351 | end |
||
352 | |||
353 | function SmartHeal:isSelfCast(spell) |
||
354 | |||
355 | if (not UnitExists("target") or not UnitIsFriend("target","player")) then |
||
356 | return 1 |
||
357 | else |
||
358 | return 0 |
||
359 | end |
||
360 | |||
361 | end |
||
362 | |||
363 | function SmartHeal:targetRank(target,spell) |
||
364 | |||
365 | local targetRank=1; |
||
366 | local SpellStats |
||
367 | |||
368 | |||
369 | if (SmartHeal.isBuff) then |
||
370 | SpellStats=SmartHeal.buffList[spell]; |
||
371 | elseif (SmartHeal.isHeal) then |
||
372 | SpellStats=SmartHeal.spellList[spell]; |
||
373 | end |
||
374 | |||
375 | -- find target acceptable rank |
||
376 | for i=table.getn(SpellStats.level),1,-1 do |
||
377 | if (UnitLevel(target)>=SpellStats.level[i]-10) then |
||
378 | targetRank=i; |
||
379 | break; |
||
380 | |||
381 | end |
||
382 | end |
||
383 | |||
384 | return targetRank |
||
385 | end |
||
386 | |||
387 | function SmartHeal:AdjustHealValue(spell,rank) |
||
388 | |||
389 | -- calculate bonus offsets |
||
390 | local EquipmentBonus=0 |
||
391 | if (BonusScanner) then |
||
392 | EquipmentBonus=tonumber(BonusScanner:GetBonus("HEAL")) |
||
393 | end |
||
394 | |||
395 | -- Adjust Talent |
||
396 | local talent_multiplier,talent_adder=SmartHeal:TalentAdjust(spell) |
||
397 | |||
398 | local healvalue=(SmartHeal.spellList[spell].value[rank]*talent_multiplier)+talent_adder+(EquipmentBonus*SmartHeal:bonusAdjust(spell,rank)); |
||
399 | |||
400 | return healvalue or 0 |
||
401 | |||
402 | end |
||
403 | |||
404 | function SmartHeal:UseAction(slot, arg2, onself) |
||
405 | |||
406 | -- Hack to get the spell name |
||
407 | SmartHealSpellTooltip:SetAction(slot) |
||
408 | local spell = getglobal("SmartHealSpellTooltipTextLeft1"):GetText() |
||
409 | local rankTemp = getglobal("SmartHealSpellTooltipTextRight1"):GetText() |
||
410 | local _,rankCap |
||
411 | if(rankTemp) then |
||
412 | _,_,rankCap=string.find(rankTemp,"^"..SH_RANK.." (%d+)") |
||
413 | end |
||
414 | |||
415 | SmartHeal.HotkeyMouseButton=arg1 |
||
416 | |||
417 | if ( (SmartHeal.spellList[spell]~=nil or SmartHeal.buffList[spell]~=nil) |
||
418 | and SmartHeal:getConfig("override") and SmartHeal:getConfig("enable")) then |
||
419 | |||
420 | if (rankCap) then |
||
421 | SmartHeal:Cast(spell.."("..SH_RANK.." "..rankCap..")") |
||
422 | else |
||
423 | SmartHeal:Cast(spell) |
||
424 | end |
||
425 | |||
426 | else |
||
427 | |||
428 | SmartHeal.selfCast=onself |
||
429 | |||
430 | -- Check for alt self cast |
||
431 | if (IsAltKeyDown() and SmartHeal:getConfig("altselfcast")) then |
||
432 | SmartHeal.selfCast=1 |
||
433 | |||
434 | elseif(SmartHeal.HotkeyMouseButton=="RightButton" and SmartHeal:getConfig("RClickHotKeySelfCast")) then |
||
435 | |||
436 | SmartHeal.selfCast=1 |
||
437 | |||
438 | elseif( SmartHeal:isSelfCast(spell)==1 and SmartHeal:getConfig("autoselfcast") and |
||
439 | (SmartHeal.spellList[spell]~=nil or SmartHeal.buffList[spell]~=nil) |
||
440 | |||
441 | ) then |
||
442 | SmartHeal.selfCast=1 |
||
443 | end |
||
444 | |||
445 | SmartHeal.CacheUnitId=SmartHeal:TargetUnitId() |
||
446 | |||
447 | if (rankCap and SmartHeal.spellList[spell]~=nil and SmartHeal.spellList[spell].HoT~=1) then |
||
448 | SmartHeal.HealedValue=SmartHeal:AdjustHealValue(spell,tonumber(rankCap)) |
||
449 | end |
||
450 | |||
451 | -- do default button action if the spell is not listed in the healing spells list |
||
452 | SMARTHEAL_ORIG_USEACTION(slot, arg2, SmartHeal.selfCast) |
||
453 | |||
454 | SmartHeal.selfCast=nil |
||
455 | end |
||
456 | |||
457 | |||
458 | end |
||
459 | |||
460 | function SmartHeal:SpellMaxRank(spellname,ignoreMana) |
||
461 | local maxRank=1; |
||
462 | local manatooltip; |
||
463 | local spells={[1]=spellname} |
||
464 | |||
465 | if(spellname==SH_LESSER_GREATER_HEALS) then |
||
466 | spells={[1]=SH_LESSER_HEAL, [4]=SH_HEAL, [8]=SH_GREATER_HEAL,} |
||
467 | end |
||
468 | |||
469 | |||
470 | for r,spell in spells do |
||
471 | local i = 1 |
||
472 | while true do |
||
473 | local sName , sRank = GetSpellName(i, BOOKTYPE_SPELL) |
||
474 | if not sName then |
||
475 | do break end |
||
476 | elseif (sName==spells[r]) then |
||
477 | local _,_,rankNumber=string.find(sRank,"^"..SH_RANK.." (%d+)") |
||
478 | if (rankNumber and rankNumber~="") then |
||
479 | rankNumber=tonumber(rankNumber) |
||
480 | SmartHealSpellTooltip:SetSpell(i,BOOKTYPE_SPELL) |
||
481 | manatooltip = getglobal("SmartHealSpellTooltipTextLeft2"):GetText() |
||
482 | local _,_,mana=string.find(manatooltip,"^(%d+) "..SH_MANA); |
||
483 | if ((mana and UnitMana('player')>tonumber(mana)) or not mana or ignoreMana) then |
||
484 | maxRank=max(maxRank,rankNumber+(r-1)) |
||
485 | end |
||
486 | else |
||
487 | return |
||
488 | end |
||
489 | end |
||
490 | |||
491 | i = i + 1 |
||
492 | end -- end of while loop |
||
493 | end -- end of for loop |
||
494 | return maxRank |
||
495 | end |
||
496 | |||
497 | function SmartHeal:TalentAdjust(spell) |
||
498 | |||
499 | local _, playerClass = UnitClass("player"); |
||
500 | local rank |
||
501 | local multiplier_factor=1 |
||
502 | local additional_factor=0; |
||
503 | |||
504 | if (playerClass=="PRIEST") then |
||
505 | |||
506 | -- Improved Renew (renew only) 5% per point |
||
507 | _, _, _, _, rank,_= GetTalentInfo(2,2); |
||
508 | if (spell==SH_RENEW) then multiplier_factor=multiplier_factor*(1+(rank*0.05)); end; |
||
509 | |||
510 | -- Spiritual Healing (all healing) 2% per point |
||
511 | _, _, _, _, rank,_= GetTalentInfo(2,15); |
||
512 | multiplier_factor=multiplier_factor*(1+(rank*0.02)); |
||
513 | |||
514 | -- Spiritual Guidance (all healing) 5% per point, based on total spirit |
||
515 | _, _, _, _, rank,_= GetTalentInfo(2,14); |
||
516 | |||
517 | local spirit=0; |
||
518 | if (BonusScanner) then |
||
519 | spirit=tonumber(BonusScanner:GetBonus("SPI")); |
||
520 | end |
||
521 | |||
522 | additional_factor=additional_factor+spirit*(rank*0.05) |
||
523 | |||
524 | elseif (playerClass=="PALADIN") then |
||
525 | |||
526 | -- Healing Light (healing light and flash light) 4% per point |
||
527 | _, _, _, _, rank,_= GetTalentInfo(1,5); |
||
528 | if (spell==SH_HEALING_LIGHT or spell==SH_FLASH_OF_LIGHT) then multiplier_factor=multiplier_factor*(1+(rank*0.04)); end; |
||
529 | |||
530 | elseif (playerClass=="DRUID") then |
||
531 | |||
532 | -- Improved Rejuvenation (rejuvenation only) 5% per point |
||
533 | _, _, _, _, rank,_= GetTalentInfo(3,10); |
||
534 | if (spell==SH_REJUVENATION) then multiplier_factor=multiplier_factor*(1+(rank*0.05)); end; |
||
535 | |||
536 | -- Gift of Nature (all healing spells) 2% per point |
||
537 | _, _, _, _, rank,_= GetTalentInfo(3,12); |
||
538 | multiplier_factor=multiplier_factor*(1+(rank*0.02)); |
||
539 | |||
540 | elseif (playerClass=="SHAMAN") then |
||
541 | |||
542 | -- Purification 2% per point |
||
543 | _, _, _, _, rank,_= GetTalentInfo(3,10); |
||
544 | multiplier_factor=multiplier_factor*(1+(rank*0.02)); |
||
545 | |||
546 | end |
||
547 | |||
548 | return multiplier_factor,additional_factor |
||
549 | |||
550 | end |
||
551 | |||
552 | function SmartHeal:bonusAdjust(spell,rank) |
||
553 | |||
554 | local SpellStats=SmartHeal.spellList[spell]; |
||
555 | local bonus=1; |
||
556 | local castTimeBonus=1; |
||
557 | local lowlevelBonus=1; |
||
558 | local HoTBonus=1; |
||
559 | |||
560 | -- cast time discount, ActualBenefit = AdvertisedBenefit * (CastingTime / 3.5) |
||
561 | if (SpellStats.castTime[rank]<3.5 and SpellStats.value[rank]>0) then |
||
562 | castTimeBonus=SpellStats.castTime[rank]/3.5; |
||
563 | end |
||
564 | |||
565 | -- Low level discount , EffectiveBonus = (1-((20-LevelLearnt)*0.0375))*AdvertisedBonus |
||
566 | if (SpellStats.level[rank]<20) then |
||
567 | lowlevelBonus=(1-((20-SpellStats.level[rank])*0.0375)) |
||
568 | end |
||
569 | |||
570 | -- Heal+HoT discount |
||
571 | if (SpellStats.HoTvalue~=nil) then |
||
572 | if (SpellStats.value[rank]>0 and SpellStats.HoTvalue[rank]>0) then |
||
573 | HoTBonus=SpellStats.value[rank]/(SpellStats.value[rank]+SpellStats.HoTvalue[rank]) |
||
574 | end |
||
575 | end |
||
576 | bonus=bonus*castTimeBonus*lowlevelBonus*HoTBonus; |
||
577 | |||
578 | return bonus; |
||
579 | end |
||
580 | |||
581 | function SmartHeal:buffRank(spell) |
||
582 | |||
583 | local BuffStats=SmartHeal.buffList[spell]; |
||
584 | local targetRank=1; |
||
585 | local target="target"; |
||
586 | |||
587 | if(SmartHeal.selfCast==1) then |
||
588 | target="player"; |
||
589 | end |
||
590 | |||
591 | local maxrank=SmartHeal:SpellMaxRank(spell) |
||
592 | |||
593 | if(not maxrank) then return end |
||
594 | |||
595 | if (BuffStats.group==0) then -- target buff |
||
596 | targetRank=SmartHeal:targetRank(target,spell); |
||
597 | |||
598 | elseif (BuffStats.group==1) then -- group member buff |
||
599 | |||
600 | for i=1,4 do |
||
601 | targetRank=max(targetRank,SmartHeal:targetRank("party"..i,spell)); |
||
602 | end |
||
603 | |||
604 | targetRank=max(targetRank,SmartHeal:targetRank("player",spell)); |
||
605 | |||
606 | elseif (BuffStats.group==2) then -- paladin unit class blessings |
||
607 | |||
608 | local _, targetClass = UnitClass(target); |
||
609 | local thisUnitClass; |
||
610 | |||
611 | if SmartHeal:inRaid() then |
||
612 | |||
613 | for i=1,40 do |
||
614 | |||
615 | _, thisUnitClass = UnitClass("raid"..i); |
||
616 | if (thisUnitClass==targetClass) then |
||
617 | targetRank=max(targetRank,SmartHeal:targetRank("raid"..i,spell)); |
||
618 | end |
||
619 | |||
620 | end |
||
621 | |||
622 | elseif SmartHeal:inParty() then |
||
623 | |||
624 | for i=1,4 do |
||
625 | |||
626 | _, thisUnitClass = UnitClass("party"..i); |
||
627 | if (thisUnitClass==targetClass) then |
||
628 | targetRank=max(targetRank,SmartHeal:targetRank("party"..i,spell)); |
||
629 | end |
||
630 | |||
631 | end |
||
632 | targetRank=max(targetRank,SmartHeal:targetRank("player",spell)); |
||
633 | |||
634 | end |
||
635 | |||
636 | else |
||
637 | targetRank=SmartHeal:targetRank(target,spell); -- treat as target only buff |
||
638 | end |
||
639 | |||
640 | -- target max acceptable rank or player max rank whichever is lower |
||
641 | return min(targetRank,maxrank); |
||
642 | |||
643 | end |
||
644 | |||
645 | function SmartHeal:inRaid() |
||
646 | if GetNumRaidMembers()>0 then |
||
647 | return true |
||
648 | else |
||
649 | return false |
||
650 | end |
||
651 | end |
||
652 | |||
653 | function SmartHeal:inParty() |
||
654 | if GetNumPartyMembers()>0 then |
||
655 | return true |
||
656 | else |
||
657 | return false |
||
658 | end |
||
659 | end |
||
660 | |||
661 | function SmartHeal:ErrorMsg(msg,r,g,b) |
||
662 | if (not r and not g and not b) then |
||
663 | r=1;g=0;b=0; |
||
664 | end |
||
665 | DEFAULT_CHAT_FRAME:AddMessage(msg,r,g,b); |
||
666 | end |
||
667 | |||
668 | function SmartHeal:doDebug() |
||
669 | |||
670 | SmartHeal:ErrorMsg("SmartHeal Casted: "..SmartHeal.CastedSpell.."(Rank "..SmartHeal.CastedRank..")") |
||
671 | |||
672 | if (SMARTHEAL_HEALTABLE[SmartHeal.playerClass] ~= nil) then |
||
673 | SmartHeal_DebugMsg['talent']=SmartHeal:getAllTalent() |
||
674 | end |
||
675 | |||
676 | end |
||
677 | |||
678 | function SmartHeal:AlertHealer(arg1) |
||
679 | |||
680 | if (not UnitExists("target") or not UnitIsFriend("player","target")) then |
||
681 | return |
||
682 | end |
||
683 | |||
684 | local current_targetName=UnitName("target") |
||
685 | |||
686 | local _,_,casterName,spell=string.find(arg1,"(.+) "..SH_BEGINS_TO_CAST.." (.+).") |
||
687 | if(not casterName or not spell) then return end |
||
688 | |||
689 | TargetByName(casterName) |
||
690 | |||
691 | if (UnitName("target")==casterName and UnitName("targettarget")==current_targetName) then |
||
692 | |||
693 | local _, casterClass = UnitClass("target"); |
||
694 | |||
695 | if (UnitName("target")~= current_targetName) then |
||
696 | TargetLastTarget() |
||
697 | end |
||
698 | |||
699 | local alert_msg=string.format(SH_ALERT_HEALER_MSG, casterName, spell, current_targetName); |
||
700 | local holdtime=UIERRORS_HOLD_TIME; |
||
701 | local casterspellList=SMARTHEAL_HEALTABLE[casterClass]; |
||
702 | |||
703 | if (casterspellList) then |
||
704 | local spellStats=casterspellList[spell]; |
||
705 | if (spellStats) then |
||
706 | if (spellStats.castTime[1]) then |
||
707 | holdtime=spellStats.castTime[1]; -- take the rank 1 cast time as holdtime |
||
708 | end |
||
709 | |||
710 | UIErrorsFrame:AddMessage(alert_msg, 0, 1.0, 0, 1.0, holdtime); |
||
711 | end |
||
712 | |||
713 | end |
||
714 | |||
715 | else |
||
716 | |||
717 | if (UnitName("target")~= current_targetName) then |
||
718 | TargetLastTarget() |
||
719 | end |
||
720 | end |
||
721 | |||
722 | end |
||
723 | |||
724 | -- cannot stop cast onupdate after 1.10 , using warning alert instead |
||
725 | function SmartHeal:StopCasting_OnUpdate(arg1) |
||
726 | |||
727 | --if (not SmartHeal.SpellIsCasting and not SmartHeal.SpellIsChanneling) then return end |
||
728 | |||
729 | if (not SmartHeal.HealUnitId or not SmartHeal.DoExcessHealAlert or not SmartHeal:getConfig("excesshealalert")) then |
||
730 | return |
||
731 | end |
||
732 | |||
733 | if (SmartHeal.SpellIsCasting) then |
||
734 | SmartHeal.timer=SmartHeal.timer-(arg1*1000) |
||
735 | end |
||
736 | |||
737 | if(SmartHeal.timer<1000) then |
||
738 | |||
739 | local hp_ratio=UnitHealth(SmartHeal.HealUnitId)/UnitHealthMax(SmartHeal.HealUnitId)*100 |
||
740 | |||
741 | if (hp_ratio>=SmartHeal:getConfig("excesshealalerttrigger")) then |
||
742 | UIErrorsFrame:AddMessage(SH_EXCESSIVE_HEALING_ALERT_MSG.." "..UnitName(SmartHeal.HealUnitId).."!!!", 1, 0, 1, 1.0,3); |
||
743 | end |
||
744 | |||
745 | SmartHeal.DoExcessHealAlert=nil |
||
746 | |||
747 | end |
||
748 | |||
749 | end |
||
750 | |||
751 | -- for debug purposes, use when talent tree is changed by Blizzard |
||
752 | function SmartHeal:getAllTalent() |
||
753 | |||
754 | local _, playerClass = UnitClass("player"); |
||
755 | local numTabs = GetNumTalentTabs(); |
||
756 | local talent={} |
||
757 | talent[playerClass]={} |
||
758 | for t=1, numTabs do |
||
759 | local numTalents = GetNumTalents(t); |
||
760 | talent[playerClass][t]={} |
||
761 | for i=1, numTalents do |
||
762 | local nameTalent, _, _, _, currRank, maxRank= GetTalentInfo(t,i); |
||
763 | talent[playerClass][t][i]={name=nameTalent, rank=currRank,max=maxRank} |
||
764 | end |
||
765 | end |
||
766 | |||
767 | return talent |
||
768 | end |
||
769 |