--[[ ############################################################################## _____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_ # ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__ # __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____ # ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____ # ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____ # _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____ # __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ # _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_# ___\///////////___________\///___________\/////////_____\///////////_# ############################################################################## S U P E R - V I L L A I N - U I By: Munglunch # ############################################################################## ########################################################## LOCALIZED LUA FUNCTIONS ########################################################## ]]-- --[[ GLOBALS ]]-- local _G = _G; local unpack = _G.unpack; local select = _G.select; local pairs = _G.pairs; local ipairs = _G.ipairs; local type = _G.type; local tinsert = _G.tinsert; local string = _G.string; --[[ STRING METHODS ]]-- local format, gsub = string.format, string.gsub; --[[ ########################################################## GET ADDON DATA ########################################################## ]]-- local SuperVillain, L = unpack(select(2, ...)); --[[ ########################################################## Simple click2cast spell binder(sBinder by Fernir) ########################################################## ]]-- local DB = {}; DB.spells = DB.spells or {} DB.frames = DB.frames or {} DB.keys = DB.keys or {} local binder = CreateFrame("Frame", "SVUI_SpellBinder", SpellBookFrame, "ButtonFrameTemplate") binder:SetPoint("TOPLEFT", SpellBookFrame, "TOPRIGHT", 100, 0) binder:SetSize(300, 400) binder:Hide() binder.title = binder:CreateFontString(nil, "OVERLAY", "GameFontNormal") binder.title:SetPoint("TOP", binder, "TOP", 0, -5) binder.title:SetText("Click-Cast Bindings") binder.sbOpen = false binder.spellbuttons = {} binder.list = CreateFrame("ScrollFrame", "SVUI_SpellBinderSpellList", _G["SVUI_SpellBinderInset"], "UIPanelScrollFrameTemplate") binder.list.child = CreateFrame("Frame", nil, binder.list) binder.list:SetPoint("TOPLEFT", _G["SVUI_SpellBinderInset"], "TOPLEFT", 0, -5) binder.list:SetPoint("BOTTOMRIGHT", _G["SVUI_SpellBinderInset"], "BOTTOMRIGHT", -30, 5) binder.list:SetScrollChild(binder.list.child) binder.roster = {} local BoundSpell_OnEnter = function(self) self.delete:GetNormalTexture():SetVertexColor(1, 0, 0) self:SetBackdrop({bgFile = "Interface\\Buttons\\WHITE8x8"}) self:SetBackdropColor(0.2, 0.2, 0.2, 0.7) end local BoundSpell_OnLeave = function(self) self.delete:GetNormalTexture():SetVertexColor(0.8, 0, 0) self:SetBackdrop(nil) end local Temp_OnUpdate = function(self) self:UpdateAll() if self.updated then self:UnregisterEvent("PLAYER_REGEN_ENABLED") end end local SpellBindTab_OnEnter = function(self) GameTooltip:ClearLines() GameTooltip:SetOwner(self, "ANCHOR_RIGHT") GameTooltip:AddLine("Click-Cast Binding") GameTooltip:Show() end local SpellBindTab_OnLeave = function(self) GameTooltip:Hide() end local SpellBindTab_OnShow = function(self) if binder:IsVisible() then self:SetChecked(true) end local num = GetNumSpellTabs() local lastTab = _G["SpellBookSkillLineTab"..num] self:ClearAllPoints() self:SetPoint("TOPLEFT", lastTab, "BOTTOMLEFT", 0, -17) self:SetScript("OnEnter", SpellBindTab_OnEnter) self:SetScript("OnLeave", SpellBindTab_OnLeave) end local SpellBindTab_OnClick = function(self) if InCombatLockdown() then binder:Hide() return end if binder:IsVisible() then binder:Hide() binder.sbOpen = false else binder:Show() binder.sbOpen = true end binder:ToggleButtons() end local SpellBindClose_OnClick = function(self) binder:Hide() binder.sbOpen = false binder:ToggleButtons() end local _hook_SpellBookFrame_OnUpdate = function(self) if binder.sbOpen then binder:ToggleButtons() end end local _hook_SpellBookFrame_OnHide = function(self) binder:Hide() binder.sbOpen = false binder:ToggleButtons() end local addSpell = function(self, button) if binder.sbOpen then local slot = SpellBook_GetSpellBookSlot(self:GetParent()) local spellname, subtype = GetSpellBookItemName(slot, SpellBookFrame.bookType) local texture = GetSpellBookItemTexture(slot, SpellBookFrame.bookType) if spellname ~= 0 and ((SpellBookFrame.bookType == BOOKTYPE_PET) or (SpellBookFrame.selectedSkillLine > 1)) then local originalbutton = button local modifier = "" if IsShiftKeyDown() then modifier = "Shift-"..modifier end if IsControlKeyDown() then modifier = "Ctrl-"..modifier end if IsAltKeyDown() then modifier = "Alt-"..modifier end if IsHarmfulSpell(slot, SpellBookFrame.bookType) then button = format("%s%d", "harmbutton", SecureButton_GetButtonSuffix(button)) originalbutton = "|cffff2222(harm)|r "..originalbutton else button = SecureButton_GetButtonSuffix(button) end for i, v in pairs(DB.spells) do if v.spell == spellname then return end end tinsert(DB.spells, {["id"] = slot, ["modifier"] = modifier, ["button"] = button, ["spell"] = spellname, ["rank"] = rank, ["texture"] = texture, ["origbutton"] = originalbutton,}) binder:BuildSpells(false) end end end local SpellBind_OnEvent = function(self, event, ...) if event == "PLAYER_LOGIN" then DB = SVUI_Cache["Bindings"] or {} DB.spells = DB.spells or {} DB.frames = DB.frames or {} DB.keys = DB.keys or {} binder:BuildList() binder:BuildSpells(true) for i = 1, SPELLS_PER_PAGE do local parent = _G["SpellButton"..i] local button = CreateFrame("Button", "SpellButtonMask"..i, parent) button:SetID(parent:GetID()) button:RegisterForClicks("AnyDown") button:SetAllPoints(parent) button:SetScript("OnClick", addSpell) button.shine = SpellBook_GetAutoCastShine() button.shine:Show() button.shine:SetParent(button) button.shine:SetAllPoints() AutoCastShine_AutoCastStart(button.shine) button:Hide() binder.spellbuttons[i] = button end self:UnregisterEvent("PLAYER_LOGIN") elseif event == "PLAYER_ENTERING_WORLD" or event == "GROUP_ROSTER_UPDATE" or event == "ZONE_CHANGED" or event == "ZONE_CHANGED_NEW_AREA" then binder:UpdateAll() end end local function binder_BuildSpells(self, delete) local oldb local scroll = self.list.child scroll:SetPoint("TOPLEFT") scroll:SetSize(270, 300) if delete then i = 1 while _G[i.."_cbs"] do _G[i.."_fs"]:SetText("") _G[i.."_texture"]:SetTexture(0,0,0,0) _G[i.."_cbs"].checked = false _G[i.."_cbs"]:ClearAllPoints() _G[i.."_cbs"]:Hide() i = i + 1 end end for i, spell in ipairs(DB.spells) do v = spell.spell if v then local bf = _G[i.."_cbs"] or CreateFrame("Button", i.."_cbs", scroll) spell.checked = spell.checked or false if i == 1 then bf:SetPoint("TOPLEFT", scroll, "TOPLEFT", 10, -10) bf:SetPoint("BOTTOMRIGHT", scroll, "TOPRIGHT", -10, -34) else bf:SetPoint("TOPLEFT", oldb, "BOTTOMLEFT", 0, -2) bf:SetPoint("BOTTOMRIGHT", oldb, "BOTTOMRIGHT", 0, -26) end bf:EnableMouse(true) bf.tex = bf.tex or bf:CreateTexture(i.."_texture", "OVERLAY") bf.tex:SetSize(22, 22) bf.tex:SetPoint("LEFT") bf.tex:SetTexture(spell.texture) bf.tex:SetTexCoord(0.1, 0.9, 0.1, 0.9) bf.delete = bf.delete or CreateFrame("Button", i.."_delete", bf) bf.delete:SetSize(16, 16) bf.delete:SetPoint("RIGHT") bf.delete:SetNormalTexture("Interface\\BUTTONS\\UI-GroupLoot-Pass-Up") bf.delete:GetNormalTexture():SetVertexColor(0.8, 0, 0) bf.delete:SetPushedTexture("Interface\\BUTTONS\\UI-GroupLoot-Pass-Up") bf.delete:SetHighlightTexture("Interface\\BUTTONS\\UI-GroupLoot-Pass-Up") bf.delete:SetScript("OnClick", function() for j, k in ipairs(DB.spells) do if k ~= spell then k.checked = false _G[j.."_cbs"]:SetBackdropColor(0, 0, 0, 0) end end spell.checked = not spell.checked binder:DeleteSpell() end) bf:SetScript("OnEnter", BoundSpell_OnEnter) bf:SetScript("OnLeave", BoundSpell_OnLeave) bf.fs = bf.fs or bf:CreateFontString(i.."_fs", "OVERLAY", "GameFontNormal") bf.fs:SetText(spell.modifier..spell.origbutton) bf.fs:SetPoint("RIGHT", bf.delete, "LEFT", -4, 0) for frame, j in pairs(self.roster) do if frame and DB.frames[frame] then if frame:CanChangeAttribute() or frame:CanChangeProtectedState() then if frame:GetAttribute(spell.modifier.."type"..spell.button) ~= "menu" then --frame:RegisterForClicks("AnyDown") if spell.button:find("harmbutton") then frame:SetAttribute(spell.modifier..spell.button, spell.spell) frame:SetAttribute(spell.modifier.."type-"..spell.spell, "spell") frame:SetAttribute(spell.modifier.."spell-"..spell.spell, spell.spell) DB.keys[spell.modifier..spell.button] = spell.spell DB.keys[spell.modifier.."type-"..spell.spell] = "spell" DB.keys[spell.modifier.."spell-"..spell.spell] = spell.spell else frame:SetAttribute(spell.modifier.."type"..spell.button, "spell") frame:SetAttribute(spell.modifier.."spell"..spell.button, spell.spell) DB.keys[spell.modifier.."type"..spell.button] = "spell" DB.keys[spell.modifier.."spell"..spell.button] = spell.spell end end end end end bf:Show() oldb = bf end end end local function binder_BuildList(self) for frame, value in pairs(self.roster) do DB.frames[frame] = DB.frames[frame] or true end end local function binder_ToggleButtons(self) for i = 1, SPELLS_PER_PAGE do if(binder.spellbuttons[i]) then binder.spellbuttons[i]:Hide() if binder.sbOpen and SpellBookFrame.bookType ~= BOOKTYPE_PROFESSION then local slot = SpellBook_GetSpellBookSlot(binder.spellbuttons[i]:GetParent()) if slot then local spellname, subtype = GetSpellBookItemName(slot, SpellBookFrame.bookType) if spellname then binder.spellbuttons[i]:Show() end end end end end binder:BuildList() binder:BuildSpells(true) if binder:IsVisible() then binder.tab:SetChecked(true) else binder.tab:SetChecked(false) end end local function binder_DeleteSpell(self) local count = table.getn(DB.spells) for i, spell in ipairs(DB.spells) do if spell.checked then for frame, j in pairs(self.roster) do local f if frame and type(frame) == "table" then f = frame:GetName() end if f then if frame:CanChangeAttribute() or frame:CanChangeProtectedState() then if frame:GetAttribute(spell.modifier.."type"..spell.button) ~= "menu" then if spell.button:find("harmbutton") then frame:SetAttribute(spell.modifier..spell.button, nil) frame:SetAttribute(spell.modifier.."type-"..spell.spell, nil) frame:SetAttribute(spell.modifier.."spell-"..spell.spell, nil) else frame:SetAttribute(spell.modifier.."type"..spell.button, nil) frame:SetAttribute(spell.modifier.."spell"..spell.button, nil) end end end end end tremove(DB.spells, i) end end self:BuildSpells(true) end local function binder_UpdateAll(self) if InCombatLockdown() then self:SheduleUpdate() return end self:BuildList() self:BuildSpells(true) end local function binder_SheduleUpdate(self) self.updated = false if InCombatLockdown() then self:RegisterEvent("PLAYER_REGEN_ENABLED") self:SetScript("OnEvent", Temp_OnUpdate) else self:UpdateAll() end end --[[ ########################################################## LOADER ########################################################## ]]-- local function enable(frame) if type(frame) == "string" then local frameName = frame frame = _G[frameName] end if frame then binder.roster[frame] = true end end local BindableFrames = SuperVillain.SVUnit.Roster for i, v in pairs(BindableFrames) do if _G[v] then binder.roster[_G[v]] = true end end binder.BuildSpells = binder_BuildSpells binder.BuildList = binder_BuildList binder.ToggleButtons = binder_ToggleButtons binder.DeleteSpell = binder_DeleteSpell binder.UpdateAll = binder_UpdateAll binder.SheduleUpdate = binder_SheduleUpdate _G["SVUI_SpellBinderCloseButton"]:SetScript("OnClick", SpellBindClose_OnClick) hooksecurefunc("SpellBookFrame_Update", _hook_SpellBookFrame_OnUpdate) hooksecurefunc(SpellBookFrame, "Hide", _hook_SpellBookFrame_OnHide) binder:Formula409() _G["SVUI_SpellBinderInset"]:Formula409() binder:SetPanelTemplate("Action") binder.Panel:SetPoint("TOPLEFT", -18, 0) binder.Panel:SetPoint("BOTTOMRIGHT", 0, 0) binder.list:Formula409() binder.list:SetPanelTemplate("Inset") binder.tab = CreateFrame("CheckButton", nil, _G["SpellBookSkillLineTab1"], "SpellBookSkillLineTabTemplate") binder.tab:Formula409() binder.tab:SetButtonTemplate() binder.tab:SetNormalTexture("Interface\\ICONS\\Achievement_Guild_Doctorisin") binder.tab:GetNormalTexture():ClearAllPoints() binder.tab:GetNormalTexture():SetPoint("TOPLEFT", 2, -2) binder.tab:GetNormalTexture():SetPoint("BOTTOMRIGHT", -2, 2) binder.tab:GetNormalTexture():SetTexCoord(0.1, 0.9, 0.1, 0.9) binder.tab:SetScript("OnShow", SpellBindTab_OnShow) binder.tab:SetScript("OnClick", SpellBindTab_OnClick) binder.tab:Show() binder:RegisterEvent("GROUP_ROSTER_UPDATE") binder:RegisterEvent("PLAYER_ENTERING_WORLD") binder:RegisterEvent("PLAYER_LOGIN") binder:RegisterEvent("ZONE_CHANGED_NEW_AREA") binder:RegisterEvent("ZONE_CHANGED") binder:SetScript("OnEvent", SpellBind_OnEvent) local function LoadSpellBinder() for i, v in pairs(SuperVillain.SVUnit.Roster) do if _G[v] then binder.roster[_G[v]] = true end end end SuperVillain.Registry:NewScript(LoadSpellBinder)