PHP код:
local function ToNumber(v)
local r = tonumber(v)
if not r then return 0 end
return r
end
local function IsTable(o)
return type(o) == "table"
end
local function RegisterCD(self, srcGUID, srcName, srcFlags, spellID)
local cd1, cd2 = spellBase[spellID][2], spellBase[spellID][3]
local cd = (cd2 > 0 and cd2 or cd1)
local spellName, spellRank, spellIcon = GetSpellInfo(spellID)
if not self.cds[srcGUID] then self.cds[srcGUID] = {} end
local currentTime = GetTime()
self.cds[srcGUID][spellID] = {
cdID = srcGUID .. "|" .. spellID,
flags = srcFlags,
srcName = srcName,
srcGUID = srcGUID,
spellID = spellID,
spellName = spellName,
spellRank = spellRank,
spellIcon = spellIcon,
startTime = currentTime,
endTime = currentTime + cd,
duration = cd,
elapsed = 0,
remaining = cd
}
end
local function RemoveCDsByUnitSpell(self, unitGUID, spellID)
if(not unitGUID) then return; end
local unitCDs = self.cds[unitGUID];
if(not unitCDs) then return; end
if(spellID) then
unitCDs[spellID] = nil;
elseif(spellID == -1) then
self.cds[unitGUID] = nil;
end
end
local function Time(time)
return (time <= 1 and string.format("%.1f", time))
or (time <= 60 and string.format("%d", time))
or (string.format("%d", time))
end
local function ClearTracker(self, trackerID)
local timers = self.trackers[trackerID].timers;
for k, v in ipairs(timers) do
if(IsTable(v) and v.timer and v.timer.trackerID) then
v.timer:Hide();
timers[k].timer = nil;
end
end
end
local function CreateTimer(self)
local t = CreateFrame("frame", nil, self);
t:Hide();
t:SetFrameStrata("MEDIUM");
t:SetClampedToScreen(true);
t:SetScript("OnUpdate", function()
uf.OnTimerUpdate(self)
end)
-- icon
local ti = t:CreateTexture(nil, "BORDER");
ti:SetAllPoints();
ti:SetTexCoord(0.07, 0.93, 0.07, 0.93);
t.icon = ti;
-- cooldown
local cooldown = CreateFrame("Cooldown", nil, t, "CooldownFrameTemplate");
cooldown:SetReverse(false);
cooldown:SetAllPoints();
t.cooldown = cooldown;
local tt = cooldown:CreateFontString(nil, "OVERLAY");
tt:SetFont("Fonts\\FRIZQT__.TTF", 11, "OUTLINE")
tt:SetPoint("BOTTOM", t, 0, 1);
tt:SetJustifyH("RIGHT");
t.timeText = tt;
return t;
end
local function GetTrinketIcon(unit)
if(UnitFactionGroup(unit) == "Horde") then
return "Interface\\Icons\\INV_Jewelry_TrinketPVP_02";
else
return "Interface\\Icons\\INV_Jewelry_TrinketPVP_01";
end
end
local function RemainingComparer(a, b)
return b.remaining < a.remaining
end
local function ReversalRemainingComparer(b, a)
return b.remaining > a.remaining
end
local function UpdateTracker(self, trackerID)
if(not trackerID) then
return;
end
ClearTracker(self, trackerID);
local timers = self.trackers[trackerID].timers;
local tabID = self.np[trackerID].tabID;
local activeGUID = (ToNumber(tabID) < 0 and self.trackers[trackerID].unitGUID or tabID);
local unitCDs = self.cds[activeGUID];
if(not unitCDs) then
return;
end
local unitClass = self.np[trackerID].units[activeGUID].unitClass;
local tmp = {}
local m = 1
local lastCD = {spellID = -1, time = -1}
for spellID, cd in pairs(unitCDs) do
if IsTable(cd) then
local currentTime = GetTime()
cd.elapsed = currentTime - cd.startTime
cd.remaining = cd.duration - cd.elapsed
if (cd.remaining and cd.remaining > 0 and cd.remaining <= self.timeLimit) then
if (cd.startTime > lastCD.time) then
lastCD.spellID = spellID
lastCD.time = cd.startTime
end
tmp[m] = {spellID = spellID, remaining = ToNumber(cd.remaining)}
m = m + 1
end
end
if m > self.numButtons then break end
end
table.sort(tmp, function(a, b) if self.growRight then return RemainingComparer(a, b) else return ReversalRemainingComparer(a, b) end end)
if not IsTable(timers) or #timers < self.numButtons then
self.trackers[trackerID].timers = {}
end
local numRows = 1;
for i, v in ipairs(tmp) do
local timers = self.trackers[trackerID].timers;
if(not timers[i]) then
timers[i] = {}
end
local cd = unitCDs[v.spellID]
if(cd and cd.cdID) then
if(not timers[i].timer) then
timers[i].timer = CreateTimer(self)
end
local t = timers[i].timer;
CooldownFrame_SetTimer(timers[i].timer.cooldown, cd.startTime, cd.duration, 1)
t.trackerID = trackerID;
t.cdID = cd.cdID;
t.unitGUID = cd.srcGUID;
t.spellID = cd.spellID;
t:SetParent(self)
t:ClearAllPoints();
t:SetSize(self.iconSize, self.iconSize);
t:SetAlpha(self.alpha);
if(i == 1) then
t:SetPoint(self.point, self.relativeFrame, self.relativePoint, self.ofsx, self.ofsy)
else
local row = ceil(i / self.rows);
if(numRows ~= row) then
if self.growY=="UP" then
t:SetPoint("BOTTOM", timers[i-self.rows].timer, "TOP", 0, self.space)
elseif self.growY=="DOWN" then
t:SetPoint("TOP", timers[i-self.rows].timer, "BOTTOM", 0, -self.space)
end
numRows = row;
else
if self.growX=="LEFT" then
t:SetPoint("RIGHT", timers[i-1].timer, "LEFT", -self.space, 0)
elseif self.growX=="RIGHT" then
t:SetPoint("LEFT", timers[i-1].timer, "RIGHT", self.space, 0)
end
end
end
local spellID = cd.spellID;
if(spellID == 59752 or spellID == 42292 or spellID == 7744) then
t.icon:SetTexture(GetTrinketIcon(trackerID));
else
t.icon:SetTexture(cd.spellIcon);
end
t.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
t:Show();
end
end
end
function uf.OnTimerUpdate(frame)
local u = frame.cds[this.unitGUID];
if not u or not u[this.spellID] then
UpdateTracker(frame, this.trackerID)
return
end
local cd = u[this.spellID]
local currentTime = GetTime()
if currentTime > cd.endTime then
UpdateTracker(frame, this.trackerID)
return
end
cd.elapsed = currentTime - cd.startTime
cd.remaining = cd.duration - cd.elapsed
this.timeText:SetText(Time(cd.remaining))
end
local function Update(self, event)
if event=="COMBAT_LOG_EVENT_UNFILTERED" then
if UnitExists(self.unit) and arg3~=UnitGUID(self.unit) then return end
local isPlayer = (arg3 == UnitGUID("player")) and false;
if(not arg3 or isPlayer) then return; end
-- print(self.unit)
if(arg2 == "SPELL_CAST_SUCCESS") then
if not arg9 then return end
local cdID = arg3 .. "." .. arg9
local spell = spellBase[arg9]
if not IsTable(spell) then return end
if IsTable(spell[4]) then
for _, sid in pairs(spell[4]) do
if v == -1 then
RemoveCDsByUnitSpell(self, arg3, -1)
do break end
elseif sid > 0 then
RemoveCDsByUnitSpell(self, arg3, sid)
end
end
end
RegisterCD(self, arg3, arg4, arg5, arg9)
for k, v in pairs(self.trackers) do
local tabID = self.np[k].tabID
local activeGUID = (ToNumber(tabID) < 0) and v.unitGUID or tabID
-- print(arg3, activeGUID)
if arg3 == activeGUID then
UpdateTracker(self, k)
end
end
end
elseif event=="UNIT_SPELLCAST_SUCCEEDED" then
if arg1~=self.unit then return end
local unitGUID = UnitGUID(arg1)
local playerGUID = UnitGUID("player")
if not unitGUID or unitGUID == playerGUID or UnitIsDead(arg1) or not UnitPlayerControlled(arg1) then
return
end
for k, _ in pairs(self.np) do
local currentTime = GetTime()
local _, unitClass = UnitClass(arg1)
local unitName = UnitName(arg1)
self.np[k].units[unitGUID] = {unitGUID = unitGUID, unitName = unitName, unitClass = unitClass, time = currentTime}
end
-- print(arg1, unitGUID)
self.trackers[arg1].unitGUID = unitGUID
UpdateTracker(self, arg1)
end
end
local function Enable(self)
if not self.trackers then return end
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", Update)
self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED", Update)
end
local function Disable(self)
if not self.trackers then return end
self:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED", Update)
self:UnregisterEvent("UNIT_SPELLCAST_SUCCEEDED", Update)
end
uf:AddElement('Cooldowns', Update, Enable, Disable)