-- Adapted from TokensWorth/ShaguTweaks-mods (MIT, original copyright GryllsAddons). local _G = ShaguTweaks.GetGlobalEnv() local T = ShaguTweaks.T local API = ShaguTweaks.API local module = ShaguTweaks:register({ title = T["Unit Frame Abbreviated Names"], description = T["Abbreviates long target and target-of-target names."], expansions = { ["vanilla"] = true, ["tbc"] = nil }, category = T["Unit Frames"], enabled = nil, }) module.enable = function(self) local maxLength = 15 local cache = {} local function AbbrevWord(word) return string.sub(word, 1, 1) .. ". " end local function GetShortName(unit) local name = UnitName(unit) if not name then cache[unit] = nil return end local cached = cache[unit] if cached and cached.raw == name then return cached.short end local short = name if strlen(short) > maxLength then short = string.gsub(short, "^(%S+) ", AbbrevWord) end if strlen(short) > maxLength then short = string.gsub(short, "(%S+) ", AbbrevWord) end cache[unit] = { raw = name, short = short, } return short end local function GetNameText(frame) if not frame then return end if frame.name then return frame.name end if frame.GetName then local frameName = frame:GetName() if frameName then return _G[frameName .. "Name"] end end end local function UpdateFrame(frame, unit) local text = GetNameText(frame) local name = GetShortName(unit) if not text or not name then return end -- Avoid forcing a FontString update when the displayed value is already -- correct. This matters most for the 250 ms target-of-target fallback. if not text.GetText or text:GetText() ~= name then text:SetText(name) end end local function UpdateTarget() UpdateFrame(TargetFrame, "target") end local function UpdateTargetTarget() if TargetofTargetFrame then UpdateFrame(TargetofTargetFrame, "targettarget") end end local function EventValid(name) return API.eventutils and _G.C_EventUtils and _G.C_EventUtils.IsEventValid and _G.C_EventUtils.IsEventValid(name) end local events = CreateFrame("Frame") events:RegisterEvent("PLAYER_ENTERING_WORLD") events:RegisterEvent("PLAYER_TARGET_CHANGED") local hasUnitTarget = EventValid("UNIT_TARGET") local hasUnitName = EventValid("UNIT_NAME_UPDATE") if hasUnitTarget then events:RegisterEvent("UNIT_TARGET") end if hasUnitName then events:RegisterEvent("UNIT_NAME_UPDATE") end events:SetScript("OnEvent", function() if event == "PLAYER_ENTERING_WORLD" or event == "PLAYER_TARGET_CHANGED" then UpdateTarget() UpdateTargetTarget() elseif event == "UNIT_TARGET" then if arg1 == "target" then UpdateTargetTarget() end elseif event == "UNIT_NAME_UPDATE" then if arg1 == "target" then UpdateTarget() elseif arg1 == "targettarget" then UpdateTargetTarget() end end end) -- Vanilla has no UNIT_TARGET event for target-of-target changes. Prefer the -- ClassicAPI native ticker so Lua only runs at the required 250 ms cadence, -- instead of entering a Lua OnUpdate handler every rendered frame. Keep the -- old throttled path only for older environments without C_Timer.NewTicker. if not hasUnitTarget then local function UpdateTargetTargetFallback() if UnitName("targettarget") then UpdateTargetTarget() end end if _G.C_Timer and type(_G.C_Timer.NewTicker) == "function" then _G.C_Timer.NewTicker(.25, UpdateTargetTargetFallback) else local fallback = CreateFrame("Frame") fallback.elapsed = 0 fallback:SetScript("OnUpdate", function() this.elapsed = this.elapsed + (arg1 or 0) if this.elapsed < .25 then return end this.elapsed = 0 UpdateTargetTargetFallback() end) end end UpdateTarget() UpdateTargetTarget() end