vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[---------------------------------------------------------------------------------
2 This is a template for the plugin/module system for Clique.
3  
4 Plugins are typically used to tie Clique to a specific set of unit frames, but
5 can also be used to add functionality to the system through a manner of hooks.
6  
7 Plugins are registered with Clique with a shortname that is used for all slash
8 commands. In addition they are required to have a fullname parameter that is
9 used in all display messages
10 ----------------------------------------------------------------------------------]]
11  
12 local L = AceLibrary("AceLocale-2.0"):new("Clique")
13  
14 -- Create a new plugin for Clique, with the shortname "test"
15 local Plugin = Clique:NewModule("healselect")
16 Plugin.fullname = "Clique Heal Selection"
17  
18 -- Plugin:Test() is called anytime the mod tries to enable. It is optional
19 -- but it will be checked if it exists. Will typically be based off some global
20 -- or the state of the addon itself.
21 function Plugin:Test()
22 local _,class = UnitClass("player")
23 return class == "SHAMAN" or class == "PALADIN" or class == "DRUID" or class == "PRIEST"
24 end
25  
26 -- Plugin:OnEnable() is called if Plugin:Test() is true, and the mod hasn't been explicitly
27 -- disabled. This is where you should handle all your hooks, etc.
28 function Plugin:OnEnable()
29  
30 Clique:RegisterCustomFunction("Clique:EfficientHeal()", "Clique:EfficientHeal()", "Cast Efficient Heal the unit you clicked on.")
31 Clique:RegisterCustomFunction("Clique:EmergencyHeal()", "Clique:EmergencyHeal()", "Cast Emergency Heal the unit you clicked on.")
32  
33 local spell_lookup = {
34 [L"Lesser Heal"] = "EFFICIENT",
35 [L"Heal"] = "EFFICIENT",
36 [L"Greater Heal"] = "EFFICIENT",
37 [L"Flash Heal"] = "EMERGENCY",
38 [L"Healing Touch"] = "EFFICIENT",
39 [L"Regrowth"] = "EMERGENCY",
40 [L"Healing Wave"] = "EFFICIENT",
41 [L"Lesser Healing Wave"] = "EMERGENCY",
42 [L"Holy Light"] = "EFFICIENT",
43 [L"Flash of Light"] = "EMERGENCY",
44 }
45  
46 self:LevelDebug(2, "Creating a tooltip for scanning purposes")
47 if not Clique.tooltip then
48 local tt = CreateFrame("GameTooltip", "CliqueTooltip", nil, "GameTooltipTemplate")
49 tt:SetOwner(tt, "ANCHOR_NONE")
50 tt.name = CliqueTooltipTextLeft1
51 Clique.tooltip = tt
52 end
53  
54 self:LevelDebug(2, "Removing all old spell data")
55  
56 local spellbook = Clique.spellbook
57 spellbook.EFFICIENT = Clique:ClearTable(spellbook.EFFICIENT)
58 spellbook.EMERGENCY = Clique:ClearTable(spellbook.EMERGENCY)
59  
60 self:LevelDebug(2, "Scanning the spellbook for heal spells")
61  
62 local tabs = GetNumSpellTabs()
63 local name,texture,start,offset = GetSpellTabInfo(tabs)
64 local numspells = start + offset
65 local RANK_PATTERN = L"RANK" .. " (%d+)"
66  
67 self:LevelDebug(3, "Scanning " .. tabs .. " tabs for spells.")
68 for i=1,numspells do
69 local name,rank = GetSpellName(i, BOOKTYPE_SPELL)
70 self:LevelDebug(3, "** Scanning spell id: " .. i .. " found " .. name .. ".")
71 local _,_,numrank = string.find(rank, RANK_PATTERN)
72 numrank = tonumber(numrank)
73  
74 local type = spell_lookup[name]
75 if type then
76 self:LevelDebug(3, "Build a tooltip with the spell information")
77 Clique.tooltip:SetSpell(i, BOOKTYPE_SPELL)
78  
79 self:LevelDebug(3, "Scanning for mana cost")
80  
81 local _,mana,min,max
82  
83 _,_,mana = string.find(CliqueTooltipTextLeft2:GetText(), L"MANA_PATTERN")
84  
85 for i=1,10 do
86 local t = getglobal("CliqueTooltipTextLeft"..i)
87 if not t:IsVisible() then break end
88  
89 _,_,min,max = string.find(t:GetText(), L"HEALTH_PATTERN")
90 if min and max then
91 break
92 elseif min or max then
93 self:LevelDebug(3, "Found some funky error when scanning tooltip for %s", name)
94 end
95 end
96  
97 if not (mana and min and max) then
98 error("Could not properly scan tooltips. Try reloading")
99 self:LevelDebug(1, "Could not properly scan tooltip for %s", name)
100 end
101  
102 mana,min,max = tonumber(mana),tonumber(min),tonumber(max)
103  
104 local t = {
105 ["name"] = name,
106 ["rank"] = tonumber(numrank),
107 ["mana"] = mana,
108 ["min"] = min,
109 ["max"] = max,
110 ["amt"] = math.floor((max + min) / 2),
111 ["cast"] = string.format("%s(%s %d)", name, L"RANK", numrank),
112 }
113  
114 table.insert(Clique.spellbook[type], t)
115 end
116  
117 local sort_mana = function(a,b) return a.mana < b.mana end
118 table.sort(Clique.spellbook.EFFICIENT, sort_mana)
119 table.sort(Clique.spellbook.EMERGENCY, sort_mana)
120 end
121  
122 self:LevelDebug(2, "Injecting Clique:EfficientHeal() and Clique:EmergencyHeal()")
123  
124 local health_lookup = {
125 ["DRUID"] = {[1] = 30, [60] = 3500},
126 ["MAGE"] = {[1] = 30, [60] = 2500},
127 ["HUNTER"] = {[1] = 30, [60] = 3500},
128 ["PALADIN"] = {[1] = 30, [60] = 4000},
129 ["PRIEST"] = {[1] = 30, [60] = 2500},
130 ["ROGUE"] = {[1] = 30, [60] = 3500},
131 ["SHAMAN"] = {[1] = 30, [60] = 3800},
132 ["WARLOCK"] = {[1] = 30, [60] = 3500},
133 ["WARRIOR"] = {[1] = 30, [60] = 5000},
134 }
135  
136 -- Returns a quick guess as to how much health a unit has, along with their predicted max health
137 Clique.GuessHealth = function(self, unit)
138 -- Friendly will be nil if this isn't a friendly unit
139 local friendly = Clique:GetFriendlyUnit(unit)
140  
141 if not friendly then
142  
143 -- This means we don't have a friendly unit id for this unit
144 local _,class = UnitClass(unit)
145 local slope = (health_lookup[class][60] - health_lookup[class][1]) / 60
146 local health_max = UnitLevel(unit) * slope + health_lookup[class][1]
147 local health = health_max * (UnitHealth(unit)/UnitHealthMax(unit))
148 return health, health_max
149 else
150 -- We can get at the numbers natively
151 return UnitHealth(friendly), UnitHealthMax(friendly)
152 end
153 end
154  
155 local SelectHeal = function(type, unit, modifier)
156 self:LevelDebug(3, "SelectHeal(%s, %s, %s)", tostring(type), tostring(unit), tostring(modifier))
157 if not unit then
158 self:LevelDebug(3, "Setting unit to %s", tostring(Clique.unit))
159 unit = Clique.unit
160 end
161 if not unit or not UnitExists(unit) then
162 error("Bad argument #2 passed to Clique:EfficientHeal, must supply a valid unitid.")
163 end
164 if table.getn(Clique.spellbook[type]) == 0 then
165 self:LevelDebug(1, "No spells of type \"%s\"", type)
166 return
167 end
168  
169 local cur_mana = UnitMana("player")
170 local hp,hpmax = Clique:GuessHealth(unit)
171 local deficit = hpmax - hp
172  
173 if modifier then
174 deficit = deficit + modifier
175 end
176  
177 if Clique.plusHealing and deficit > Clique.plusHealing then
178 self:LevelDebug(3, "The deficit is larger than our plusHealing setting (current deficit is %d)", deficit)
179 deficit = deficit - Clique.plusHealing
180 end
181  
182 self:LevelDebug(3, "Got health for %s [Cur: %d, Max: %d, deficit: %d]", unit, hp, hpmax, deficit)
183  
184 if deficit == 0 then
185 self:LevelDebug(2, "Not casting and spells. %s is at full health.", UnitName(unit))
186 return true
187 end
188 local num = table.getn(Clique.spellbook[type])
189  
190 -- Look for the first spell that will heal the unit fully
191 for i,entry in Clique.spellbook[type] do
192 local isbuff = Clique:IsBuff(entry.name)
193 local validBuff = Clique:BuffTest(entry.name, entry.rank, unit)
194 local freemana = Clique:IsBuffActive(L"FREE_INNER_FIRE")
195  
196 self:LevelDebug(3, "Testing rank %d with level %d", entry.rank, UnitLevel(unit))
197  
198 local valid = true
199 if isbuff and not validBuff then
200 valid = false
201 end
202  
203 if (entry.amt >= deficit or i == num) and valid then
204 -- We have a candidate for this spell
205 if entry.mana <= cur_mana or freemana then
206 Clique:CastSpell(entry.cast)
207 self:LevelDebug(1, "Casting %s on %s for min %d", entry.cast, UnitName(unit), entry.min)
208 return true
209 else
210 for k=i,1,-1 do
211 local e = Clique.spellbook[type][k]
212 if e.mana <= cur_mana then
213 Clique:CastSpell(e.cast)
214 self:LevelDebug(1, "Casting (low mana) %s on %s for avg %s", e.cast, UnitName(unit), tostring(e.amt))
215 return true
216 end
217 end
218 end
219 end
220 end
221 self:LevelDebug(2, "Could not find a suitable spell to cast for %s", type)
222 end
223  
224 Clique.EfficientHeal = function(self, unit, modifier)
225 return SelectHeal("EFFICIENT", unit, modifier)
226 end
227  
228 Clique.EmergencyHeal = function(self, unit, modifier)
229 if Clique.plusHealing then
230 if not modifier then modifier = 0 end
231 local plus = math.floor(Clique.plusHealing * .58)
232 -- modifier makes the deficit larger, so we need to ADD
233 -- the amount we're MISSING in plusHealing to modifier
234 modifier = modifier + plus
235 end
236 return SelectHeal("EMERGENCY", unit, modifier)
237 end
238 end