SFrames.Focus = {} local function Trim(text) if type(text) ~= "string" then return "" end text = string.gsub(text, "^%s+", "") text = string.gsub(text, "%s+$", "") return text end function SFrames.Focus:EnsureDB() if not SFramesDB then SFramesDB = {} end if not SFramesDB.Focus then SFramesDB.Focus = {} end return SFramesDB.Focus end function SFrames.Focus:Initialize() self:EnsureDB() end function SFrames.Focus:GetFocusName() if UnitExists and UnitExists("focus") and UnitName then local name = UnitName("focus") if name and name ~= "" then return name end end local db = self:EnsureDB() if db.name and db.name ~= "" then return db.name end return nil end function SFrames.Focus:SetFromTarget() if not UnitExists or not UnitExists("target") then return false, "NO_TARGET" end local name = UnitName and UnitName("target") if not name or name == "" then return false, "INVALID_TARGET" end local db = self:EnsureDB() db.name = name db.level = UnitLevel and UnitLevel("target") or nil local _, classToken = UnitClass and UnitClass("target") db.class = classToken local usedNative = false if FocusUnit then local ok = pcall(function() FocusUnit("target") end) if not ok then ok = pcall(function() FocusUnit() end) end if ok and UnitExists and UnitExists("focus") then usedNative = true end end return true, name, usedNative end function SFrames.Focus:Clear() if ClearFocus then pcall(ClearFocus) end local db = self:EnsureDB() db.name = nil db.level = nil db.class = nil return true end function SFrames.Focus:Target() if UnitExists and UnitExists("focus") then TargetUnit("focus") return true, "NATIVE" end local name = self:GetFocusName() if not name then return false, "NO_FOCUS" end if TargetByName then TargetByName(name, true) else return false, "NO_TARGETBYNAME" end if UnitExists and UnitExists("target") and UnitName and UnitName("target") == name then return true, "NAME" end return false, "NOT_FOUND" end function SFrames.Focus:Cast(spellName) local spell = Trim(spellName) if spell == "" then return false, "NO_SPELL" end if UnitExists and UnitExists("focus") then CastSpellByName(spell) if SpellIsTargeting and SpellIsTargeting() then SpellTargetUnit("focus") end if SpellIsTargeting and SpellIsTargeting() then SpellStopTargeting() return false, "BAD_TARGET" end return true, "NATIVE" end local focusName = self:GetFocusName() if not focusName then return false, "NO_FOCUS" end local hadTarget = UnitExists and UnitExists("target") local prevName = hadTarget and UnitName and UnitName("target") or nil local onFocus = false if hadTarget and prevName == focusName then onFocus = true elseif TargetByName then TargetByName(focusName, true) if UnitExists and UnitExists("target") and UnitName and UnitName("target") == focusName then onFocus = true end end if not onFocus then return false, "FOCUS_NOT_FOUND" end CastSpellByName(spell) if SpellIsTargeting and SpellIsTargeting() then SpellTargetUnit("target") end if SpellIsTargeting and SpellIsTargeting() then SpellStopTargeting() if hadTarget and prevName and prevName ~= focusName and TargetLastTarget then TargetLastTarget() end return false, "BAD_TARGET" end if hadTarget and prevName and prevName ~= focusName and TargetLastTarget then TargetLastTarget() end return true, "NAME" end