From 8bdf839b68b524ba5e72d8f200f2db6aff41e647 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 13 Jan 2021 15:50:31 +0100 Subject: [PATCH] Revision 38 --- Clickzz.toc | 9 ++ core.lua | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++++ icon2.tga | Bin 0 -> 2938 bytes license.txt | 6 + pack.xml | 3 + 5 files changed, 364 insertions(+) create mode 100644 Clickzz.toc create mode 100644 core.lua create mode 100644 icon2.tga create mode 100644 license.txt create mode 100644 pack.xml diff --git a/Clickzz.toc b/Clickzz.toc new file mode 100644 index 0000000..050e9dc --- /dev/null +++ b/Clickzz.toc @@ -0,0 +1,9 @@ +## Interface: 90002 +## Title: Clickzz +## Notes: Clickcasting for Unitframes +## Author: Rilgamon +## X-WoWI-ID: 25674 +## SavedVariables: ClickzzDB +## OptionalDeps: Ace3, BrokerPack, zzLibCommon +Common\common.xml +pack.xml diff --git a/core.lua b/core.lua new file mode 100644 index 0000000..7768ee4 --- /dev/null +++ b/core.lua @@ -0,0 +1,346 @@ +local name, addon = ... +local parentName = addon['parentName'] or "BrokerPack" +local childName = "Clickzz" +local eventframe, db +local options +local mouseButtons = {'LEFTBUTTON','RIGHTBUTTON','WHEEL',"BUTTON4","BUTTON5"} +local buffButtons = {'Buff1', 'Buff2', 'Buff3', 'Debuff1', 'Debuff2', 'Debuff3', 'DispelDebuff1', 'DispelDebuff2', 'DispelDebuff3'} +local modifier = {'none','shift','ctrl','alt'} +ClickCastFrames = ClickCastFrames or {} +local castFrames = ClickCastFrames +local ldbicon = LibStub:GetLibrary("LibDBIcon-1.0") +local function OnClick(self, button) + if(IsShiftKeyDown() and button == "LeftButton") then + addon['db']['global']['ldbicons'][childName]['hide'] = not addon['db']['global']['ldbicons'][childName]['hide'] + if(ldbicon) then + if(addon['db']['global']['ldbicons'][childName]['hide']) then + ldbicon:Hide(childName) + else + ldbicon:Show(childName) + end + end + else + if(InterfaceOptionsFrame:IsVisible() and not InCombatLockdown()) then + InterfaceOptionsFrame:Hide() + else + InterfaceOptionsFrame_OpenToCategory(childName) + InterfaceOptionsFrame_OpenToCategory(childName) -- Twice because of a bug in InterfaceOptionsFrame_OpenToCategory + end + end +end +local function unregisterAttrs(frame) + if(InCombatLockdown()) then return end + frame['attrs'] = frame['attrs'] or {} + for key, value in pairs(frame['attrs']) do + frame:SetAttribute(key, nil) + frame['attrs'][key] = nil + end +end +local function registerAttrs(frame, key, value) + if(InCombatLockdown()) then + eventframe:RegisterEvent("PLAYER_REGEN_ENABLED") + else + frame['attrs'] = frame['attrs'] or {} + frame['attrs'][key] = value + frame:SetAttribute(key, value) + end +end +local function buffButtonSwitch(frame, switch) + local fName = frame:GetName() + if(strsub(fName, 1, 7) == 'Compact') then + for i = 1, #buffButtons do + local buffBtn = _G[format("%s%s", fName, buffButtons[i])] + + if(buffBtn) then + buffBtn:EnableMouse(switch) + end + end + end +end +local function disableFrame(frame) + if(InCombatLockdown()) then + eventframe:RegisterEvent("PLAYER_REGEN_ENABLED") + return + end + if(frame and frame:GetName()) then + buffButtonSwitch(frame, true) + unregisterAttrs(frame) + registerAttrs(frame, 'type', 'target') + registerAttrs(frame, 'type2', 'togglemenu') + castFrames[frame] = nil + end +end +local function gettype(v, attr) + local r = format("%s%i", attr, v['btn']) + if(v['mod'] ~= 1) then + r = format("%s-%s", v['modName'],r) + end + return r +end +local function regAtt(frame, v) + registerAttrs(frame, gettype(v, 'harmbutton'), format("nuke%i",v['btn'])) + registerAttrs(frame, gettype(v, 'helpbutton'), format("heal%i",v['btn'])) + registerAttrs(frame, gettype(v, 'type-heal'), 'spell') + registerAttrs(frame, gettype(v, 'type-nuke'), 'spell') + registerAttrs(frame, gettype(v, 'spell-nuke'), v['spell']) + registerAttrs(frame, gettype(v, 'spell-heal'), v['dualSpell'] and v['spellHeal'] or v['spell']) +end +local function enableFrame(frame, force) + if(InCombatLockdown()) then + eventframe:RegisterEvent("PLAYER_REGEN_ENABLED") + if(not force) then return end + end + if(frame['unit'] and strsub(frame['unit'], 1, 9) == 'nameplate') then +-- print('nameplate ignored', frame['unit']) + return + end + if(frame and frame:GetName()) then +-- disableFrame(frame) + buffButtonSwitch(frame, false) + frame:RegisterForClicks('AnyDown') + for k,v in pairs(db['clicks']) do + regAtt(frame, v) + end + castFrames[frame] = true + end +end +local firstRun = true +local function enableAllFrames() + local frames = { + 'PlayerFrame', 'TargetFrame', 'TargetFrameToT', 'FocusFrame', 'FocusFrameToT','PetFrame', + } + for n = 1, 8 do + for i = 1, 5 do + if(n==1) then + if(i<5) then + frames[#frames + 1] = format("PartyMemberFrame%i",i) + frames[#frames + 1] = format("PartyMemberFrame%iPetFrame",i) + frames[#frames + 1] = format("Boss%iTargetFrame",i) + end + frames[#frames + 1] = format("CompactPartyFrameMember%i",i) + end + frames[#frames + 1] = format("CompactRaidGroup%iMember%i",n,i) + end + end + for k,v in pairs(castFrames) do + if(v) then + local frame = k:GetName() + local skip = false + for n = 1, #frames do + if(frames[n] == frame) then + skip = true + break + end + end + if(not skip and frame) then + frames[#frames + 1] = frame + end + end + end + for k,frame in ipairs(frames) do + if(_G[frame]) then + enableFrame(_G[frame], firstRun) + else +-- print('skip', frame) + end + end + firstRun = false +end +local function OnText(message) + addon:OnText(childName, message) +end +local racialSpells = {} -- Beta returns the old names with C_AlliedRaces.GetAllRacialAbilitiesFromID(raceID) +local function isRacialSpell(spellIcon) -- Replace spellIcon with spellName once the bug is fixed +-- local name, rank, icon, castTime, minRange, maxRange, spellId = GetSpellInfo(spellName) +-- print('start',spellIcon) + for k, v in pairs(racialSpells) do +-- local nameR, rankR, iconR, castTimeR, minRangeR, maxRangeR, spellIdR = GetSpellInfo(v) +-- print(' check',v) + if(v == spellIcon) then + return true + end + end +end +local function buildRacialSpells() + local raceName, raceFile, raceID = UnitRace('player') + local res = C_AlliedRaces.GetAllRacialAbilitiesFromID(raceID) + if(res) then + for k, v in pairs(C_AlliedRaces.GetAllRacialAbilitiesFromID(raceID)) do + if(type(v)=='table') then + if(not IsPassiveSpell(v['name']) and not isRacialSpell(v['icon'])) then -- Replace icon with name once the bug is fixed + racialSpells[#racialSpells+1] = v['icon'] -- Replace icon with name once the bug is fixed + end + end + end + end +end +local function buildSpells(self) + if(InCombatLockdown()) then + self:RegisterEvent("PLAYER_REGEN_ENABLED") + return + end + local currentSpec = GetSpecialization() + if currentSpec then + local classInfo = C_CreatureInfo.GetClassInfo(select(3,UnitClass('player'))) + buildRacialSpells() + local _, currentSpecName = GetSpecializationInfo(currentSpec) + db['spells'] = {} + for tabIndex = 1, GetNumSpellTabs() do + local name, texture, offset, numEntries, isGuild, offspecID = GetSpellTabInfo(tabIndex) + if(name == currentSpecName or name == classInfo['className'] or tabIndex==1) then + if(offspecID==0) then + for spellIndex = offset + 1, offset + numEntries do + local skillType, special = GetSpellBookItemInfo(spellIndex, BOOKTYPE_SPELL) + if(skillType=="SPELL" and not IsPassiveSpell(spellIndex, BOOKTYPE_SPELL)) then + local spellName, spellSubName = GetSpellBookItemName(spellIndex, BOOKTYPE_SPELL) +-- print(spellName,spellSubName,IsPassiveSpell(spellIndex, BOOKTYPE_SPELL), raceSpell) + local _, _, icon = GetSpellInfo(spellName) + if(not IsAttackSpell(spellName)) then + if(spellSubName and spellSubName ~= "" and not isRacialSpell(icon)) then +-- db['spells'][special] = format("%s (%s)",spellName, spellSubName) + db['spells'][special] = spellName -- Fix when C_AlliedRaces.GetAllRacialAbilitiesFromID(raceID) returns a value + else + db['spells'][special] = spellName + end + end + end + end + end + end + end + end +end +local function OnEvent(self, event, ...) + if(event=="PLAYER_REGEN_ENABLED") then + self:UnregisterEvent(event) + elseif(event=="SPELLS_CHANGED") then + if(InCombatLockdown()) then + self:RegisterEvent("PLAYER_REGEN_ENABLED") + return + end + end + buildSpells(self) + enableAllFrames(self) +end +local function selectSpell() + local list = {} + for spellId, spellName in pairs(db['spells']) do + list[#list+1] = spellName + end + sort(list) + return list +end +local function remClick(pref) + addon['options']['args'][childName]['args']["activeClickzz"]['args'][pref[#pref-1]] = nil + db['clicks'][strsub(pref[#pref-1],10)] = nil + enableAllFrames() +end +local function buildMenu() + for clickName,v in pairs(db['clicks']) do + local grpName = v['btnName'] + if(v['mod'] ~= 1) then + grpName = format("%s-%s",strupper(v['modName']),grpName) + end + local clickNum = format("clickNum-%s", clickName) + local grp = addon:AddConfigEntry(childName,"group",clickNum,grpName,'',1,true,nil,nil,nil,options['args'][childName]['args']["activeClickzz"]) + addon:AddConfigEntry(childName,"execute","remClick",'Remove',nil,9,remClick,nil,nil,nil,options['args'][childName]['args']["activeClickzz"]['args'][clickNum]) + addon:AddConfigEntry(childName,"toggle","dualSpell",'Dual','Set damage and heal spell on same click',8,nil,nil,nil,nil,options['args'][childName]['args']["activeClickzz"]['args'][clickNum]) + addon:AddConfigEntry(childName,"select","selectSpell",'Spell',nil,7,selectSpell,nil,nil,nil,options['args'][childName]['args']["activeClickzz"]['args'][clickNum]) + if(v['dualSpell']) then + addon:AddConfigEntry(childName,"select","selectSpell2",'Heal Spell',nil,6,selectSpell,nil,nil,nil,options['args'][childName]['args']["activeClickzz"]['args'][clickNum]) + end + end +end +local function getPref(pref) + if(pref[#pref] == 'selectSpell') then + local spells = selectSpell() + for i = 1, #spells do + if(spells[i] == db['clicks'][strsub(pref[#pref-1],10)]['spell']) then + return i + end + end + elseif(pref[#pref] == 'selectSpell2') then + local spells = selectSpell() + for i = 1, #spells do + if(spells[i] == db['clicks'][strsub(pref[#pref-1],10)]['spellHeal']) then + return i + end + end + elseif(pref[#pref] == 'dualSpell') then + return db['clicks'][strsub(pref[#pref-1],10)]['dualSpell'] + end + return db[pref[#pref]] +end +local function setPref(pref,value) + if(pref[#pref] == 'selectSpell') then + local spells = selectSpell() + db['clicks'][strsub(pref[#pref-1],10)]['spell'] = spells[value] + enableAllFrames() + return + elseif(pref[#pref] == 'dualSpell') then + db['clicks'][strsub(pref[#pref-1],10)]['dualSpell'] = value + buildMenu() + return + elseif(pref[#pref] == 'selectSpell2') then + local spells = selectSpell() + db['clicks'][strsub(pref[#pref-1],10)]['spellHeal'] = spells[value] + enableAllFrames() + return + end + db[pref[#pref]] = value +end +local function addClick() + local mod = tonumber(db['modType']) + if(modifier[mod]) then + local clickName + local btn = tonumber(db['mouseButton']) + local mf = modifier[mod] + local bf = mouseButtons[btn] + if(mod==1) then + clickName = format("type%i", btn) + else + clickName = format("%s-type%i", mf, btn) + end + db['clicks'][clickName] = db['clicks'][clickName] or { + ['btnName'] = bf, + ['modName'] = mf, + ['btn'] = btn, + ['mod'] = mod + } + buildMenu() + enableAllFrames() + end +end +hooksecurefunc("CompactUnitFrame_SetUnit", function(self, unit) + if(InCombatLockdown()) then + eventframe:RegisterEvent("PLAYER_REGEN_ENABLED") + return + end + if(unit and not castFrames[self]) then + enableFrame(self,firstRun) + end +end) +do + + addon['preloads'][#addon['preloads'] + 1] = function(...) + db = addon['db']['profile'][childName] + eventframe = addon:RegisterFunc({'SPELLS_CHANGED','GROUP_ROSTER_UPDATE','RAID_ROSTER_UPDATE'},"OnEvent",OnEvent) + enableAllFrames() + end + addon:startup(name, childName, function() + options = addon:InitConfig(childName, true, { + ['type'] = "launcher", -- 'data source | launcher' + ['OnClick'] = OnClick + }, getPref, setPref) + addon:AddConfigEntry(childName,"select","modType",'Modifier',nil,1,modifier,nil,nil,nil,options['args'][childName]) + addon:AddConfigEntry(childName,"select","mouseButton",'Mousebutton',nil,2,mouseButtons,nil,nil,nil,options['args'][childName]) + addon:AddConfigEntry(childName,"execute","addClick",'Add Click',nil,3,addClick,nil,nil,nil,options['args'][childName]) + addon:AddConfigEntry(childName,"group","activeClickzz","Active Clickzz",'',4,true,nil,nil,nil,options['args'][childName]) + buildMenu() + end, nil, { + ['spells'] = {}, + ['clicks'] = {}, + ['mouseButton'] = 1, + ['modType'] = 1 + }) +end \ No newline at end of file diff --git a/icon2.tga b/icon2.tga new file mode 100644 index 0000000000000000000000000000000000000000..89d81ab198a55f18c8ec01d9774b53c83745188a GIT binary patch literal 2938 zcmYk830zgj6~^z|SRNp<$STBWuv)4$#;vBfB)H%L2!R;XR6|5#LlqZ5L=ZHnUZ)VOpbCo2m)cYGC z@t?_70Ft`W*I8BN*MDTSzss7M4_pqgosMI7LCvnA#@}ThXToSPykd^CQuf&_94*Uz z94#t*ox>{U^uNNUtMqe0&4+_luY`&aW(6*Ls|)s=WT>?)dSXDm}U3bgj9r=8{TsrFSx(;Uzo^&YxQ zR{#wO2K4Df;5*7xtpzGpQQ_oDXi>2msOHFbalq*$gJpdJUKIZWXV*-CAdy%^vR2lJ zm-kRGxt~el`*vkVJ?+u5aT@gBE(dC9P)khNN^C{RXOK`XWNPD~)|ZCja*QX0J^c#u zCt9mzlH3^`nrOSNU{XK)7(E#{{&%2!9Z<3oI1-GFIQ$7zU4;>N+FXq%r;p)9-eSY3 zk(fv6D%wXue=z@AbhWpvzwj6m!!BA%yIo2PO6g zq3cKtdY(MuYWY*VxOD~HIUi$_nAhO&QsCGM^y~{l%>s9j)OBFI%?O!oBm{ECS}Ak? zV*UN0Ne+0H>IWRtD4y?&fbPkEAu@~DYZuVH)0ZNgGeX*I zAag#D=8bbpMj(5%wT`4Q|Ho#G?0YbKj5VGm&HxTG{3%{^-9Clb-1S^-CqyL>+d}NN zmvb8Ip!KfV=!~C$%u!az7-`AWWWDZjH`neR-se$;&j8??&wz|2#3gtTm$eSMXHS?A z0{7d+Ms#nQWSCPUX)5$IDxTgS^lsnnZl+eJxm%3e?QWs}Y0(hIi0PW-jd;Y2Au2sm zMlneR>Oup$qsJTO)QEc*h#8CK`EH=MF7=P*Lrr%5!7TX8A?EmXsXMc2JFspn5bQ@Zn~gsum;SPSU&FH->bTY>v+T&WQ2I(G`Xh<7+gceU_G#0cC99t^>! zj=yorTiWOyZf5BCoRcT_08v~~{8S*(7y8>b4MHkes5*~_#0=~eQ{q+&L&Yq+-)^uo z5pz9-y9|U##%;w=VEGU{2p)tKH!YIi(tfV~=bNUn+XtHB@lx)oA|2Qs#1$q5u<-8u zY}kj|Aehf%44`QED^Zm!Dn`?my%LsiGRMGBBf$p+pK`)%Y#W3g_31{)9 z&*OF2d$1DPt{KLa!UE~6AO2;Hd}@$s3vhrSQ(?Yoyq$X5Mte1`_}Fs?IZTL3Rx&Tm z0+v`lt38h`CxXDQLn&MIB{Sn?x=6TvgDK8&6;_Tz^GsWiq$hElCe}vTFVrk$Kix^iUBMewF2uH_SfUL(cHcB(iIxB^O ztuE0;%}U^{)6xiBY2@}QGnfKJDLkNqF@#oRz7B1@LMX@8*cpPZh5flw704-~kz^#g zNDC=sZ666gd5eQ!kbk`nG?j40b-8q_&1D2qcsKKksM-HIy8SAz4G#0lTN%T0ss4Re8OKLB@`0cVOR(Ri3=*l-9qkp|Qqcs-b{EyNck z6Q31@=ZjpiZ2)W0Lb@JdZXh#0+ydX0aTN8QR=`1K#iw$&b}oMY}X__$9!VpS&#A z(7#y#?F>N!(0r1u9QeMFXOzt^ESuO=?LLZBXYq#S6Hf6W*fJkieeDosDG8zCaC1p1 zYs8Dam~by|aJW6*UWvAknEs_K^Lsq2&ig>?j|@vOqgkKN`fFrioGXt(|(E>;j(0&!+I%fCE8 zT&gn6T|dM17eF8Di%YX?d!^dQ9wMu35>oy6I!vrUBtgk|3p@#(z!{E@P79uZv&>=txLcU+|BOQ==fwX6W?4;B(g4(=_b=zmXK_iPPQD*Wz&friICl0 zFc`Ycf8(c>IeH?K=g*U_WUdzP<+q8S`gJpL=Ob5?dGujD$%oWK|Gg1rQeT +