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