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