vanilla-wow-addons – Blame information for rev 1
?pathlinks?
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 |