libcast: add global library for cast detection

This commit is contained in:
shagu
2018-06-01 20:53:07 +02:00
parent 532a212871
commit 9eb2b97f57
4 changed files with 424 additions and 509 deletions
+301
View File
@@ -0,0 +1,301 @@
-- load pfUI environment
setfenv(1, pfUI:GetEnvironment())
--[[ libcast ]]--
-- A pfUI library that detects and saves all ongoing castbars of players, NPCs and enemies.
-- This also includes spells that usually don't have a castbar like Multi-Shot and Aimed Shot.
--
-- libcast:GetCastInfo(unit)
-- Returns all ongoing casts of a unit (name)
-- cast, start, casttime, icon, delay, channel
--
-- libcast:RegisterEventFunc(func, frame)
-- Triggers the given function `func` with `frame` as arg1,
-- whenever a new cast-event was detected
--
-- libcast:TriggerEvents()
-- Triggers all registered event functions.
--
-- libcast:AddAction(mob, spell, channel)
-- Adds a spell to the database by using pfUI's spell database
-- to obtain durations and icons
--
-- libcast:RemoveAction(mob, spell)
-- Removes the castbar of a given mob, if `spell` is an interrupt.
-- spell can be set to "INTERRUPT" to force remove an action.
--
local libcast = CreateFrame("Frame", "pfEnemyCast")
function libcast:GetCastInfo(unit)
local db = self.db[unit]
-- clean legacy values
if db and db.start + db.delay + db.casttime / 1000 > GetTime() then
return db.cast, db.start, db.casttime, db.icon, db.delay, db.channel
elseif db then
self.db[unit] = nil
end
return nil, 0, 0, "", 0, nil
end
function libcast:RegisterEventFunc(func, frame)
table.insert(self.frames, { func, frame })
end
function libcast:TriggerEvents()
for id, ft in pairs(self.frames) do ft[1](ft[2]) end
end
function libcast:AddAction(mob, spell, channel)
if L["spells"][spell] ~= nil then
local casttime = L["spells"][spell].t
local icon = L["spells"][spell].icon
self.db[mob] = {cast = spell, start = GetTime(), casttime = casttime, icon = icon, delay = 0, channel = channel}
self:TriggerEvents()
end
end
function libcast:RemoveAction(mob, spell)
if self.db[mob] and ( L["interrupts"][spell] ~= nil or spell == "INTERRUPT" ) then
self.db[mob] = nil
self:TriggerEvents()
end
end
-- Combatlog parser strings
libcast.SPELL_CAST = SanitizePattern(SPELLCASTOTHERSTART)
libcast.SPELL_PERFORM = SanitizePattern(SPELLPERFORMOTHERSTART)
libcast.SPELL_GAINS = SanitizePattern(AURAADDEDOTHERHELPFUL)
libcast.SPELL_AFFLICTED = SanitizePattern(AURAADDEDOTHERHARMFUL)
libcast.SPELL_HIT = SanitizePattern(SPELLLOGSELFOTHER)
libcast.SPELL_CRIT = SanitizePattern(SPELLLOGCRITSELFOTHER)
libcast.OTHER_SPELL_HIT = SanitizePattern(SPELLLOGOTHEROTHER)
libcast.OTHER_SPELL_CRIT = SanitizePattern(SPELLLOGCRITOTHEROTHER)
libcast.SPELL_INTERRUPT = SanitizePattern(SPELLINTERRUPTSELFOTHER)
libcast.OTHER_SPELL_INTERRUPT = SanitizePattern(SPELLINTERRUPTOTHEROTHER)
-- main data
libcast.db = {}
libcast.frames = {}
-- environmental casts
libcast:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF")
libcast:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS")
libcast:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE")
libcast:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF")
-- player spells
libcast:RegisterEvent("SPELLCAST_START")
libcast:RegisterEvent("SPELLCAST_STOP")
libcast:RegisterEvent("SPELLCAST_FAILED")
libcast:RegisterEvent("SPELLCAST_INTERRUPTED")
libcast:RegisterEvent("SPELLCAST_DELAYED")
libcast:RegisterEvent("SPELLCAST_CHANNEL_START")
libcast:RegisterEvent("SPELLCAST_CHANNEL_STOP")
libcast:RegisterEvent("SPELLCAST_CHANNEL_UPDATE")
libcast:RegisterEvent("PLAYER_TARGET_CHANGED")
libcast:SetScript("OnEvent", function()
local player = UnitName("player")
-- Fill database with player casts
if event == "PLAYER_TARGET_CHANGED" then
this:TriggerEvents()
elseif event == "SPELLCAST_START" then
this.db[player] = {cast = arg1, start = GetTime(), casttime = arg2, icon = nil, channel = nil, delay = 0}
this:TriggerEvents()
elseif event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" then
if this.db[player] and not this.db[player].channel then
this.db[player] = nil
this:TriggerEvents()
end
elseif ( event == "SPELLCAST_DELAYED" ) then
if this.db[player] then
this.db[player].delay = this.db[player].delay + arg1/1000
this:TriggerEvents()
end
elseif ( event == "SPELLCAST_CHANNEL_START" ) then
this.db[player] = {cast = arg2, start = GetTime(), casttime = arg1, icon = nil, channel = true, delay = 0}
this:TriggerEvents()
elseif event == "SPELLCAST_CHANNEL_STOP" then
if this.db[player] and this.db[player].channel then
this.db[player] = nil
this:TriggerEvents()
end
elseif ( event == "SPELLCAST_CHANNEL_UPDATE" ) then
this.db[player].delay = this.db[player].delay + this.db[player].casttime / 1000 - this.db[player].delay + this.db[player].start - GetTime() - arg1 / 1000
-- Fill database with environmental casts
elseif arg1 then
-- (.+) begins to cast (.+).
for mob, spell in string.gfind(arg1, libcast.SPELL_CAST) do
libcast:AddAction(mob, spell)
return
end
-- (.+) begins to perform (.+).
for mob, spell in string.gfind(arg1, libcast.SPELL_PERFORM) do
libcast:AddAction(mob, spell)
return
end
-- (.+) gains (.+).
for mob, spell in string.gfind(arg1, libcast.SPELL_GAINS) do
libcast:RemoveAction(mob, spell)
return
end
-- (.+) is afflicted by (.+).
for mob, spell in string.gfind(arg1, libcast.SPELL_AFFLICTED) do
libcast:RemoveAction(mob, spell)
return
end
-- Your (.+) hits (.+) for (%d+).
for spell, mob in string.gfind(arg1, libcast.SPELL_HIT) do
libcast:RemoveAction(mob, spell)
return
end
-- Your (.+) crits (.+) for (%d+).
for spell, mob in string.gfind(arg1, libcast.SPELL_CRIT) do
libcast:RemoveAction(mob, spell)
return
end
-- (.+)'s (.+) %a hits (.+) for (%d+).
for _, spell, mob in string.gfind(arg1, libcast.OTHER_SPELL_HIT) do
libcast:RemoveAction(mob, spell)
return
end
-- (.+)'s (.+) %a crits (.+) for (%d+).
for _, spell, mob in string.gfind(arg1, libcast.OTHER_SPELL_CRIT) do
libcast:RemoveAction(mob, spell)
return
end
-- You interrupt (.+)'s (.+).";
for mob, spell in string.gfind(arg1, libcast.SPELL_INTERRUPT) do
libcast:RemoveAction(mob, "INTERRUPT")
return
end
-- (.+) interrupts (.+)'s (.+).
for _, mob, spell in string.gfind(arg1, libcast.OTHER_SPELL_INTERRUPT) do
libcast:RemoveAction(mob, "INTERRUPT")
return
end
end
end)
--[[ Custom Casts
Enable Castbars for spells that don't have a castbar by default
(e.g Multi-Shot and Aimed Shot)
]]--
local aimedshot = L["customcast"]["AIMEDSHOT"]
local multishot = L["customcast"]["MULTISHOT"]
libcast.customcast = {}
libcast.customcast[strlower(aimedshot)] = function(begin)
if begin then
local duration = 3000
for i=1,32 do
if UnitBuff("player", i) == "Interface\\Icons\\Racial_Troll_Berserk" then
local berserk = 0.3
if((UnitHealth("player")/UnitHealthMax("player")) >= 0.40) then
berserk = (1.30 - (UnitHealth("player") / UnitHealthMax("player"))) / 3
end
duration = duration / (1 + berserk)
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Hunter_RunningShot" then
duration = duration / 1.4
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Warrior_InnerRage" then
duration = duration / 1.3
elseif UnitBuff("player", i) == "Interface\\Icons\\Inv_Trinket_Naxxramas04" then
duration = duration / 1.2
elseif UnitDebuff("player", i) == "Interface\\Icons\\Spell_Shadow_CurseOfTounges" then
duration = duration / 0.5
end
end
local _,_, lag = GetNetStats()
local start = GetTime() + lag/1000
libcast.db[UnitName("player")] = {cast = aimedshot, start = start, casttime = duration, icon = icon, delay = 0, channel = nil}
libcast:TriggerEvents()
else
libcast.db[UnitName("player")] = nil
libcast:TriggerEvents()
end
end
libcast.customcast[strlower(multishot)] = function(begin)
if begin then
local duration = 500
local _,_, lag = GetNetStats()
local start = GetTime() + lag/1000
libcast.db[UnitName("player")] = {cast = multishot, start = start, casttime = duration, icon = icon, delay = 0, channel = nil}
libcast:TriggerEvents()
else
libcast.db[UnitName("player")] = nil
libcast:TriggerEvents()
end
end
local function CastCustom(spell)
if not libcast:GetCastInfo(UnitName("player")) then
for custom, func in pairs(libcast.customcast) do
if strfind(strlower(spell), custom) or strlower(spell) == custom then
func(true)
end
end
end
end
hooksecurefunc("CastSpell", function(id, bookType)
if GetSpellCooldown(id, bookType) ~= 0 then
local spellName = GetSpellName(id, bookType)
CastCustom(spellName)
end
end, true)
hooksecurefunc("CastSpellByName", function(spellName, target)
for i=1,120 do
-- detect if any cast is ongoing
if IsCurrentAction(i) then
CastCustom(spellName)
return
end
end
end, true)
local scanner = CreateFrame("GameTooltip", "pfSpellScanner", nil, "GameTooltipTemplate")
scanner:SetOwner(WorldFrame, "ANCHOR_NONE")
hooksecurefunc("UseAction", function(slot, target, button)
if GetActionText(slot) or not IsCurrentAction(slot) then return end
scanner:ClearLines()
scanner:SetAction(slot)
local spellName = pfSpellScannerTextLeft1:GetText()
CastCustom(spellName)
end, true)
-- add libcast to pfUI API
pfUI.api.libcast = libcast
+110 -500
View File
@@ -1,5 +1,4 @@
pfUI:RegisterModule("castbar", function ()
local font = C.castbar.use_unitfonts == "1" and pfUI.font_unit or pfUI.font_default
local font_size = C.castbar.use_unitfonts == "1" and C.global.font_unit_size or C.global.font_size
@@ -8,6 +7,114 @@ pfUI:RegisterModule("castbar", function ()
default_border = C.appearance.border.unitframes
end
local function CreateCastbar(name, parent, unitstr, unitname)
local cb = CreateFrame("Frame", name, parent or UIParent)
CreateBackdrop(cb, default_border)
UpdateMovable(cb)
cb:SetHeight(C.global.font_size * 1.5)
cb:SetFrameStrata("MEDIUM")
cb:Hide()
cb.unitstr = unitstr
cb.unitname = unitname
cb.delay = 0
-- statusbar
cb.bar = CreateFrame("StatusBar", nil, cb)
cb.bar:SetStatusBarTexture("Interface\\AddOns\\pfUI\\img\\bar")
cb.bar:ClearAllPoints()
cb.bar:SetAllPoints(cb)
cb.bar:SetMinMaxValues(0, 100)
cb.bar:SetValue(20)
local r,g,b,a = strsplit(",", C.appearance.castbar.castbarcolor)
cb.bar:SetStatusBarColor(r,g,b,a)
-- text left
cb.bar.left = cb.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
cb.bar.left:ClearAllPoints()
cb.bar.left:SetPoint("TOPLEFT", cb.bar, "TOPLEFT", 3, 0)
cb.bar.left:SetPoint("BOTTOMRIGHT", cb.bar, "BOTTOMRIGHT", -3, 0)
cb.bar.left:SetNonSpaceWrap(false)
cb.bar.left:SetFontObject(GameFontWhite)
cb.bar.left:SetTextColor(1,1,1,1)
cb.bar.left:SetFont(font, font_size, "OUTLINE")
cb.bar.left:SetText("left")
cb.bar.left:SetJustifyH("left")
-- text right
cb.bar.right = cb.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
cb.bar.right:ClearAllPoints()
cb.bar.right:SetPoint("TOPLEFT", cb.bar, "TOPLEFT", 3, 0)
cb.bar.right:SetPoint("BOTTOMRIGHT", cb.bar, "BOTTOMRIGHT", -3, 0)
cb.bar.right:SetNonSpaceWrap(false)
cb.bar.right:SetFontObject(GameFontWhite)
cb.bar.right:SetTextColor(1,1,1,1)
cb.bar.right:SetFont(font, font_size, "OUTLINE")
cb.bar.right:SetText("right")
cb.bar.right:SetJustifyH("right")
cb:SetScript("OnUpdate", function()
if this.fadeout and this:GetAlpha() > 0 then
this:SetAlpha(this:GetAlpha()-0.05)
if this:GetAlpha() == 0 then
this:Hide()
this.fadeout = nil
end
return
end
local name = this.unitstr and UnitName(this.unitstr) or this.unitname
local spellname, start, duration, icon, delay, channel = libcast:GetCastInfo(name)
if spellname then
local max = duration / 1000
local cur = channel and duration / 1000 - delay + start - GetTime() or
GetTime() - start - delay
cur = cur > max and max or cur
cur = cur < 0 and 0 or cur
this.bar:SetValue(cur)
if delay > 0 then
delay = "|cffffaaaa" .. (channel and "-" or "+") .. round(delay,1) .. " |r "
this.bar.right:SetText(delay .. string.format("%.1f",cur) .. " / " .. round(max,1))
else
this.bar.right:SetText(string.format("%.1f",cur) .. " / " .. round(max,1))
end
this.fadeout = nil
else
this.bar:SetMinMaxValues(1,100)
this.bar:SetValue(100)
this.fadeout = 1
end
end)
function cb.OnEvent(self)
local name = self.unitstr and UnitName(self.unitstr) or self.unitname
local spellname, start, casttime, icon, delay, channel = libcast:GetCastInfo(name)
if spellname then
self.bar:SetStatusBarColor(strsplit(",", C.appearance.castbar[(channel and "channelcolor" or "castbarcolor")]))
self.bar:SetMinMaxValues(0, casttime / 1000)
self.bar.left:SetText(spellname)
self:SetAlpha(1)
self:Show()
self.fadeout = nil
else
self.bar:SetMinMaxValues(1,100)
self.bar:SetValue(100)
self.fadeout = 1
end
end
libcast:RegisterEventFunc(cb.OnEvent, cb)
return cb
end
pfUI.castbar = CreateFrame("Frame", "pfCastBar", UIParent)
-- hide blizzard
@@ -17,10 +124,7 @@ pfUI:RegisterModule("castbar", function ()
end
-- [[ pfPlayerCastbar ]] --
pfUI.castbar.player = CreateFrame("Frame", "pfPlayerCastbar", UIParent)
pfUI.castbar.player:SetFrameStrata("MEDIUM")
CreateBackdrop(pfUI.castbar.player, default_border)
pfUI.castbar.player:SetHeight(C.global.font_size * 1.5)
pfUI.castbar.player = CreateCastbar("pfPlayerCastbar", UIParent, "player")
if pfUI.uf.player then
local pspace = tonumber(C.unitframes.player.pspace)
@@ -31,307 +135,8 @@ pfUI:RegisterModule("castbar", function ()
pfUI.castbar.player:SetWidth(200)
end
UpdateMovable(pfUI.castbar.player)
pfUI.castbar.player:Hide()
pfUI.castbar.player.delay = 0
-- statusbar
pfUI.castbar.player.bar = CreateFrame("StatusBar", nil, pfUI.castbar.player)
pfUI.castbar.player.bar:SetStatusBarTexture("Interface\\AddOns\\pfUI\\img\\bar")
pfUI.castbar.player.bar:ClearAllPoints()
pfUI.castbar.player.bar:SetAllPoints(pfUI.castbar.player)
pfUI.castbar.player.bar:SetMinMaxValues(0, 100)
pfUI.castbar.player.bar:SetValue(20)
local r,g,b,a = strsplit(",", C.appearance.castbar.castbarcolor)
pfUI.castbar.player.bar:SetStatusBarColor(r,g,b,a)
-- text left
pfUI.castbar.player.bar.left = pfUI.castbar.player.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
pfUI.castbar.player.bar.left:ClearAllPoints()
pfUI.castbar.player.bar.left:SetPoint("TOPLEFT", pfUI.castbar.player.bar, "TOPLEFT", 3, 0)
pfUI.castbar.player.bar.left:SetPoint("BOTTOMRIGHT", pfUI.castbar.player.bar, "BOTTOMRIGHT", -3, 0)
pfUI.castbar.player.bar.left:SetNonSpaceWrap(false)
pfUI.castbar.player.bar.left:SetFontObject(GameFontWhite)
pfUI.castbar.player.bar.left:SetTextColor(1,1,1,1)
pfUI.castbar.player.bar.left:SetFont(font, font_size, "OUTLINE")
pfUI.castbar.player.bar.left:SetText("left")
pfUI.castbar.player.bar.left:SetJustifyH("left")
-- text right
pfUI.castbar.player.bar.right = pfUI.castbar.player.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
pfUI.castbar.player.bar.right:ClearAllPoints()
pfUI.castbar.player.bar.right:SetPoint("TOPLEFT", pfUI.castbar.player.bar, "TOPLEFT", 3, 0)
pfUI.castbar.player.bar.right:SetPoint("BOTTOMRIGHT", pfUI.castbar.player.bar, "BOTTOMRIGHT", -3, 0)
pfUI.castbar.player.bar.right:SetNonSpaceWrap(false)
pfUI.castbar.player.bar.right:SetFontObject(GameFontWhite)
pfUI.castbar.player.bar.right:SetTextColor(1,1,1,1)
pfUI.castbar.player.bar.right:SetFont(font, font_size, "OUTLINE")
pfUI.castbar.player.bar.right:SetText("right")
pfUI.castbar.player.bar.right:SetJustifyH("right")
-- events
pfUI.castbar.player:RegisterEvent("SPELLCAST_START")
pfUI.castbar.player:RegisterEvent("SPELLCAST_STOP")
pfUI.castbar.player:RegisterEvent("SPELLCAST_DELAYED")
pfUI.castbar.player:RegisterEvent("SPELLCAST_CHANNEL_START")
pfUI.castbar.player:RegisterEvent("SPELLCAST_CHANNEL_STOP")
pfUI.castbar.player:RegisterEvent("SPELLCAST_CHANNEL_UPDATE")
pfUI.castbar.player:RegisterEvent("SPELLCAST_FAILED")
pfUI.castbar.player:RegisterEvent("SPELLCAST_INTERRUPTED")
local scanner = CreateFrame("GameTooltip", "pfSpellScanner", nil, "GameTooltipTemplate")
scanner:SetOwner(WorldFrame, "ANCHOR_NONE")
local delayByLag = CreateFrame("Frame", "pfDelayCast", nil)
delayByLag.currentCast = nil
delayByLag.startTime = nil
function delayByLag:SetCast(cast)
for custom in pairs(pfUI.castbar.player.customcast) do
if strfind(strlower(cast), strlower(custom)) then
delayByLag.currentCast = custom
delayByLag.startTime = GetTime()
end
end
end
delayByLag:SetScript("OnUpdate", function()
if this.currentCast and this.startTime then
local _,_, lag = GetNetStats()
if this.startTime + lag/1000 < GetTime() then
pfUI.castbar.player.customcast[this.currentCast](true)
this.currentCast = nil
this.startTime = nil
end
end
end)
local aimedshot = L["customcast"]["AIMEDSHOT"]
local multishot = L["customcast"]["MULTISHOT"]
pfUI.castbar.player.customcast = {}
pfUI.castbar.player.customcast[aimedshot] = function(begin)
if begin then
local duration = 3000
for i=1,32 do
if UnitBuff("player", i) == "Interface\\Icons\\Racial_Troll_Berserk" then
local berserk = 0.3
if((UnitHealth("player")/UnitHealthMax("player")) >= 0.40) then
berserk = (1.30 - (UnitHealth("player") / UnitHealthMax("player"))) / 3
end
duration = duration / (1 + berserk)
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Hunter_RunningShot" then
duration = duration / 1.4
elseif UnitBuff("player", i) == "Interface\\Icons\\Ability_Warrior_InnerRage" then
duration = duration / 1.3
elseif UnitBuff("player", i) == "Interface\\Icons\\Inv_Trinket_Naxxramas04" then
duration = duration / 1.2
elseif UnitDebuff("player", i) == "Interface\\Icons\\Spell_Shadow_CurseOfTounges" then
duration = duration / 0.5
end
end
if not pfUI.castbar.player.casting then
pfUI.castbar.player:SpellcastStart(aimedshot, duration)
end
else
pfUI.castbar.player:SpellcastStop()
end
end
pfUI.castbar.player.customcast[multishot] = function(begin)
if begin then
local duration = 500
if not pfUI.castbar.player.casting then
pfUI.castbar.player:SpellcastStart(multishot, duration)
end
else
pfUI.castbar.player:SpellcastStop()
end
end
hooksecurefunc("CastSpell", function(id, bookType)
if GetSpellCooldown(id, bookType) ~= 0 then
local spellName = GetSpellName(id, bookType)
delayByLag:SetCast(spellName, true)
end
end, true)
hooksecurefunc("CastSpellByName", function(spellName, target)
for i=1,120 do
-- detect if any cast is ongoing
if IsCurrentAction(i) then
delayByLag:SetCast(spellName)
return
end
end
end, true)
hooksecurefunc("UseAction", function(slot, target, button)
if GetActionText(slot) or not IsCurrentAction(slot) then return end
scanner:ClearLines()
scanner:SetAction(slot)
local spellName = pfSpellScannerTextLeft1:GetText()
delayByLag:SetCast(spellName)
end, true)
function pfUI.castbar.player:SpellcastStart(spell, duration)
pfUI.castbar.player.delay = 0
pfUI.castbar.player.spell = spell
pfUI.castbar.player.bar.left:SetText(spell)
local r,g,b,a = strsplit(",", C.appearance.castbar.castbarcolor)
pfUI.castbar.player.bar:SetStatusBarColor(r,g,b,a)
pfUI.castbar.player.startTime = GetTime()
pfUI.castbar.player.maxValue = duration / 1000
pfUI.castbar.player.endTime = nil
pfUI.castbar.player.bar:SetMinMaxValues(0, pfUI.castbar.player.maxValue)
pfUI.castbar.player.bar:SetValue(pfUI.castbar.player.startTime)
pfUI.castbar.player.holdTime = 0
pfUI.castbar.player.casting = 1
pfUI.castbar.player.channeling = nil
pfUI.castbar.player.mode = "casting"
pfUI.castbar.player.fadeout = nil
pfUI.castbar.player:SetAlpha(1)
pfUI.castbar.player:Show()
end
function pfUI.castbar.player:SpellcastStop()
delayByLag.currentCast = nil
delayByLag.startTime = nil
if pfUI.castbar.player.casting then
pfUI.castbar.player.fadeout = 1
pfUI.castbar.player.casting = nil
pfUI.castbar.player.bar:SetMinMaxValues(1,pfUI.castbar.player.bar:GetValue())
end
end
function pfUI.castbar.player:SpellcastChannelStart(duration, spell)
pfUI.castbar.player.delay = 0
pfUI.castbar.player.spell = spell
pfUI.castbar.player.bar.left:SetText(spell)
local r,g,b,a = strsplit(",", C.appearance.castbar.channelcolor)
pfUI.castbar.player.bar:SetStatusBarColor(r,g,b,a)
pfUI.castbar.player.maxValue = nil
pfUI.castbar.player.startTime = GetTime()
pfUI.castbar.player.endTime = pfUI.castbar.player.startTime + (arg1 / 1000)
pfUI.castbar.player.duration = duration / 1000
pfUI.castbar.player.bar:SetMinMaxValues(pfUI.castbar.player.startTime, pfUI.castbar.player.endTime)
pfUI.castbar.player.bar:SetValue(pfUI.castbar.player.endTime)
pfUI.castbar.player.holdTime = 0
pfUI.castbar.player.casting = nil
pfUI.castbar.player.channeling = 1
pfUI.castbar.player.fadeout = nil
pfUI.castbar.player:SetAlpha(1)
pfUI.castbar.player:Show()
end
function pfUI.castbar.player:SpellcastChannelStop()
delayByLag.currentCast = nil
delayByLag.startTime = nil
if pfUI.castbar.player.channeling then
pfUI.castbar.player.fadeout = 1
pfUI.castbar.player.channeling = nil
if GetTime() + 0.3 < pfUI.castbar.player.endTime then
pfUI.castbar.player.bar:SetStatusBarColor(1,.5,.5,1)
pfUI.castbar.player.bar:SetMinMaxValues(1,100)
pfUI.castbar.player.bar:SetValue(100)
end
end
end
pfUI.castbar.player:SetScript("OnEvent", function ()
if ( event == "SPELLCAST_START" ) then
pfUI.castbar.player:SpellcastStart(arg1, arg2)
elseif event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" then
pfUI.castbar.player:SpellcastStop()
elseif ( event == "SPELLCAST_DELAYED" ) then
if( pfUI.castbar.player:IsShown() ) then
pfUI.castbar.player.delay = pfUI.castbar.player.delay + arg1/1000
end
elseif ( event == "SPELLCAST_CHANNEL_START" ) then
pfUI.castbar.player:SpellcastChannelStart(arg1, arg2)
elseif event == "SPELLCAST_CHANNEL_STOP" then
pfUI.castbar.player:SpellcastChannelStop()
elseif ( event == "SPELLCAST_CHANNEL_UPDATE" ) then
if ( pfUI.castbar.player:IsShown() ) then
pfUI.castbar.player.delay = pfUI.castbar.player.delay + arg1/1000
local origDuration = pfUI.castbar.player.endTime - pfUI.castbar.player.startTime
pfUI.castbar.player.endTime = GetTime() + (arg1 / 1000)
pfUI.castbar.player.startTime = pfUI.castbar.player.endTime - origDuration
pfUI.castbar.player.bar:SetMinMaxValues(pfUI.castbar.player.startTime, pfUI.castbar.player.endTime)
end
end
end)
pfUI.castbar.player:SetScript("OnUpdate", function ()
if C.castbar.player.hide_pfui == "1" then pfUI.castbar.player:Hide() return end
-- cast
if pfUI.castbar.player.casting then
local cur = GetTime() - pfUI.castbar.player.startTime - pfUI.castbar.player.delay
local max = pfUI.castbar.player.maxValue
local delay = pfUI.castbar.player.delay
pfUI.castbar.player.bar:SetValue(cur)
if cur > max then cur = max end
if delay > 0 then
delay = "|cffffaaaa+" .. round(delay,1) .. " |r "
pfUI.castbar.player.bar.right:SetText(delay .. string.format("%.1f",cur) .. " / " .. round(max,1))
else
pfUI.castbar.player.bar.right:SetText(string.format("%.1f",cur) .. " / " .. round(max,1))
end
return
-- channel
elseif pfUI.castbar.player.channeling then
local time = GetTime()
local barValue = pfUI.castbar.player.startTime + (pfUI.castbar.player.endTime - time)
pfUI.castbar.player.bar:SetValue( barValue )
local cur = pfUI.castbar.player.endTime - GetTime()
local max = pfUI.castbar.player.endTime - pfUI.castbar.player.startTime
local delay = pfUI.castbar.player.delay
if cur > max then cur = max end
if ( time > pfUI.castbar.player.endTime ) then
time = pfUI.castbar.player.endTime
end
if ( time >= pfUI.castbar.player.endTime ) then
pfUI.castbar.player.channeling = nil
pfUI.castbar.player.fadeout = 1
return
end
if delay > 0 then
delay = "|cffffaaaa-" .. round(delay,1) .. " |r "
pfUI.castbar.player.bar.right:SetText(delay .. round(cur,1))
else
pfUI.castbar.player.bar.right:SetText(round(cur,1))
end
return
-- fadeout
elseif pfUI.castbar.player.fadeout and pfUI.castbar.player:GetAlpha() > 0 then
pfUI.castbar.player:SetAlpha(pfUI.castbar.player:GetAlpha()-0.025)
if pfUI.castbar.player:GetAlpha() == 0 then
pfUI.castbar.player:Hide()
pfUI.castbar.player.fadeout = nil
end
end
end)
-- [[ pfTargetCastbar ]] --
pfUI.castbar.target = CreateFrame("Frame", "pfTargetCastbar", UIParent)
pfUI.castbar.target:SetFrameStrata("MEDIUM")
CreateBackdrop(pfUI.castbar.target, default_border)
pfUI.castbar.target:SetHeight(C.global.font_size * 1.5)
pfUI.castbar.target = CreateCastbar("pfTargetCastbar", UIParent, "target")
if pfUI.uf.target then
local pspace = tonumber(C.unitframes.target.pspace)
@@ -341,199 +146,4 @@ pfUI:RegisterModule("castbar", function ()
pfUI.castbar.target:SetPoint("CENTER", 0, -225)
pfUI.castbar.target:SetWidth(200)
end
UpdateMovable(pfUI.castbar.target)
pfUI.castbar.target:Hide()
-- statusbar
pfUI.castbar.target.bar = CreateFrame("StatusBar", nil, pfUI.castbar.target)
pfUI.castbar.target.bar:SetStatusBarTexture("Interface\\AddOns\\pfUI\\img\\bar")
pfUI.castbar.target.bar:ClearAllPoints()
pfUI.castbar.target.bar:SetAllPoints(pfUI.castbar.target)
pfUI.castbar.target.bar:SetMinMaxValues(0, 100)
pfUI.castbar.target.bar:SetValue(20)
local r,g,b,a = strsplit(",", C.appearance.castbar.castbarcolor)
pfUI.castbar.target.bar:SetStatusBarColor(r,g,b,a)
-- text left
pfUI.castbar.target.bar.left = pfUI.castbar.target.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
pfUI.castbar.target.bar.left:ClearAllPoints()
pfUI.castbar.target.bar.left:SetPoint("TOPLEFT", pfUI.castbar.target.bar, "TOPLEFT", 3, 0)
pfUI.castbar.target.bar.left:SetPoint("BOTTOMRIGHT", pfUI.castbar.target.bar, "BOTTOMRIGHT", -3, 0)
pfUI.castbar.target.bar.left:SetNonSpaceWrap(false)
pfUI.castbar.target.bar.left:SetFontObject(GameFontWhite)
pfUI.castbar.target.bar.left:SetTextColor(1,1,1,1)
pfUI.castbar.target.bar.left:SetFont(font, font_size, "OUTLINE")
pfUI.castbar.target.bar.left:SetText("left")
pfUI.castbar.target.bar.left:SetJustifyH("left")
-- text right
pfUI.castbar.target.bar.right = pfUI.castbar.target.bar:CreateFontString("Status", "DIALOG", "GameFontNormal")
pfUI.castbar.target.bar.right:ClearAllPoints()
pfUI.castbar.target.bar.right:SetPoint("TOPLEFT", pfUI.castbar.target.bar, "TOPLEFT", 3, 0)
pfUI.castbar.target.bar.right:SetPoint("BOTTOMRIGHT", pfUI.castbar.target.bar, "BOTTOMRIGHT", -3, 0)
pfUI.castbar.target.bar.right:SetNonSpaceWrap(false)
pfUI.castbar.target.bar.right:SetFontObject(GameFontWhite)
pfUI.castbar.target.bar.right:SetTextColor(1,1,1,1)
pfUI.castbar.target.bar.right:SetFont(font, font_size, "OUTLINE")
pfUI.castbar.target.bar.right:SetText("right")
pfUI.castbar.target.bar.right:SetJustifyH("right")
pfUI.castbar.target.bar:SetScript("OnUpdate", function()
if pfUI.castbar.target.drag and pfUI.castbar.target.drag:IsShown() then this:Show() return end
if UnitExists("target") and pfUI.castbar.target.casterDB[UnitName("target")] then
local spellname = pfUI.castbar.target.casterDB[UnitName("target")].cast or 0
local starttime = pfUI.castbar.target.casterDB[UnitName("target")].starttime or 0
local casttime = pfUI.castbar.target.casterDB[UnitName("target")].casttime or 0
if starttime + casttime > GetTime() then
if pfUI.castbar.target.bar then
pfUI.castbar.target.bar:SetMinMaxValues(0, casttime)
pfUI.castbar.target.bar:SetValue(GetTime() - starttime)
pfUI.castbar.target.bar.left:SetText(spellname)
pfUI.castbar.target.bar.right:SetText(round(GetTime() - starttime,1) .. " / " .. casttime)
end
else
pfUI.castbar.target.casterDB[UnitName("target")] = nil
pfUI.castbar.target:Hide()
end
else
pfUI.castbar.target:Hide()
end
end)
pfUI.castbar.target.SPELL_CAST = SanitizePattern(SPELLCASTOTHERSTART)
pfUI.castbar.target.SPELL_PERFORM = SanitizePattern(SPELLPERFORMOTHERSTART)
pfUI.castbar.target.SPELL_GAINS = SanitizePattern(AURAADDEDOTHERHELPFUL)
pfUI.castbar.target.SPELL_AFFLICTED = SanitizePattern(AURAADDEDOTHERHARMFUL)
pfUI.castbar.target.SPELL_HIT = SanitizePattern(SPELLLOGSELFOTHER)
pfUI.castbar.target.SPELL_CRIT = SanitizePattern(SPELLLOGCRITSELFOTHER)
pfUI.castbar.target.OTHER_SPELL_HIT = SanitizePattern(SPELLLOGOTHEROTHER)
pfUI.castbar.target.OTHER_SPELL_CRIT = SanitizePattern(SPELLLOGCRITOTHEROTHER)
pfUI.castbar.target.SPELL_INTERRUPT = SanitizePattern(SPELLINTERRUPTSELFOTHER)
pfUI.castbar.target.OTHER_SPELL_INTERRUPT = SanitizePattern(SPELLINTERRUPTOTHEROTHER)
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_SELF_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_SELF_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PARTY_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PARTY_BUFF")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE")
pfUI.castbar.target:RegisterEvent("CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF")
pfUI.castbar.target:RegisterEvent("PLAYER_TARGET_CHANGED")
pfUI.castbar.target.casterDB = {}
pfUI.castbar.target:SetScript("OnEvent", function()
if event == "PLAYER_TARGET_CHANGED" then
if UnitExists("target") and pfUI.castbar.target.casterDB[UnitName("target")] then
local starttime = pfUI.castbar.target.casterDB[UnitName("target")].starttime or 0
local casttime = pfUI.castbar.target.casterDB[UnitName("target")].casttime or 0
if starttime + casttime > GetTime() then
if C.castbar.target.hide_pfui == "1" then
pfUI.castbar.target:Hide()
else
pfUI.castbar.target:Show()
end
elseif pfUI.castbar.target.drag and not pfUI.castbar.target.drag:IsShown() then
pfUI.castbar.target.casterDB[UnitName("target")] = nil
pfUI.castbar.target:Hide()
end
end
elseif arg1 then
-- (.+) begins to cast (.+).
for mob, spell in string.gfind(arg1, pfUI.castbar.target.SPELL_CAST) do
pfUI.castbar.target:Action(mob, spell)
return
end
-- (.+) begins to perform (.+).
for mob, spell in string.gfind(arg1, pfUI.castbar.target.SPELL_PERFORM) do
pfUI.castbar.target:Action(mob, spell)
return
end
-- (.+) gains (.+).
for mob, spell in string.gfind(arg1, pfUI.castbar.target.SPELL_GAINS) do
pfUI.castbar.target:StopAction(mob, spell)
return
end
-- (.+) is afflicted by (.+).
for mob, spell in string.gfind(arg1, pfUI.castbar.target.SPELL_AFFLICTED) do
pfUI.castbar.target:StopAction(mob, spell)
return
end
-- Your (.+) hits (.+) for (%d+).
for spell, mob in string.gfind(arg1, pfUI.castbar.target.SPELL_HIT) do
pfUI.castbar.target:StopAction(mob, spell)
return
end
-- Your (.+) crits (.+) for (%d+).
for spell, mob in string.gfind(arg1, pfUI.castbar.target.SPELL_CRIT) do
pfUI.castbar.target:StopAction(mob, spell)
return
end
-- (.+)'s (.+) %a hits (.+) for (%d+).
for _, spell, mob in string.gfind(arg1, pfUI.castbar.target.OTHER_SPELL_HIT) do
pfUI.castbar.target:StopAction(mob, spell)
return
end
-- (.+)'s (.+) %a crits (.+) for (%d+).
for _, spell, mob in string.gfind(arg1, pfUI.castbar.target.OTHER_SPELL_CRIT) do
pfUI.castbar.target:StopAction(mob, spell)
return
end
-- You interrupt (.+)'s (.+).";
for mob, spell in string.gfind(arg1, pfUI.castbar.target.SPELL_INTERRUPT) do
pfUI.castbar.target:StopAction(mob, "INTERRUPT")
return
end
-- (.+) interrupts (.+)'s (.+).
for _, mob, spell in string.gfind(arg1, pfUI.castbar.target.OTHER_SPELL_INTERRUPT) do
pfUI.castbar.target:StopAction(mob, "INTERRUPT")
return
end
end
end)
function pfUI.castbar.target:Action(mob, spell)
if L["spells"][spell] ~= nil then
local casttime = L["spells"][spell].t / 1000
local icon = L["spells"][spell].icon
pfUI.castbar.target.casterDB[mob] = {cast = spell, starttime = GetTime(), casttime = casttime, icon = icon}
if UnitExists("target") and pfUI.castbar.target.casterDB[UnitName("target")] then
if C.castbar.target.hide_pfui == "1" then
pfUI.castbar.target:Hide()
else
pfUI.castbar.target:Show()
end
elseif pfUI.castbar.target.drag and not pfUI.castbar.target.drag:IsShown() then
pfUI.castbar.target:Hide()
end
end
end
function pfUI.castbar.target:StopAction(mob, spell)
if pfUI.castbar.target.casterDB[mob] and ( L["interrupts"][spell] ~= nil or spell == "INTERRUPT" ) then
pfUI.castbar.target.casterDB[mob] = nil
end
end
end)
+10 -9
View File
@@ -496,16 +496,17 @@ pfUI:RegisterModule("nameplates", function ()
end
-- show castbar
if healthbar.castbar and pfUI.castbar and C.nameplates["showcastbar"] == "1" and pfUI.castbar.target.casterDB[unitname] ~= nil and pfUI.castbar.target.casterDB[unitname]["cast"] ~= nil then
if pfUI.castbar.target.casterDB[unitname]["starttime"] + pfUI.castbar.target.casterDB[unitname]["casttime"] <= GetTime() then
pfUI.castbar.target.casterDB[unitname] = nil
if healthbar.castbar and pfUI.castbar and C.nameplates["showcastbar"] == "1" then
local spellname, start, casttime, icon = libcast:GetCastInfo(unitname)
casttime = casttime / 1000
if not spellname then
healthbar.castbar:Hide()
else
healthbar.castbar:SetMinMaxValues(0, pfUI.castbar.target.casterDB[unitname]["casttime"])
healthbar.castbar:SetValue(GetTime() - pfUI.castbar.target.casterDB[unitname]["starttime"])
healthbar.castbar.text:SetText(round( pfUI.castbar.target.casterDB[unitname]["starttime"] + pfUI.castbar.target.casterDB[unitname]["casttime"] - GetTime(),1))
healthbar.castbar:SetMinMaxValues(0, casttime)
healthbar.castbar:SetValue(GetTime() - start)
healthbar.castbar.text:SetText(round(start + casttime - GetTime(),1))
if C.nameplates.spellname == "1" and healthbar.castbar.spell then
healthbar.castbar.spell:SetText(pfUI.castbar.target.casterDB[unitname]["cast"])
healthbar.castbar.spell:SetText(spellname)
else
healthbar.castbar.spell:SetText("")
end
@@ -514,8 +515,8 @@ pfUI:RegisterModule("nameplates", function ()
this.debuffs[1]:SetPoint("TOPLEFT", healthbar.castbar, "BOTTOMLEFT", 0, -3)
end
if pfUI.castbar.target.casterDB[unitname]["icon"] then
healthbar.castbar.icon:SetTexture("Interface\\Icons\\" .. pfUI.castbar.target.casterDB[unitname]["icon"])
if icon then
healthbar.castbar.icon:SetTexture("Interface\\Icons\\" .. icon)
healthbar.castbar.icon:SetTexCoord(.1,.9,.1,.9)
end
end
+3
View File
@@ -39,6 +39,9 @@ api\config.lua
api\ui-widgets.lua
api\unitframes.lua
# libs
libs\libcast.lua
# modules
modules\firstrun.lua
modules\gui.lua