Files
coa-quartz/Quartz/modules/Swing.lua
T
Andrew6810 3b75efe038 init
2022-10-21 07:30:59 -07:00

465 lines
12 KiB
Lua

--[[
Copyright (C) 2006-2007 Nymbia
Copyright (C) 2010 Hendrik "Nevcairiel" Leppkes < h.leppkes@gmail.com >
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
]]
local Quartz3 = LibStub("AceAddon-3.0"):GetAddon("Quartz3")
local L = LibStub("AceLocale-3.0"):GetLocale("Quartz3")
local MODNAME = "Swing"
local Swing = Quartz3:NewModule(MODNAME, "AceEvent-3.0")
local Player = Quartz3:GetModule("Player")
local media = LibStub("LibSharedMedia-3.0")
local lsmlist = AceGUIWidgetLSMlists
----------------------------
-- Upvalues
local CreateFrame, GetTime, UIParent = CreateFrame, GetTime, UIParent
local UnitClass, UnitDamage, UnitAttackSpeed, UnitRangedDamage = UnitClass, UnitDamage, UnitAttackSpeed, UnitRangedDamage
local math_abs, bit_band, unpack = math.abs, bit.band, unpack
local COMBATLOG_FILTER_ME = COMBATLOG_FILTER_ME
local playerclass
local autoshotname = GetSpellInfo(75)
local slam = GetSpellInfo(1464)
local swordprocname = GetSpellInfo(12281)
local resetspells = {
[GetSpellInfo(845)] = true, -- Cleave
[GetSpellInfo(78)] = true, -- Heroic Strike
[GetSpellInfo(6807)] = true, -- Maul
[GetSpellInfo(2973)] = true, -- Raptor Strike
[GetSpellInfo(56815)] = true, -- Rune Strike
}
local resetautoshotspells = {
--[GetSpellInfo(19434)] = true, -- Aimed Shot
}
local swingbar, swingbar_width, swingstatusbar, remainingtext, durationtext
local swingmode -- nil is none, 0 is meleeing, 1 is autoshooting
local starttime, duration
local slamstart
local db, getOptions
local defaults = {
profile = {
barcolor = {1, 1, 1},
swingalpha = 1,
swingheight = 4,
swingposition = "top",
swinggap = -4,
durationtext = true,
remainingtext = true,
x = 300,
y = 300,
}
}
local function OnUpdate()
if slamstart then return end
if starttime then
local spent = GetTime() - starttime
remainingtext:SetFormattedText("%.1f", duration - spent)
local perc = spent / duration
if perc > 1 then
return swingbar:Hide()
else
swingstatusbar:SetValue(perc)
end
end
end
local function OnHide()
swingbar:SetScript("OnUpdate", nil)
end
local function OnShow()
swingbar:SetScript("OnUpdate", OnUpdate)
end
function Swing:OnInitialize()
self.db = Quartz3.db:RegisterNamespace(MODNAME, defaults)
db = self.db.profile
self:SetEnabledState(Quartz3:GetModuleEnabled(MODNAME))
Quartz3:RegisterModuleOptions(MODNAME, getOptions, L["Swing"])
end
function Swing:OnEnable()
local _, c = UnitClass("player")
playerclass = playerclass or c
-- fired when autoattack is enabled/disabled.
self:RegisterEvent("PLAYER_ENTER_COMBAT")
self:RegisterEvent("PLAYER_LEAVE_COMBAT")
-- fired when autoshot (or autowand) is enabled/disabled
self:RegisterEvent("START_AUTOREPEAT_SPELL")
self:RegisterEvent("STOP_AUTOREPEAT_SPELL")
self:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
self:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
-- slam stuff
if playerclass == "WARRIOR" then
self:RegisterEvent("UNIT_SPELLCAST_START")
self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
end
self:RegisterEvent("UNIT_ATTACK")
if not swingbar then
swingbar = CreateFrame("Frame", "Quartz3SwingBar", UIParent)
swingbar:SetFrameStrata("HIGH")
swingbar:SetScript("OnShow", OnShow)
swingbar:SetScript("OnHide", OnHide)
swingbar:SetMovable(true)
swingbar:RegisterForDrag("LeftButton")
swingbar:SetClampedToScreen(true)
swingstatusbar = CreateFrame("StatusBar", nil, swingbar)
durationtext = swingstatusbar:CreateFontString(nil, "OVERLAY")
remainingtext = swingstatusbar:CreateFontString(nil, "OVERLAY")
swingbar:Hide()
end
self:ApplySettings()
end
function Swing:OnDisable()
swingbar:Hide()
end
function Swing:PLAYER_ENTER_COMBAT()
local _,_,offhandlow, offhandhigh = UnitDamage("player")
if math_abs(offhandlow - offhandhigh) <= 0.1 or playerclass == "DRUID" then
swingmode = 0 -- shouldn"t be dual-wielding
end
end
function Swing:PLAYER_LEAVE_COMBAT()
if not swingmode or swingmode == 0 then
swingmode = nil
end
end
function Swing:START_AUTOREPEAT_SPELL()
swingmode = 1
end
function Swing:STOP_AUTOREPEAT_SPELL()
if not swingmode or swingmode == 1 then
swingmode = nil
end
end
do
local swordspecproc = false
function Swing:COMBAT_LOG_EVENT_UNFILTERED(event, timestamp, combatevent, srcGUID, srcName, srcFlags, dstName, dstGUID, dstFlags, spellID, spellName)
if swingmode ~= 0 then return end
if combatevent == "SPELL_EXTRA_ATTACKS" and spellName == swordprocname and (bit_band(srcFlags, COMBATLOG_FILTER_ME) == COMBATLOG_FILTER_ME) then
swordspecproc = true
elseif (combatevent == "SWING_DAMAGE" or combatevent == "SWING_MISSED") and (bit_band(srcFlags, COMBATLOG_FILTER_ME) == COMBATLOG_FILTER_ME) then
if swordspecproc then
swordspecproc = false
else
self:MeleeSwing()
end
elseif (combatevent == "SWING_MISSED") and (bit_band(dstFlags, COMBATLOG_FILTER_ME) == COMBATLOG_FILTER_ME) and spellID == "PARRY" and duration then
duration = duration * 0.6
end
end
end
function Swing:UNIT_SPELLCAST_SUCCEEDED(event, unit, spell)
if unit ~= "player" then return end
if swingmode == 0 then
if resetspells[spell] then
self:MeleeSwing()
elseif spell == slam and slamstart then
starttime = starttime + GetTime() - slamstart
slamstart = nil
end
elseif swingmode == 1 then
if spell == autoshotname then
self:Shoot()
end
end
if resetautoshotspells[spell] then
swingmode = 1
self:Shoot()
end
end
function Swing:UNIT_SPELLCAST_START(event, unit, spell)
if unit == "player" and spell == slam then
slamstart = GetTime()
end
end
function Swing:UNIT_SPELLCAST_INTERRUPTED(event, unit, spell)
if unit == "player" and spell == slam and slamstart then
slamstart = nil
end
end
function Swing:UNIT_ATTACK(event, unit)
if unit == "player" then
if not swingmode then
return
elseif swingmode == 0 then
duration = UnitAttackSpeed("player")
else
duration = UnitRangedDamage("player")
end
durationtext:SetFormattedText("%.1f", duration)
end
end
function Swing:MeleeSwing()
duration = UnitAttackSpeed("player")
durationtext:SetFormattedText("%.1f", duration)
starttime = GetTime()
swingbar:Show()
end
function Swing:Shoot()
duration = UnitRangedDamage("player")
durationtext:SetFormattedText("%.1f", duration)
starttime = GetTime()
swingbar:Show()
end
function Swing:ApplySettings()
db = self.db.profile
if swingbar and self:IsEnabled() then
swingbar:ClearAllPoints()
swingbar:SetHeight(db.swingheight)
swingbar_width = Player.Bar:GetWidth() - 8
swingbar:SetWidth(swingbar_width)
swingbar:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16})
swingbar:SetBackdropColor(0,0,0)
swingbar:SetAlpha(db.swingalpha)
swingbar:SetScale(Player.db.profile.scale)
if db.swingposition == "bottom" then
swingbar:SetPoint("TOP", Player.Bar, "BOTTOM", 0, -1 * db.swinggap)
elseif db.swingposition == "top" then
swingbar:SetPoint("BOTTOM", Player.Bar, "TOP", 0, db.swinggap)
else -- L["Free"]
swingbar:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", db.x, db.y)
end
swingstatusbar:SetAllPoints(swingbar)
swingstatusbar:SetStatusBarTexture(media:Fetch("statusbar", Player.db.profile.texture))
swingstatusbar:GetStatusBarTexture():SetHorizTile(false)
swingstatusbar:GetStatusBarTexture():SetVertTile(false)
swingstatusbar:SetStatusBarColor(unpack(db.barcolor))
swingstatusbar:SetMinMaxValues(0, 1)
if db.durationtext then
durationtext:Show()
durationtext:ClearAllPoints()
durationtext:SetPoint("BOTTOMLEFT", swingbar, "BOTTOMLEFT")
durationtext:SetJustifyH("LEFT")
else
durationtext:Hide()
end
durationtext:SetFont(media:Fetch("font", Player.db.profile.font), 9)
durationtext:SetShadowColor( 0, 0, 0, 1)
durationtext:SetShadowOffset( 0.8, -0.8 )
durationtext:SetTextColor(1,1,1)
durationtext:SetNonSpaceWrap(false)
durationtext:SetWidth(swingbar_width)
if db.remainingtext then
remainingtext:Show()
remainingtext:ClearAllPoints()
remainingtext:SetPoint("BOTTOMRIGHT", swingbar, "BOTTOMRIGHT")
remainingtext:SetJustifyH("RIGHT")
else
remainingtext:Hide()
end
remainingtext:SetFont(media:Fetch("font", Player.db.profile.font), 9)
remainingtext:SetShadowColor( 0, 0, 0, 1)
remainingtext:SetShadowOffset( 0.8, -0.8 )
remainingtext:SetTextColor(1,1,1)
remainingtext:SetNonSpaceWrap(false)
remainingtext:SetWidth(swingbar_width)
end
end
do
local locked = true
local function nothing()
end
local function dragstart()
swingbar:StartMoving()
end
local function dragstop()
db.x = swingbar:GetLeft()
db.y = swingbar:GetBottom()
swingbar:StopMovingOrSizing()
end
local function setOpt(info, value)
db[info[#info]] = value
Swing:ApplySettings()
end
local function getOpt(info)
return db[info[#info]]
end
local function getColor(info)
return unpack(getOpt(info))
end
local function setColor(info, r, g, b, a)
setOpt(info, {r, g, b, a})
end
local options
function getOptions()
options = options or {
type = "group",
name = L["Swing"],
desc = L["Swing"],
get = getOpt,
set = setOpt,
order = 600,
args = {
toggle = {
type = "toggle",
name = L["Enable"],
desc = L["Enable"],
get = function()
return Quartz3:GetModuleEnabled(MODNAME)
end,
set = function(info, v)
Quartz3:SetModuleEnabled(MODNAME, v)
end,
order = 100,
},
barcolor = {
type = "color",
name = L["Bar Color"],
desc = L["Set the color of the swing timer bar"],
get = getColor,
set = setColor,
order = 103,
},
swingheight = {
type = "range",
name = L["Height"],
desc = L["Set the height of the swing timer bar"],
min = 1, max = 20, step = 1,
order = 104,
},
swingalpha = {
type = "range",
name = L["Alpha"],
desc = L["Set the alpha of the swing timer bar"],
min = 0.05, max = 1, bigStep = 0.05,
isPercent = true,
order = 105,
},
swingposition = {
type = "select",
name = L["Bar Position"],
desc = L["Set the position of the swing timer bar"],
values = {["top"] = L["Top"], ["bottom"] = L["Bottom"], ["free"] = L["Free"]},
order = 106,
},
lock = {
type = "toggle",
name = L["Lock"],
desc = L["Toggle Cast Bar lock"],
get = function()
return locked
end,
set = function(info, v)
if v then
swingbar.Hide = nil
swingbar:EnableMouse(false)
swingbar:SetScript("OnDragStart", nil)
swingbar:SetScript("OnDragStop", nil)
if not swingmode then
swingbar:Hide()
end
else
swingbar:Show()
swingbar:EnableMouse(true)
swingbar:SetScript("OnDragStart", dragstart)
swingbar:SetScript("OnDragStop", dragstop)
swingbar:SetAlpha(1)
swingbar.Hide = nothing
end
locked = v
end,
hidden = function()
return db.swingposition ~= "free"
end,
order = 107,
},
x = {
type = "range",
name = L["X"],
desc = L["Set an exact X value for this bar's position."],
min = -2560, max = 2560, bigStep = 1,
order = 108,
hidden = function()
return db.swingposition ~= "free"
end,
},
y = {
type = "range",
name = L["Y"],
desc = L["Set an exact Y value for this bar's position."],
min = -2560,
max = 2560,
order = 108,
hidden = function()
return db.swingposition ~= "free"
end,
},
swinggap = {
type = "range",
name = L["Gap"],
desc = L["Tweak the distance of the swing timer bar from the cast bar"],
min = -35, max = 35, step = 1,
order = 108,
},
durationtext = {
type = "toggle",
name = L["Duration Text"],
desc = L["Toggle display of text showing your total swing time"],
order = 109,
},
remainingtext = {
type = "toggle",
name = L["Remaining Text"],
desc = L["Toggle display of text showing the time remaining until you can swing again"],
order = 110,
},
},
}
return options
end
end