You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.2 KiB

local _, Cell = ...
local L = Cell.L
---@type CellFuncs
local F = Cell.funcs
---@class CellIndicatorFuncs
local I = Cell.iFuncs
local UnitGUID = UnitGUID
local UnitCanAttack = UnitCanAttack
local UnitIsOtherPlayersPet = UnitIsOtherPlayersPet
-------------------------------------------------
-- events
-------------------------------------------------
local nameplates = {
-- nameplateUnitId = true,
}
local nameplateTargets = {
-- nameplateUnitId = targetGUID,
}
local counter = {
-- friendGUID = {enemyGUID=true, ...},
}
local eventFrame = CreateFrame("Frame")
eventFrame:SetScript("OnEvent", function(self, event, ...)
self[event](self, ...)
end)
function eventFrame:NAME_PLATE_UNIT_REMOVED(unit)
nameplates[unit] = nil
nameplateTargets[unit] = nil
end
function eventFrame:NAME_PLATE_UNIT_ADDED(unit)
if not unit or not UnitCanAttack(unit, "player") or UnitIsOtherPlayersPet(unit) then return end
nameplates[unit] = true
end
local function ScanNameplates()
for _, nameplate in pairs(C_NamePlate.GetNamePlates()) do
eventFrame:NAME_PLATE_UNIT_ADDED(nameplate.namePlateUnitToken)
end
end
local function SetCount(b, count)
b.indicators.targetCounter:SetCount(count)
end
local ticker
local function StartTicker()
if ticker then ticker:Cancel() end
ticker = C_Timer.NewTicker(0.25, function()
-- reset
for _, ct in pairs(counter) do
wipe(ct)
end
-- check & calculate
for unit in pairs(nameplates) do
local target = UnitGUID(unit.."target")
if not target then -- no target
nameplateTargets[unit] = nil
elseif not Cell.vars.guids[target] then -- target doesn't exists in player's group
nameplateTargets[unit] = nil
counter[target] = nil
else
nameplateTargets[unit] = target
end
target = nameplateTargets[unit]
if target and Cell.vars.guids[target] then -- valid target exists
if not counter[target] then counter[target] = {} end -- init
counter[target][unit] = true
end
end
-- update indicator
for guid in pairs(Cell.vars.guids) do
F.HandleUnitButton("guid", guid, SetCount, counter[guid] and F.Getn(counter[guid]) or 0)
end
end)
end
local function StopTicker()
if ticker then ticker:Cancel() end
ticker = nil
end
local counterEnabled, zoneFilters = false, {}
function eventFrame:PLAYER_ENTERING_WORLD()
-- reset
wipe(nameplates)
wipe(counter)
F.IterateAllUnitButtons(function(b)
b.indicators.targetCounter:SetCount(0)
end, true)
local isIn, iType = IsInInstance()
local isValidZone
if not isIn or iType == "none" then
isValidZone = zoneFilters["outdoor"]
elseif iType == "pvp" or iType == "arena" then
isValidZone = zoneFilters["pvp"]
else -- party, raid, scenario
isValidZone = zoneFilters["pve"]
end
if counterEnabled and isValidZone then
eventFrame:RegisterEvent("NAME_PLATE_UNIT_ADDED")
eventFrame:RegisterEvent("NAME_PLATE_UNIT_REMOVED")
ScanNameplates()
StartTicker()
else
eventFrame:UnregisterEvent("NAME_PLATE_UNIT_ADDED")
eventFrame:UnregisterEvent("NAME_PLATE_UNIT_REMOVED")
StopTicker()
end
end
function I.EnableTargetCounter(enabled)
if enabled then
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
counterEnabled = true
else
eventFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
counterEnabled = false
end
eventFrame:PLAYER_ENTERING_WORLD() -- check now
-- texplore(nameplateTargets)
end
function I.UpdateTargetCounterFilters(filters, noUpdate)
if filters then zoneFilters = filters end
if not noUpdate and counterEnabled then
eventFrame:PLAYER_ENTERING_WORLD()
end
end
-------------------------------------------------
-- CreateTargetCounter
-------------------------------------------------
function I.CreateTargetCounter(parent)
local targetCounter = CreateFrame("Frame", parent:GetName().."TargetCounter", parent)
parent.indicators.targetCounter = targetCounter
targetCounter:Hide()
local text = targetCounter:CreateFontString(nil, "OVERLAY", "CELL_FONT_STATUS")
targetCounter.text = text
-- stack:SetJustifyH("RIGHT")
text:SetPoint("CENTER", 1, 0)
function targetCounter:SetFont(font, size, outline, shadow)
font = F.GetFont(font)
local flags
if outline == "None" then
flags = ""
elseif outline == "Outline" then
flags = "OUTLINE"
else
flags = "OUTLINE,MONOCHROME"
end
text:SetFont(font, size, flags)
if shadow then
text:SetShadowOffset(1, -1)
text:SetShadowColor(0, 0, 0, 1)
else
text:SetShadowOffset(0, 0)
text:SetShadowColor(0, 0, 0, 0)
end
local point = targetCounter:GetPoint(1)
text:ClearAllPoints()
if string.find(point, "LEFT") then
text:SetPoint("LEFT")
elseif string.find(point, "RIGHT") then
text:SetPoint("RIGHT")
else
text:SetPoint("CENTER")
end
targetCounter:SetSize(size+3, size+3)
end
targetCounter._SetPoint = targetCounter.SetPoint
function targetCounter:SetPoint(point, relativeTo, relativePoint, x, y)
text:ClearAllPoints()
if string.find(point, "LEFT") then
text:SetPoint("LEFT")
elseif string.find(point, "RIGHT") then
text:SetPoint("RIGHT")
else
text:SetPoint("CENTER")
end
targetCounter:_SetPoint(point, relativeTo, relativePoint, x, y)
end
function targetCounter:SetCount(n)
if n == 0 then
targetCounter:Hide()
else
targetCounter:Show()
end
text:SetText(n)
end
function targetCounter:SetColor(r, g, b)
text:SetTextColor(r, g, b)
end
end