--[[-------------------------------------------------------------------- Ovale Spell Priority Copyright (C) 2009, 2010, 2011, 2012 Sidoine Copyright (C) 2012, 2013 Johnny C. Lam This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License in the LICENSE file accompanying this program. --]]---------------------------------------------------------------------- local addonName, addonTable = ... Ovale = LibStub("AceAddon-3.0"):NewAddon(addonTable, addonName, "AceConsole-3.0", "AceEvent-3.0", "AceSerializer-3.0", "AceTimer-3.0") --<private-static-properties> local AceGUI = LibStub("AceGUI-3.0") local L = LibStub("AceLocale-3.0"):GetLocale(addonName) local OvaleOptions = nil local format = string.format local next = next local pairs = pairs local select = select local tconcat = table.concat local tostring = tostring local unpack = unpack local wipe = table.wipe local API_GetTime = GetTime local API_IsInGroup = IsInGroup local API_RegisterAddonMessagePrefix = RegisterAddonMessagePrefix local API_SendAddonMessage = SendAddonMessage local API_UnitCanAttack = UnitCanAttack local API_UnitExists = UnitExists local API_UnitHasVehicleUI = UnitHasVehicleUI local API_UnitIsDead = UnitIsDead local OVALE_FALSE_STRING = tostring(false) local OVALE_NIL_STRING = tostring(nil) local OVALE_TRUE_STRING = tostring(true) -- Addon message prefix. local OVALE_MSG_PREFIX = addonName -- Flags used by debugging print functions. -- If "bug" flag is set, then the next frame refresh is traced. local self_bug = false -- If "traced" flag is set, then the public "trace" property is toggled before the next frame refresh. local self_traced = false -- Table of lines output using Log() or Logf() methods. local self_traceLog = {} -- Maximum length of the trace log. local OVALE_TRACELOG_MAXLINES = 4096 -- 2^14 -- Table of strings to display once per session. local self_oneTimeMessage = {} --</private-static-properties> --<public-static-properties> -- Project version number. Ovale.version = "@project-version@" -- Localization string table. Ovale.L = L --the frame with the icons Ovale.frame = nil -- Checkbox and dropdown definitions from evaluating the script. Ovale.checkBox = {} Ovale.list = {} -- Checkbox and dropdown GUI controls. Ovale.checkBoxWidget = {} Ovale.listWidget = {} -- Flag to activate tracing the function calls for the next frame refresh. Ovale.trace = false --in combat? Ovale.enCombat = false Ovale.refreshNeeded = {} Ovale.combatStartTime = nil --</public-static-properties> --Key bindings BINDING_HEADER_OVALE = addonName BINDING_NAME_OVALE_CHECKBOX0 = L["Inverser la boîte à cocher "].."(1)" BINDING_NAME_OVALE_CHECKBOX1 = L["Inverser la boîte à cocher "].."(2)" BINDING_NAME_OVALE_CHECKBOX2 = L["Inverser la boîte à cocher "].."(3)" BINDING_NAME_OVALE_CHECKBOX3 = L["Inverser la boîte à cocher "].."(4)" BINDING_NAME_OVALE_CHECKBOX4 = L["Inverser la boîte à cocher "].."(5)" --<private-static-methods> local function OnCheckBoxValueChanged(widget) -- Reflect the value change into the profile (model). local profile = OvaleOptions:GetProfile() local name = widget:GetUserData("name") profile.check[name] = widget:GetValue() Ovale:SendMessage("Ovale_CheckBoxValueChanged", name) end local function OnDropDownValueChanged(widget) -- Reflect the value change into the profile (model). local profile = OvaleOptions:GetProfile() local name = widget:GetUserData("name") profile.list[name] = widget:GetValue() Ovale:SendMessage("Ovale_ListValueChanged", name) end --</private-static-methods> --<public-static-methods> function Ovale:OnInitialize() -- Resolve module dependencies. OvaleOptions = self:GetModule("OvaleOptions") -- Register message prefix for the addon. API_RegisterAddonMessagePrefix(OVALE_MSG_PREFIX) end function Ovale:OnEnable() self:RegisterEvent("CHAT_MSG_ADDON") self:RegisterEvent("PLAYER_ENTERING_WORLD") self:RegisterEvent("PLAYER_REGEN_ENABLED") self:RegisterEvent("PLAYER_REGEN_DISABLED") self:RegisterEvent("PLAYER_TARGET_CHANGED") self.frame = AceGUI:Create(addonName .. "Frame") self:UpdateFrame() end function Ovale:OnDisable() self:UnregisterEvent("CHAT_MSG_ADDON") self:UnregisterEvent("PLAYER_ENTERING_WORLD") self:UnregisterEvent("PLAYER_REGEN_ENABLED") self:UnregisterEvent("PLAYER_REGEN_DISABLED") self:UnregisterEvent("PLAYER_TARGET_CHANGED") self.frame:Hide() end do local versionReply = {} local timer function Ovale:CHAT_MSG_ADDON(event, ...) local prefix, message, channel, sender = ... if prefix == OVALE_MSG_PREFIX then local ok, msgType, version = self:Deserialize(message) if ok then if msgType == "V" then local msg = self:Serialize("VR", self.version) local channel = API_IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT" or "RAID" API_SendAddonMessage(OVALE_MSG_PREFIX, msg, channel) elseif msgType == "VR" then versionReply[sender] = version end end end end function Ovale:VersionCheck() if not timer then wipe(versionReply) local message = self:Serialize("V", self.version) local channel = API_IsInGroup(LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT" or "RAID" API_SendAddonMessage(OVALE_MSG_PREFIX, message, channel) timer = self:ScheduleTimer("PrintVersionCheck", 3) end end function Ovale:PrintVersionCheck() if next(versionReply) then for sender, version in pairs(versionReply) do self:FormatPrint(">>> %s is using Ovale %s", sender, version) end else self:Print(">>> No other Ovale users present.") end timer = nil end end --Called when the player target change --Used to update the visibility e.g. if the user chose --to hide Ovale if a friendly unit is targeted function Ovale:PLAYER_ENTERING_WORLD() self:ClearOneTimeMessages() end function Ovale:PLAYER_TARGET_CHANGED() self.refreshNeeded.target = true self:UpdateVisibility() end function Ovale:PLAYER_REGEN_ENABLED() self.enCombat = false self:UpdateVisibility() end function Ovale:PLAYER_REGEN_DISABLED() self.enCombat = true self.combatStartTime = API_GetTime() self:UpdateVisibility() end function Ovale:IsPreloaded(moduleList) local preloaded = true for _, moduleName in pairs(moduleList) do preloaded = preloaded and self[moduleName].ready end return preloaded end function Ovale:ToggleOptions() self.frame:ToggleOptions() end function Ovale:UpdateVisibility() local visible = true local profile = OvaleOptions:GetProfile() if not self.frame.hider:IsVisible() then visible = false elseif not profile.display then visible = false else if profile.apparence.hideVehicule and API_UnitHasVehicleUI("player") then visible = false end if profile.apparence.avecCible and not API_UnitExists("target") then visible = false end if profile.apparence.enCombat and not Ovale.enCombat then visible = false end if profile.apparence.targetHostileOnly and (API_UnitIsDead("target") or not API_UnitCanAttack("player", "target")) then visible = false end end if visible then self.frame:Show() else self.frame:Hide() end end function Ovale:ResetControls() wipe(self.checkBox) wipe(self.list) end function Ovale:UpdateControls() local profile = OvaleOptions:GetProfile() -- Create a new CheckBox widget for each checkbox declared in the script. wipe(self.checkBoxWidget) for name, checkBox in pairs(self.checkBox) do local widget = AceGUI:Create("CheckBox") widget:SetLabel(checkBox.text) if profile.check[name] == nil then profile.check[name] = checkBox.checked end if profile.check[name] then widget:SetValue(profile.check[name]) end widget:SetUserData("name", name) widget:SetCallback("OnValueChanged", OnCheckBoxValueChanged) self.frame:AddChild(widget) self.checkBoxWidget[name] = widget end -- Create a new Dropdown widget for each list declared in the script. wipe(self.listWidget) for name, list in pairs(self.list) do local widget = AceGUI:Create("Dropdown") widget:SetList(list.items) if not profile.list[name] then profile.list[name] = list.default end if profile.list[name] then widget:SetValue(profile.list[name]) end widget:SetUserData("name", name) widget:SetCallback("OnValueChanged", OnDropDownValueChanged) self.frame:AddChild(widget) self.listWidget[name] = widget end end function Ovale:UpdateFrame() local profile = OvaleOptions:GetProfile() self.frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", profile.left, profile.top) self.frame:ReleaseChildren() self.frame:UpdateIcons() self:UpdateControls() self:UpdateVisibility() end function Ovale:ResetTrace() self.trace = false self_traced = false self_bug = false end function Ovale:UpdateTrace() -- If trace flag is set here, then flag that we just traced one frame. if self.trace then self_traced = true end -- If there was a bug, then enable trace on the next frame. if self_bug then self.trace = true end -- Toggle trace flag so we don't endlessly trace successive frames. if self.trace and self_traced then self_traced = false self.trace = false end end function Ovale:IsChecked(name) local widget = self.checkBoxWidget[name] return widget and widget:GetValue() end function Ovale:GetListValue(name) local widget = self.listWidget[name] return widget and widget:GetValue() end -- Set the k'th checkbox control to the specified on/off (true/false) value. function Ovale:SetCheckBox(k, on) local profile = OvaleOptions:GetProfile() for name, widget in pairs(self.checkBoxWidget) do if k == 0 then widget:SetValue(on) profile.check[name] = on break end k = k - 1 end end -- Toggle the k'th checkbox control. function Ovale:ToggleCheckBox(k) local profile = OvaleOptions:GetProfile() for name, widget in pairs(self.checkBoxWidget) do if k == 0 then local on = not widget:GetValue() widget:SetValue(on) profile.check[name] = on break end k = k - 1 end end -- Debugging methods. -- format() wrapper that turns nil arguments into tostring(nil) function Ovale:Format(...) local arg = {} for i = 1, select("#", ...) do local v = select(i, ...) if type(v) == "boolean" then arg[i] = v and OVALE_TRUE_STRING or OVALE_FALSE_STRING else arg[i] = v or OVALE_NIL_STRING end end return format(unpack(arg)) end function Ovale:FormatPrint(...) self:Print(self:Format(...)) end function Ovale:DebugPrint(flag, ...) local profile = OvaleOptions:GetProfile() if profile and profile.debug and profile.debug[flag] then self:Print("[" .. flag .. "]", ...) end end function Ovale:DebugPrintf(flag, ...) local profile = OvaleOptions:GetProfile() if profile and profile.debug and profile.debug[flag] then local addTimestamp = select(1, ...) if type(addTimestamp) == "boolean" or type(addTimestamp) == "nil" then if addTimestamp then local now = API_GetTime() self:Printf("[%s] @%f %s", flag, now, self:Format(select(2, ...))) else self:Printf("[%s] %s", flag, self:Format(select(2, ...))) end else self:Printf("[%s] %s", flag, self:Format(...)) end end end function Ovale:Error(...) self:Print("Fatal error: ", ...) self_bug = true end function Ovale:Errorf(...) self:Printf("Fatal error: %s", self:Format(...)) self_bug = true end function Ovale:Log(...) if self.trace then local N = #self_traceLog if N < OVALE_TRACELOG_MAXLINES - 1 then local output = { ... } self_traceLog[N + 1] = tconcat(output, "\t") elseif N == OVALE_TRACELOG_MAXLINES - 1 then self_traceLog[N + 1] = "WARNING: Maximum length of trace log has been reached." end end end function Ovale:Logf(...) local N = #self_traceLog if self.trace then if N < OVALE_TRACELOG_MAXLINES - 1 then self_traceLog[N + 1] = self:Format(...) elseif N == OVALE_TRACELOG_MAXLINES - 1 then self_traceLog[N + 1] = "WARNING: Maximum length of trace log has been reached." end end end -- Reset/empty the contents of the trace log. function Ovale:ClearLog() wipe(self_traceLog) end -- Return the contents of the trace log as a string. function Ovale:TraceLog() return tconcat(self_traceLog, "\n") end function Ovale:OneTimeMessage(...) local s = Ovale:Format(...) if not self_oneTimeMessage[s] then self_oneTimeMessage[s] = true end end function Ovale:ClearOneTimeMessages() wipe(self_oneTimeMessage) end function Ovale:PrintOneTimeMessages() for s in pairs(self_oneTimeMessage) do if self_oneTimeMessage[s] ~= "printed" then Ovale:Print(s) self_oneTimeMessage[s] = "printed" end end end --</public-static-methods>