diff --git a/ElvUI/Libraries/HealPredict/healpredict.lua b/ElvUI/Libraries/HealPredict/healpredict.lua deleted file mode 100644 index 5a03c9b..0000000 --- a/ElvUI/Libraries/HealPredict/healpredict.lua +++ /dev/null @@ -1,542 +0,0 @@ ---[[ -API: - * RegisterCallback(addon, callback) - `callback` is called whenever some heal state (new heal/ heal stop/ heal delay) changes. - callback`'s arguments will be all units affected by the change in heal state, e.g., - `callback("Tankguy", "Dpsguy")`. - - * UnregisterCallback(addon) - Remove all callbacks registered by `addon`. - - * UnitGetIncomingHeals(unit[, healer]) - Return predicted incoming heals on unit. If `healer`, only predict incoming heals from healer. -]] -local ADDON_NAME = "HealPredict" - --- Wow API -local CheckInteractDistance = CheckInteractDistance -local CreateFrame = CreateFrame -local GetInventoryItemLink = GetInventoryItemLink -local GetLocale = GetLocale -local GetNumRaidMembers = GetNumRaidMembers -local GetSpellInfo = GetSpellInfo -local GetTime = GetTime -local SendAddonMessage = SendAddonMessage -local strjoin = strjoin -local strsplit = strsplit -local UIParent = UIParent -local UnitBuff = UnitBuff -local UnitCanAssist =UnitCanAssist -local UnitCastingInfo = UnitCastingInfo -local UnitChannelInfo = UnitChannelInfo -local UnitHealth = UnitHealth -local UnitHealthMax = UnitHealthMax -local UnitInRaid = UnitInRaid -local UnitName = UnitName -local UnitIsDeadOrGhost = UnitIsDeadOrGhost - --- Addon message constants: -local HEALSTOP = "HealStop" -local HEALDELAY = "HealDelay" -local HEAL = "Heal" -local SEP = "/" - --- Localize spell names: -local BEACON_OF_LIGHT -do - local locales = { - deDE = "Flamme des Glaubens", - enUS = "Beacon of Light", - esES = "Señal de la Luz", - esMX = "Señal de la Luz", - frFR = "Guide de lumière", - itIT = "Faro di Luce", - koKR = "빛의 봉화", - ptBR = "Foco de Luz", - ruRU = "Частица Света", - zhCN = "圣光道标", - zhTW = "聖光信標", - } - - BEACON_OF_LIGHT = locales[GetLocale()] or locales.enUS -end - -local CHAIN_HEAL -do - local locales = { - deDE = "Kettenheilung", - enUS = "Chain Heal", - esES = "Sanación en cadena", - esMX = "Sanación en cadena", - frFR = "Salve de guérison", - itIT = "Catena di Guarigione", - koKR = "연쇄 치유", - ptBR = "Cura Encadeada", - ruRU = "Цепное исцеление", - zhCN = "治疗链", - zhTW = "治療鍊", - } - - CHAIN_HEAL = locales[GetLocale()] or locales.enUS -end - -local PRAYER_OF_HEALING -do - local locales = { - deDE = "Gebet der Heilung", - enUS = "Prayer of Healing", - esES = "Rezo de curación", - esMX = "Rezo de sanación", - frFR = "Prière de soins", - itIT = "Preghiera di Cura", - koKR = "치유의 기원", - ptBR = "Prece de Cura", - ruRU = "Молитва исцеления", - zhCN = "治疗祷言", - zhTW = "治療禱言", - } - - PRAYER_OF_HEALING = locales[GetLocale()] or locales.enUS -end - -local PRAYER_OF_PRESERVATION = "Prayer of Preservation" - -local TRANQUILITY -do - local locales = { - deDE = "Gelassenheit", - enUS = "Tranquility", - esES = "Tranquilidad", - esMX = "Tranquilidad", - frFR = "Tranquillité", - itIT = "Tranquillità", - koKR = "평온", - ptBR = "Tranquilidade", - ruRU = "Спокойствие", - zhCN = "宁静", - zhTW = "寧靜", - } - - TRANQUILITY = locales[GetLocale()] or locales.enUS -end - -local SMART_HEALS = { } -SMART_HEALS[TRANQUILITY] = 5 -SMART_HEALS[PRAYER_OF_PRESERVATION] = 5 -SMART_HEALS[CHAIN_HEAL] = 3 - --- Addon locals -local player = UnitName("player") -local heals, callbacks, cache, gear_string = { }, { }, { }, "" -local is_healing, beacon_info, current_target - --- API functions -local healpredict = CreateFrame("Frame") -function healpredict.UnitGetIncomingHeals(unit, healer) - if UnitIsDeadOrGhost(unit) then return 0 end - - local name = UnitName(unit) - - if not heals[name] then - return 0 - end - - local sumheal, time = 0, GetTime() - - for sender, amount in pairs(heals[name]) do - if amount[2] <= time then - heals[name][sender] = nil - elseif not healer or sender == healer then - sumheal = sumheal + amount[1] - end - end - - return sumheal -end - -function healpredict.RegisterCallback(addon, callback) - callbacks[addon] = callback -end - -function healpredict.UnregisterCallback(addon) - callbacks[addon] = nil -end - --- Private functions -local function UpdateCache(spell, heal) - --[[ - cache total of all heals and number of casts - for calculating a rolling average of the heal - ]] - local heal = tonumber(heal) - - if not cache[spell] then - cache[spell] = {heal, 1} - else - cache[spell][1] = cache[spell][1] + heal - cache[spell][2] = cache[spell][2] + 1 - end -end - -local function handleCallbacks(...) - for _, v in pairs(callbacks) do - v(...) - end -end - -local function Heal(sender, target, amount, duration) - heals[target] = heals[target] or { } - heals[target][sender] = {amount, GetTime() + duration / 1000} - - handleCallbacks(target) -end - -local function HealStop(sender) - local affected = { } - for target, _ in pairs(heals) do - for tsender in pairs(heals[target]) do - if sender == tsender then - heals[target][tsender] = nil - table.insert(affected, target) - end - end - end - - handleCallbacks(unpack(affected)) -end - -local function HealDelay(sender, delay) - if type(delay) ~= "string" then - local delay = delay / 1000 - local affected = { } - for target, _ in pairs(heals) do - for tsender, amount in pairs(heals[target]) do - if sender == tsender then - amount[2] = amount[2] + delay - table.insert(affected, target) - end - end - end - handleCallbacks(unpack(affected)) - end -end - -local function SendHealMsg(msg) - SendAddonMessage(ADDON_NAME, msg, "RAID") - SendAddonMessage(ADDON_NAME, msg, "BATTLEGROUND") -end - -local function max(targets) - local currentmax = -1 - local raidname - - for name, pct in pairs(targets) do - if pct > currentmax then - currentmax = pct - raidname = name - end - end - - return raidname -end - -local function BeaconTarget() - if beacon_info then - local beacon_target, endtime = unpack(beacon_info) - if endtime > GetTime() then - beacon_info = nil - else - return beacon_target - end - end -end - -local function GroupHeal(amount, casttime) - local partyN, partyname, beacon_found - local beacon_target = BeaconTarget() - - for i=1,4 do - partyN = "party"..i - - if CheckInteractDistance(partyN, 4) then - partyname = (UnitName(partyN)) - if beacon_target and partyname == beacon_target then - beacon_found = true - Heal(player, partyname, amount * 1.4, casttime) - SendHealMsg(strjoin(SEP, HEAL, partyname, amount * 1.4, casttime)) - elseif partyname then - Heal(player, partyname, amount, casttime) - SendHealMsg(strjoin(SEP, HEAL, partyname, amount, casttime)) - end - end - end - - if beacon_target and not beacon_found then - Heal(player, beacon_target, amount * .4, casttime) - SendHealMsg(strjoin(SEP, HEAL, beacon_target, amount * .4, casttime)) - end - - Heal(player, player, amount, casttime) - SendHealMsg(strjoin(SEP, HEAL, player, amount, casttime)) -end - -local function SmartHeal(amount, casttime, n) - if not UnitInRaid("player") then - return GroupHeal(amount, casttime) - end - - local beacon_target = BeaconTarget() - local beacon_found - - local healthpct, currentmax - local pcts = { } - local raidN, raidname - - for i=1,GetNumRaidMembers() do - raidN = "raid"..i - - if not UnitIsDeadOrGhost(raidN) and CheckInteractDistance(raidN, 4) then - raidname = (UnitName(raidN)) - healthpct = UnitHealth(raidN) / UnitHealthMax(raidname) - - if #pcts < n then - pcts[raidname] = healthpct - - if not currentmax or healthpct > pcts[currentmax] then - currentmax = raidname - end - - elseif healthpct < pcts[currentmax] then - pcts[currentmax] = nil - pcts[raidname] = healthpct - currentmax = max(pcts) - end - end - end - - for target, _ in pairs(pcts) do - if beacon_target and target == beacon_target then - beacon_found = true - Heal(player, target, amount * 1.4, casttime) - SendHealMsg(strjoin(SEP, HEAL, target, amount * 1.4, casttime)) - else - Heal(player, target, amount, casttime) - SendHealMsg(strjoin(SEP, HEAL, target, amount, casttime)) - end - end - - if beacon_target and not beacon_found then - Heal(player, beacon_target, amount * .4, casttime) - SendHealMsg(strjoin(SEP, HEAL, beacon_target, amount * .4, casttime)) - end -end - -local function UnitByName(name) - if name == player then - return "player" - end - - local unit - - if UnitInRaid("player") then - for i=1,GetNumRaidMembers() do - unit = "raid"..i - - if (UnitName(unit)) == name then - return unit - end - end - end - - for i=1,4 do - unit = "party"..i - - if (UnitName(unit)) == name then - return unit - end - end -end - --- Message passing -healpredict:RegisterEvent("CHAT_MSG_ADDON") -healpredict:SetScript("OnEvent", function(_, _, prefix, msg, _, sender) - if prefix == ADDON_NAME then - local command, target_or_delay, amount, casttime = strsplit(SEP, msg) - if command == HEALSTOP then - HealStop(sender) - elseif command == HEAL then - Heal(sender, target_or_delay, amount, casttime) - elseif command == HEALDELAY then - HealDelay(sender, target_or_delay) - end - end -end) - --- Reset cache on skill or inventory change -local resetcache = CreateFrame("Frame") -resetcache:RegisterEvent("SKILL_LINES_CHANGED") -resetcache:RegisterEvent("UNIT_INVENTORY_CHANGED") -resetcache:SetScript("OnEvent", function(_, event, player) - if player ~= "player" then - return - end - - if event == "UNIT_INVENTORY_CHANGED" then - local gear = "" - for id = 1, 18 do - gear = gear .. (GetInventoryItemLink("player",id) or "") - end - - if gear == gear_string then - return - end - - gear_string = gear - end - - -- reset cache - cache = { } -end) - ---Event handling ----------------- -local eventhandler = CreateFrame("Frame", ADDON_NAME .. "EventHandler", UIParent) - -eventhandler:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") -function eventhandler.COMBAT_LOG_EVENT_UNFILTERED(_, subevent, _, sourcename, _, _, destname, _, spellid, spellname, _, amount) - if sourcename ~= player then return end - - if subevent == "SPELL_HEAL" then - local _, rank = GetSpellInfo(spellid) - local spellrank = spellname..(rank or "") - UpdateCache(spellrank, amount) - - if spellname == TRANQUILITY then - -- Need to re-acquire tranq targets - HealStop(player) - SendHealMsg(HEALSTOP) - - local _, _, _, _, starttime, endtime = UnitChannelInfo("player") - if starttime ~= nil and endtime ~= nil then - local casttime = endtime - starttime - - local total, casts = unpack(cache[spellrank]) - local amount = total / casts - - SmartHeal(amount, casttime, 5) - is_healing = true - end - end - elseif spellname == BEACON_OF_LIGHT then - if subevent == "SPELL_AURA_APPLIED" then - local unit = UnitByName(destname) - - if not unit then - return - end - - for i=1,40 do - local buff, _, _, _, _, endtime = UnitBuff(unit, i) - if buff == BEACON_OF_LIGHT then - beacon_info = {destname, endtime} - break - end - end - - elseif subevent == "SPELL_AURA_REMOVED" then - beacon_info = nil - end - end -end - -eventhandler:RegisterEvent("UNIT_SPELLCAST_SENT") -function eventhandler.UNIT_SPELLCAST_SENT(unit, _, _, target) - if unit == "player" then - if target == "" then - current_target = UnitCanAssist("player", "target") and UnitName("target") or player - else - current_target = target - end - end -end - -eventhandler:RegisterEvent("UNIT_SPELLCAST_START") -function eventhandler.UNIT_SPELLCAST_START(unit) - if unit ~= "player" then return end - - local spell, rank, _, _, starttime, endtime = UnitCastingInfo("player") - if not spell then - spell, rank, _, _, starttime, endtime = UnitChannelInfo("player") - end - local casttime = endtime - starttime - local spellrank = spell..(rank or "") - - if cache[spellrank] then - local total, casts = unpack(cache[spellrank]) - local amount = total / casts - - if spell == PRAYER_OF_HEALING then - GroupHeal(amount, casttime) - elseif SMART_HEALS[spell] then - SmartHeal(amount, casttime, SMART_HEALS[spell]) - else - local beacon_target = BeaconTarget() - - if beacon_target then - if beacon_target ~= current_target then - Heal(player, current_target, amount, casttime) - SendHealMsg(strjoin(SEP, HEAL, current_target, amount, casttime)) - - Heal(player, beacon_target, amount * .4, casttime) - SendHealMsg(strjoin(SEP, HEAL, beacon_target, amount * .4, casttime)) - else - Heal(player, beacon_target, amount * 1.4, casttime) - SendHealMsg(strjoin(SEP, HEAL, beacon_target, amount * 1.4, casttime)) - end - else - Heal(player, current_target, amount, casttime) - SendHealMsg(strjoin(SEP, HEAL, current_target, amount, casttime)) - end - end - - is_healing = true - end -end - -eventhandler:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START") -eventhandler.UNIT_SPELLCAST_CHANNEL_START = eventhandler.UNIT_SPELLCAST_START - -eventhandler:RegisterEvent("UNIT_SPELLCAST_FAILED") -function eventhandler.UNIT_SPELLCAST_FAILED(unit) - if is_healing and unit == "player" then - HealStop(player) - SendHealMsg(HEALSTOP) - is_healing = nil - end -end - -eventhandler:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED") -eventhandler.UNIT_SPELLCAST_INTERRUPTED = eventhandler.UNIT_SPELLCAST_FAILED - -eventhandler:RegisterEvent("UNIT_SPELLCAST_STOP") -eventhandler.UNIT_SPELLCAST_STOP = eventhandler.UNIT_SPELLCAST_FAILED - -eventhandler:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP") -eventhandler.UNIT_SPELLCAST_CHANNEL_STOP = eventhandler.UNIT_SPELLCAST_FAILED - -eventhandler:RegisterEvent("UNIT_SPELLCAST_DELAYED") -function eventhandler.UNIT_SPELLCAST_DELAYED(unit, delay) - if is_healing and unit == "player" then - HealDelay(player, delay) - SendHealMsg(strjoin(SEP, HEALDELAY, delay)) - end -end - -eventhandler:SetScript("OnEvent", function(_, event, ...) - local handler = eventhandler[event] - if handler then - handler(...) - end -end) - -_G[ADDON_NAME] = healpredict \ No newline at end of file diff --git a/ElvUI/Libraries/Load_Libraries.xml b/ElvUI/Libraries/Load_Libraries.xml index bdfa113..5254bba 100644 --- a/ElvUI/Libraries/Load_Libraries.xml +++ b/ElvUI/Libraries/Load_Libraries.xml @@ -18,7 +18,6 @@