9c6a1a5 - Don't show healthstone warning if you are dead
[wowui.git] / OmaGtfo / Gtfo.lua
1 -- Gtfo.lua
2 local _;
3 local print, tonumber, pairs = print, tonumber, pairs;
4 local format = string.format;
5 local strsplit = strsplit;
6 local UnitGUID = UnitGUID;
7 local UnitExists, UnitIsUnit = UnitExists, UnitIsUnit;
8 local UnitBuff, UnitDebuff = UnitBuff, UnitDebuff;
9 local UnitGroupRolesAssigned = UnitGroupRolesAssigned;
10 local PlaySoundFile = PlaySoundFile;
11 local playerGuid, guids;
12 local playerTank;
13 local printAll = false;
14 local frame = CreateFrame("Frame");
15 frame:Hide();
16
17 local sounds = {
18     "Interface\\Addons\\OmaGtfo\\sounds\\alarmbuzzer.ogg",
19     "Interface\\Addons\\OmaGtfo\\sounds\\alarmbeep.ogg",
20     "Interface\\Addons\\OmaGtfo\\sounds\\alarmdouble.ogg",
21     "Interface\\Addons\\OmaGtfo\\sounds\\alarmbuzz.ogg",
22 };
23 local taken = OmaGTFO.DmgTaken;
24 local caused = OmaGTFO.DmgDone;
25 local environs = {
26     ["Drowning"] = sounds[1],
27     ["Fatigue"] = sounds[1],
28     ["Lava"] = sounds[2],
29     ["Fire"] = sounds[2],
30     ["Slime"] = sounds[2],
31 };
32
33 local function mobId(guid)
34     local mob, _, _, _, _, id = strsplit("-", guid);
35     if mob and (mob == "Creature" or mob == "Vehicle" or mob == "Pet") then
36         return tonumber(id);
37     end
38     return nil;
39 end
40
41 -- negatingIgnoreTime-like functionality not implemented
42 local events = {
43     ["SPELL_DAMAGE"] = function(event, source, spellid, spellname, _, arg1, arg2)
44         if (event == "SPELL_AURA_APPLIED" or event == "SPELL_AURA_APPLIED_DOSE" or
45             event == "SPELL_AURA_REFRESH") and arg1 ~= "DEBUFF" then
46             return;
47         elseif taken[spellid] then
48             -- TODO uncomment checks when they're in use
49             local spell = taken[spellid];
50             local sound = spell.sound;
51             if spell.eventType and spell.eventType ~= event then return end
52             --if (event == "SPELL_MISSED" or event == "SPELL_PERIODIC_MISSED") and not spell.always then return end
53             if spell.negatingDebuff and UnitDebuff("player", spell.negatingDebuff) then return end
54             --if spell.negatingBuff and UnitBuff("player", spell.negatingBuff) then return end
55             --if spell.affirmingDebuff and not UnitDebuff("player", spell.affirmingDebuff) then return end
56             --if spell.mobs and source and not spell.mobs[mobId(source)] then return end
57             --if spell.ignoreSelf and source == playerGuid then return end
58             if spell.tankMechanic and playerTank then
59                 if spell.tankMechanic == true then return end
60                 sound = spell.tankMechanic;
61             end
62             if spell.applicationOnly then
63                 if event ~= "SPELL_AURA_APPLIED" and event ~= "SPELL_AURA_APPLIED_DOSE" and
64                     event ~= "SPELL_AURA_REFRESH" then
65                     return;
66                 elseif spell.minStacks and (event ~= "SPELL_AURA_APPLIED_DOSE" or
67                     not arg2 or arg2 <= spell.minStacks) then
68                     return;
69                 end
70             end
71             if spell.minDamage then
72                 local damage = tonumber(arg1) or 0;
73                 if damage < spell.minDamage then return end
74             end
75             if spell.multipleHitsTime then -- only alarm if multiple hits within a certain time
76                 local now, prevHit = GetTime(), spell.prevHit;
77                 spell.prevHit = now;
78                 if prevHit then
79                     if now - prevHit > spell.multipleHitsTime then
80                         return;
81                     end
82                 else
83                     return;
84                 end
85             end
86
87             return PlaySoundFile(sounds[sound], "SFX");
88         --elseif printAll then -- TODO uncomment when wanting to print all non-tracked events
89         --    return print(event, spellid, spellname);
90         end
91     end,
92     ["ENVIRONMENTAL_DAMAGE"] = function(_, _, env)
93         if environs[env] then return PlaySoundFile(environs[env], "SFX") end
94     end,
95 };
96 events["SPELL_MISSED"] = events["SPELL_DAMAGE"];
97 events["SPELL_PERIODIC_DAMAGE"] = events["SPELL_DAMAGE"];
98 events["SPELL_PERIODIC_MISSED"] = events["SPELL_DAMAGE"];
99 events["SPELL_ENERGIZE"] = events["SPELL_DAMAGE"];
100 events["SPELL_INSTAKILL"] = events["SPELL_DAMAGE"];
101 events["SPELL_AURA_APPLIED"] = events["SPELL_DAMAGE"];
102 events["SPELL_AURA_APPLIED_DOSE"] = events["SPELL_DAMAGE"];
103 events["SPELL_AURA_REFRESH"] = events["SPELL_DAMAGE"];
104
105 local function clog(_, event, _, sourceGuid, _, _, _, destGuid, _, _, _, ...)
106     -- TODO vehicle support?
107     if destGuid == playerGuid then
108         if events[event] then return events[event](event, sourceGuid, ...) end
109     elseif sourceGuid == playerGuid and event == "SPELL_DAMAGE" then
110         local spellid = ...;
111         if guids[destGuid] and caused[spellid] then
112             return PlaySoundFile(sounds[caused[spellid]], "SFX");
113         end
114     end
115 end
116
117 local function updateGuids()
118     guids = {};
119     if IsInGroup() then
120         if IsInRaid() then
121             for i = 1,40 do
122                 local unit = format("raid%i", i);
123                 if not UnitExists(unit) then break end
124                 if not UnitIsUnit(unit, "player") then
125                     guids[UnitGUID(unit)] = true;
126                 end
127             end
128         else
129             for i = 1,4 do
130                 local unit = format("party%i", i);
131                 if not UnitExists(unit) then break end
132                 guids[UnitGUID(unit)] = true;
133             end
134         end
135     end
136 end
137
138 local function updateRole()
139     playerTank = UnitGroupRolesAssigned("player") == "TANK";
140 end
141
142 local realEvents = {
143     ["COMBAT_LOG_EVENT_UNFILTERED"] = clog,
144     ["GROUP_ROSTER_UPDATE"] = updateGuids,
145     ["PLAYER_ROLES_ASSIGNED"] = updateRole,
146     ["MIRROR_TIMER_START"] = function(timer, _, _, scale)
147         if (timer == "EXHAUSTION" and scale < 0) then
148             return PlaySoundFile(sounds[1], "SFX");
149         end
150     end,
151 };
152 local function handleEvent(frame, event, ...)
153     realEvents[event](...);
154 end
155
156 frame:SetScript("OnEvent", function()
157     frame:UnregisterAllEvents();
158     playerGuid = UnitGUID("player");
159     updateGuids();
160     updateRole();
161     frame:SetScript("OnEvent", handleEvent);
162     frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
163     frame:RegisterEvent("GROUP_ROSTER_UPDATE");
164     frame:RegisterEvent("PLAYER_ROLES_ASSIGNED");
165     frame:RegisterEvent("MIRROR_TIMER_START");
166 end);
167 frame:RegisterEvent("PLAYER_LOGIN");
168
169 SLASH_OMAGTFO1 = "/omag";
170 function SlashCmdList.OMAGTFO(msg, editBox)
171     printAll = not printAll;
172     print("printAll", printAll)
173 end