02682ca - Add Empowered Pulse Grenade to be tracked
[wowui.git] / OmaRF / RaidFrame.lua
1 -- RaidFrame.lua
2 local _;
3 local unpack, pairs = unpack, pairs;
4 local format = string.format;
5 local UnitInRange = UnitInRange;
6 local InCombatLockdown = InCombatLockdown;
7 local CreateFrame, RegisterStateDriver, RegisterUnitWatch = CreateFrame, RegisterStateDriver, RegisterUnitWatch;
8 local CTimerAfter = C_Timer.After;
9 local STANDARD_TEXT_FONT = STANDARD_TEXT_FONT;
10 local GameTooltip = GameTooltip;
11 local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor;
12
13 local registerEvents = OmaRFEvents.RegisterEvents;
14 local registerUnitEvents = OmaRFEvents.RegisterUnitEvents;
15 local unitEvent = OmaRFEvents.UnitEvent;
16 local setupIndicators = OmaRFIndicators.SetupIndicators;
17
18 local Settings = OmaRFSettings;
19 local baseColor = Settings.BaseColor;
20 local bgColor = Settings.BgColor;
21 local healthColor = Settings.HealthColor;
22 local shieldColor = Settings.ShieldColor;
23 local shieldhlColor = Settings.ShieldhlColor;
24 local healpredColor = Settings.HealpredColor;
25 local healabsorbColor = Settings.HealabsorbColor;
26 local width, height = Settings.Width, Settings.Height;
27 -- placeholders with visible values when error happens
28 local anchorX, anchorY = 10, 10;
29 local attributes = {};
30
31 local CFrame = CreateFrame("Frame", "OmaRFFrame", UIParent);
32 local inheritedFrames = "SecureUnitButtonTemplate,SecureHandlerStateTemplate";
33 local barTexture = "Interface\\AddOns\\OmaRF\\images\\minimalist";
34 local class = nil;
35 local party = {};
36 local raid = {};
37 local updaters = {};
38
39 local M = {};
40 OmaRaidFrame = M;
41
42 local function unitUpdate(frame)
43     -- there's no in/out of range event, have to check each frame
44     -- from FrameXML/CompactUnitFrame.lua
45     if frame.updating then
46         local inRange, checked = UnitInRange(frame.displayed);
47         if checked and not inRange then
48             frame:SetAlpha(0.55);
49         else
50             frame:SetAlpha(1);
51         end
52         CTimerAfter(0.20, updaters[frame]);
53     end
54 end
55
56 local function frameShow(frame)
57     registerEvents(frame);
58     registerUnitEvents(frame);
59     frame.updating = true;
60     CTimerAfter(0.20, updaters[frame]);
61     unitEvent(frame, "UPDATE_ALL_BARS");
62 end
63
64 local function frameHide(frame)
65     frame:UnregisterAllEvents();
66     frame.updating = nil;
67 end
68
69 local function showTooltip(secure)
70     -- only show raid frame tooltips out of combat
71     if not InCombatLockdown() then
72         GameTooltip_SetDefaultAnchor(GameTooltip, secure);
73         GameTooltip:SetUnit(secure:GetAttribute("unit"));
74     end
75 end
76
77 local function hideTooltip(secure)
78     if GameTooltip:IsOwned(secure) then GameTooltip:FadeOut() end
79 end
80
81 local function setupFrame(frame, secure, unit)
82     secure:SetAttribute("unit", unit);
83     frame:SetAttribute("unit", unit);
84     frame.unit = unit;
85     frame.displayed = unit;
86     -- hide frame to get initial frameShow call
87     frame:Hide();
88     if unit == "player" then frame.vehicle = "vehicle"
89     else frame.vehicle = unit.."pet" end
90     -- create visuals
91     secure:SetWidth(width+2);
92     secure:SetHeight(height+2);
93     frame:SetWidth(width+2);
94     frame:SetHeight(height+2);
95     frame.base = frame:CreateTexture(nil, "BACKGROUND");
96     frame.base:SetAllPoints();
97     frame.base:SetColorTexture(1, 1, 1);
98     frame.base:SetVertexColor(unpack(baseColor));
99     frame.background = frame:CreateTexture(nil, "BACKGROUND", nil, 1);
100     frame.background:SetPoint("TOPLEFT", frame, "TOPLEFT", 1, -1);
101     frame.background:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1);
102     frame.background:SetColorTexture(unpack(bgColor));
103     frame.health = frame:CreateTexture(nil, "BORDER");
104     frame.health:SetTexture(barTexture);
105     frame.health:SetPoint("TOPLEFT", frame.background, "TOPLEFT");
106     frame.health:SetPoint("BOTTOMLEFT", frame.background, "BOTTOMLEFT");
107     frame.health:SetVertexColor(unpack(healthColor));
108     frame.mana = frame:CreateTexture(nil, "BORDER");
109     frame.mana:SetPoint("TOPLEFT", frame.background, "BOTTOMLEFT", 0, 2);
110     frame.mana:SetPoint("BOTTOMLEFT", frame.background, "BOTTOMLEFT");
111     frame.mana:SetColorTexture(1, 1, 1);
112     frame.mana:Hide();
113     frame.shield = frame:CreateTexture(nil, "BORDER");
114     frame.shield:SetPoint("TOPLEFT", frame.health, "TOPRIGHT");
115     frame.shield:SetPoint("BOTTOMLEFT", frame.health, "BOTTOMRIGHT");
116     frame.shield:SetTexture(barTexture);
117     frame.shield:SetVertexColor(unpack(shieldColor));
118     frame.shield:Hide();
119     frame.shieldhl = frame:CreateTexture(nil, "ARTWORK");
120     frame.shieldhl:SetPoint("TOPLEFT", frame.background, "TOPRIGHT", -1, 0);
121     frame.shieldhl:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT", 1, 0);
122     frame.shieldhl:SetColorTexture(unpack(shieldhlColor));
123     frame.shieldhl:Hide();
124     frame.healpred = frame:CreateTexture(nil, "ARTWORK");
125     frame.healpred:SetPoint("TOPLEFT", frame.health, "TOPRIGHT");
126     frame.healpred:SetPoint("BOTTOMLEFT", frame.health, "BOTTOMRIGHT");
127     frame.healpred:SetColorTexture(unpack(healpredColor));
128     frame.healpred:Hide();
129     frame.healabsorb = frame:CreateTexture(nil, "ARTWORK");
130     frame.healabsorb:SetPoint("TOPRIGHT", frame.health, "TOPRIGHT");
131     frame.healabsorb:SetPoint("BOTTOMRIGHT", frame.health, "BOTTOMRIGHT");
132     frame.healabsorb:SetColorTexture(unpack(healabsorbColor));
133     frame.healabsorb:Hide();
134     frame.overlay = frame:CreateTexture(nil, "ARTWORK", nil, 1);
135     frame.overlay:SetPoint("TOPLEFT", frame.background, "TOPLEFT");
136     frame.overlay:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT");
137     frame.overlay:SetColorTexture(1, 1, 1);
138     frame.overlay:Hide();
139     frame.role = frame:CreateTexture(nil, "ARTWORK", nil, 2);
140     frame.role:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT", -2, 2);
141     frame.role:SetPoint("TOPLEFT", frame.background, "BOTTOMRIGHT", -14, 14);
142     frame.role:SetTexture("Interface\\LFGFRAME\\LFGROLE");
143     frame.role:Hide();
144     frame.name = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
145     frame.name:SetPoint("CENTER", frame.background, "CENTER", 0, 11);
146     frame.text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
147     frame.text:SetFont(STANDARD_TEXT_FONT, 13);
148     frame.text:SetPoint("CENTER", frame.background, "CENTER", 0, -1);
149     frame.text:Hide();
150     frame.ready = frame:CreateTexture(nil, "OVERLAY");
151     frame.ready:SetPoint("TOPLEFT", frame.background, "BOTTOMLEFT", 0, 14);
152     frame.ready:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMLEFT", 14, 0);
153     frame.ready:Hide();
154     frame.targeticon = frame:CreateTexture(nil, "OVERLAY");
155     frame.targeticon:SetPoint("CENTER", frame.background, "TOP");
156     frame.targeticon:SetWidth(12);
157     frame.targeticon:SetHeight(12);
158     frame.targeticon:SetTexture("Interface\\TARGETINGFRAME\\UI-RaidTargetingIcons");
159     frame.targeticon:Hide();
160     -- set up indicators
161     setupIndicators(frame, class);
162     -- set scripts
163     frame:SetScript("OnShow", frameShow);
164     frame:SetScript("OnHide", frameHide);
165     frame:SetScript("OnEvent", unitEvent);
166     secure:SetScript("OnEnter", showTooltip);
167     secure:SetScript("OnLeave", hideTooltip);
168     -- set up periodic updates
169     updaters[frame] = function() return unitUpdate(frame) end
170     -- set attributes
171     secure:RegisterForClicks("AnyDown");
172     for attr, val in pairs(attributes) do
173         secure:SetAttribute(attr, val);
174     end
175     -- rest give target and menu
176     secure:SetAttribute("*type1", "target");
177     secure:SetAttribute("*type2", "togglemenu");
178 end
179
180 -- vehicle toggle from Shadowed Unit Frames
181 local vehicletoggle = [=[
182     local unit = self:GetAttribute("unit");
183     if unit and newstate == "vehicle" and not UnitTargetsVehicleInRaidUI(unit) then
184         self:SetAttribute("toggleForVehicle", false);
185     else
186         self:SetAttribute("toggleForVehicle", true);
187     end
188 ]=]
189
190 local function initializeParty(parent)
191     local secure = CreateFrame("Button", "OmaPartySecure0", parent, inheritedFrames);
192     local frame = CreateFrame("Frame", "OmaParty0", parent);
193     local unit = "player";
194     secure:SetPoint("TOPLEFT", parent, "TOPLEFT");
195     frame:SetPoint("TOPLEFT", parent, "TOPLEFT");
196     setupFrame(frame, secure, unit);
197     RegisterStateDriver(frame, "visibility", "[@player,group:raid] hide; show");
198     RegisterStateDriver(secure, "visibility", "[@player,group:raid] hide; show");
199     RegisterStateDriver(secure, "vehicleui", "[vehicleui] vehicle; no");
200     secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
201     party[0] = {secure=secure, frame=frame};
202     for i = 1,4 do
203         local secure = CreateFrame("Button", "OmaPartySecure"..i, parent, inheritedFrames);
204         local frame = CreateFrame("Frame", "OmaParty"..i, parent);
205         local unit = "party"..i;
206         secure:SetPoint("TOPLEFT", party[i-1].secure, "TOPRIGHT");
207         frame:SetPoint("TOPLEFT", party[i-1].frame, "TOPRIGHT");
208         setupFrame(frame, secure, unit);
209         local visible = format("[@%s,exists,group:raid] hide; [@%s,exists] show; hide", unit, unit);
210         local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
211         RegisterStateDriver(frame, "visibility", visible);
212         RegisterStateDriver(secure, "visibility", visible);
213         RegisterStateDriver(secure, "vehicleui", vehicle);
214         secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
215         party[i] = {secure=secure, frame=frame};
216     end
217 end
218
219 local function initializeRaid(parent)
220     local secure = CreateFrame("Button", "OmaRaidSecure1", parent, inheritedFrames);
221     local frame = CreateFrame("Frame", "OmaRaid1", parent);
222     local unit = "raid1";
223     secure:SetPoint("TOPLEFT", parent, "TOPLEFT");
224     frame:SetPoint("TOPLEFT", parent, "TOPLEFT");
225     setupFrame(frame, secure, unit);
226     RegisterUnitWatch(frame);
227     RegisterUnitWatch(secure);
228     local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
229     RegisterStateDriver(secure, "vehicleui", vehicle);
230     secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
231     raid[1] = {secure=secure, frame=frame};
232     for y = 1,7 do
233         local i = y*5+1;
234         local secure = CreateFrame("Button", "OmaRaidSecure"..i, parent, inheritedFrames);
235         local frame = CreateFrame("Frame", "OmaRaid"..i, parent);
236         local unit = "raid"..i;
237         secure:SetPoint("TOPLEFT", raid[i-5].secure, "BOTTOMLEFT");
238         frame:SetPoint("TOPLEFT", raid[i-5].frame, "BOTTOMLEFT");
239         setupFrame(frame, secure, unit);
240         RegisterUnitWatch(frame);
241         RegisterUnitWatch(secure);
242         local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
243         RegisterStateDriver(secure, "vehicleui", vehicle);
244         secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
245         raid[i] = {secure=secure, frame=frame};
246     end
247     for y = 0,7 do
248         for x = 1,4 do
249             local i = y*5+x+1;
250             local secure = CreateFrame("Button", "OmaRaidSecure"..i, parent, inheritedFrames);
251             local frame = CreateFrame("Frame", "OmaRaid"..i, parent);
252             local unit = "raid"..i;
253             secure:SetPoint("TOPLEFT", raid[i-1].secure, "TOPRIGHT");
254             frame:SetPoint("TOPLEFT", raid[i-1].frame, "TOPRIGHT");
255             setupFrame(frame, secure, unit);
256             RegisterUnitWatch(frame);
257             RegisterUnitWatch(secure);
258             local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
259             RegisterStateDriver(secure, "vehicleui", vehicle);
260             secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
261             raid[i] = {secure=secure, frame=frame};
262         end
263     end
264 end
265
266 local function initializeFocus(parent)
267     local secure = CreateFrame("Button", "OmaFocusSecure", parent, inheritedFrames);
268     local frame = CreateFrame("Frame", "OmaFocus", parent);
269     local unit = "focus";
270     secure:SetPoint("BOTTOMLEFT", parent, "TOPLEFT");
271     frame:SetPoint("BOTTOMLEFT", parent, "TOPLEFT");
272     setupFrame(frame, secure, unit);
273     RegisterUnitWatch(frame);
274     RegisterUnitWatch(secure);
275     local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
276     RegisterStateDriver(secure, "vehicleui", vehicle);
277     secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
278 end
279
280 local function initialize()
281     _, class = UnitClass("player");
282     anchorX, anchorY = Settings.Character.AnchorX, Settings.Character.AnchorY;
283     attributes = Settings.Character.Clickheal;
284     CFrame:SetFrameStrata("LOW");
285     CFrame:SetPoint("CENTER", nil, "CENTER", anchorX, anchorY);
286     CFrame:SetHeight((height+2)*8);
287     CFrame:SetWidth((width+2)*5);
288     initializeParty(CFrame);
289     initializeRaid(CFrame);
290     initializeFocus(CFrame);
291 end
292
293 -- hiding Blizzard frames somewhat based on ShadowedUF
294 local function hideBlizzardRaidButton()
295     if InCombatLockdown() then return end
296     local manager = CompactRaidFrameManager;
297     -- remove show and unlock buttons from manager
298     manager.displayFrame.hiddenModeToggle:Hide();
299     manager.displayFrame.lockedModeToggle:Hide();
300 end
301
302 local hidden = false;
303 local function hideBlizzardRaid()
304     if hidden then return end
305     hidden = true;
306     local function hide()
307         if InCombatLockdown() then return end
308         CompactRaidFrameContainer:Hide();
309         local shown = CompactRaidFrameManager_GetSetting("IsShown");
310         if shown and shown ~= "0" then
311             CompactRaidFrameManager_SetSetting("IsShown", "0");
312         end
313     end
314
315     CompactRaidFrameContainer:UnregisterAllEvents();
316     -- there may still be frames created at startup getting events
317     for i=1,MAX_RAID_MEMBERS do
318         local frame = _G["CompactRaidFrame"..i];
319         if not frame then break end
320         frame:UnregisterAllEvents();
321     end
322     hooksecurefunc("CompactRaidFrameManager_UpdateShown", hide);
323     hide();
324     CompactRaidFrameContainer:HookScript("OnShow", hide);
325     hooksecurefunc("CompactRaidFrameManager_UpdateOptionsFlowContainer", hideBlizzardRaidButton);
326     hideBlizzardRaidButton();
327
328     -- hide focus frame
329     for _, frame in pairs({FocusFrame, FocusFrameToT, FocusFrameSpellBar}) do
330         frame:UnregisterAllEvents();
331         if frame.healthbar then frame.healthbar:UnregisterAllEvents() end
332         if frame.manabar then frame.manabar:UnregisterAllEvents() end
333         if frame.spellbar then frame.spellbar:UnregisterAllEvents() end
334         if frame.powerBarAlt then frame.powerBarAlt:UnregisterAllEvents() end
335         frame:Hide();
336     end
337 end
338
339 local function updateTooltipFuncs()
340     -- let MoveAnything hook these to anchor tooltip elsewhere
341     GameTooltip = _G["GameTooltip"];
342     GameTooltip_SetDefaultAnchor = _G["GameTooltip_SetDefaultAnchor"];
343 end
344
345 CFrame:RegisterEvent("PLAYER_LOGIN");
346 CFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
347 CFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
348 CFrame:SetScript("OnEvent", function(self, event, addon)
349     if event == "PLAYER_REGEN_ENABLED" then
350         -- if CompactRaidFrameManager_UpdateOptionsFlowContainer was called in combat
351         -- couldn't hide the button
352         hideBlizzardRaidButton();
353     elseif event == "PLAYER_ENTERING_WORLD" then
354         CTimerAfter(0.01, updateTooltipFuncs);
355     elseif event == "PLAYER_LOGIN" then
356         OmaRFLoadChar();
357         hideBlizzardRaid();
358         initialize();
359     end
360 end);