diff --git a/Lib/Aura.lua b/Lib/Aura.lua index 08485f0..6b3c07c 100644 --- a/Lib/Aura.lua +++ b/Lib/Aura.lua @@ -1,54 +1,3 @@ -local resetTooltip = (function() - local tooltip = nil - local createTooltip = function() - -- https://wowwiki-archive.fandom.com/wiki/UIOBJECT_GameTooltip - tt = CreateFrame("GameTooltip", "QuiverAuraScanningTooltip", nil, "GameTooltipTemplate") - tt:SetScript("OnHide", function() tt:SetOwner(WorldFrame, "ANCHOR_NONE") end) - tt:Hide() - tt:SetFrameStrata("Tooltip") - return tt - end - return function() - if not tooltip then tooltip = createTooltip() end - tooltip:SetOwner(WorldFrame, "ANCHOR_NONE") - return tooltip - end -end)() - --- 10% at full hp, to a max of 30% at 40% hp --- That's a line with equation f(hp)= (130-hp) / 3, but capped at 30% -local getTrollBerserkBonus = function() - local percent = UnitHealth("player") / UnitHealthMax("player") - return math.min(0.3, (1.30 - percent) / 3.0) -end - ---[[ -UnitBuff indexes from 1. -GetPlayerBuffTexture indexes from 0. -They also don't have the same iteration order. -Haven't found a reason to use one over the other. ]] -Quiver_Lib_Aura_GetRangedAttackSpeedMultiplier = function() - local speed = 1.0 - for i=1,QUIVER.Buff_Cap do - local texture = UnitBuff("player", i) - if texture == QUIVER.Icon.CurseOfTongues then - speed = speed * 0.5 - -- Unsure if it's safe to remove the wrong one. Maybe that would break other servers. - elseif texture == QUIVER.Icon.NaxxTrinket - or texture == QUIVER.Icon.NaxxTrinketWrong - then - speed = speed * 1.2 - elseif texture == QUIVER.Icon.Quickshots then - speed = speed * 1.3 - elseif texture == QUIVER.Icon.RapidFire then - speed = speed * 1.4 - elseif texture == QUIVER.Icon.TrollBerserk then - speed = speed * (1.0 + getTrollBerserkBonus()) - end - end - return speed -end - -- This doesn't work for duplicate textures (ex. cheetah + zg mount). -- For those you have to scan by name using the GameTooltip. Quiver_Lib_Aura_GetIsActiveTimeLeftByTexture = function(targetTexture) @@ -64,21 +13,24 @@ Quiver_Lib_Aura_GetIsActiveTimeLeftByTexture = function(targetTexture) return false, 0 end -Quiver_Lib_Aura_GetIsBuffActive = function(buffname) - local tooltip = resetTooltip() - for i=0,QUIVER.Buff_Cap do - local buffIndex, isCancellable = GetPlayerBuff(i, "HELPFUL|PASSIVE") - if buffIndex >= 0 then - tooltip:ClearLines() - tooltip:SetPlayerBuff(buffIndex) - local fs1 = _G["QuiverAuraScanningTooltipTextLeft1"] - if fs1 and fs1:GetText() == buffname then - return true +Quiver_Lib_Aura_GetIsBuffActive = (function() + local resetTooltip = Quiver_Lib_Tooltip_Factory("QuiverAuraScanningTooltip") + return function(buffname) + local tooltip = resetTooltip() + for i=0,QUIVER.Buff_Cap do + local buffIndex, isCancellable = GetPlayerBuff(i, "HELPFUL|PASSIVE") + if buffIndex >= 0 then + tooltip:ClearLines() + tooltip:SetPlayerBuff(buffIndex) + local fs1 = _G["QuiverAuraScanningTooltipTextLeft1"] + if fs1 and fs1:GetText() == buffname then + return true + end end end + return false end - return false -end +end)() -- This works great. Don't delete because I'm sure it will be useful in the future. --[[ diff --git a/Lib/Spellbook.lua b/Lib/Spellbook.lua index 9325b50..8822722 100644 --- a/Lib/Spellbook.lua +++ b/Lib/Spellbook.lua @@ -1,7 +1,8 @@ +-- TODO parse spellbook in case a patch changes them, instead of hard-coding here local HUNTER_CASTABLE_SHOTS = { [QUIVER_T.Spellbook.Aimed_Shot] = 3.0, - [QUIVER_T.Spellbook.Multi_Shot] = 0.5, - [QUIVER_T.Spellbook.Trueshot] = 1.3, + [QUIVER_T.Spellbook.Multi_Shot] = 0.0, + [QUIVER_T.Spellbook.Trueshot] = 1.0, } local _HUNTER_INSTANT_SHOTS = { @@ -14,6 +15,46 @@ local _HUNTER_INSTANT_SHOTS = { QUIVER_T.Spellbook.Wyvern_Sting, } +local calcRangedWeaponSpeedBase = (function() + local resetTooltip = Quiver_Lib_Tooltip_Factory("QuiverRangedWeaponScanningTooltip") + + -- Might be cachable. GetInventoryItemLink("Player", slot#) returns a link, ex. [name] + -- Weapon name always appears at line TextLeft1 + return function() + local tooltip = resetTooltip() + tooltip:ClearLines() + tooltip:SetInventoryItem("player", 18)-- ranged weapon slot + + for i=1, tooltip:NumLines() do + local fs = _G["QuiverRangedWeaponScanningTooltipTextRight"..i] + local text = fs and fs:GetText() + if text ~= nil then + local _, _, speed = string.find(text, "Speed (%d+%.%d+)") + if speed ~= nil then + local parsed = tonumber(speed) + if parsed ~= nil then + return parsed + end + end + end + end + end +end)() + +Quiver_Lib_Spellbook_CalcCastTime = function(spellName) + local baseTime = HUNTER_CASTABLE_SHOTS[spellName] + local _,_, msLatency = GetNetStats() + local start = GetTime() + msLatency / 1000 + + local speedCurrent = UnitRangedDamage("player") + local speedBase = calcRangedWeaponSpeedBase() + local speedMultiplier = speedCurrent / speedBase + + -- https://www.mmo-champion.com/content/2188-Patch-4-0-6-Feb-22-Hotfixes-Blue-Posts-Artworks-Comic + local casttime = 0.5 + baseTime * speedMultiplier + return casttime, start +end + local GetIsSpellLearned = function(spellName) local i = 0 while true do @@ -66,14 +107,6 @@ Quiver_Lib_Spellbook_TryFindTexture = function(nameSeek) end end -Quiver_Lib_Spellbook_GetCastTime = function(spellName) - local baseTime = HUNTER_CASTABLE_SHOTS[spellName] - local _,_, msLatency = GetNetStats() - local start = GetTime() + msLatency / 1000 - local casttime = baseTime / Quiver_Lib_Aura_GetRangedAttackSpeedMultiplier() - return casttime, start -end - Quiver_Lib_Spellbook_GetIsSpellCastableShot = function(spellName) for name, _castTime in HUNTER_CASTABLE_SHOTS do if spellName == name then return true end diff --git a/Lib/Tooltip.lua b/Lib/Tooltip.lua new file mode 100644 index 0000000..0457484 --- /dev/null +++ b/Lib/Tooltip.lua @@ -0,0 +1,21 @@ +local createTooltip = function(frameName) + -- https://wowwiki-archive.fandom.com/wiki/UIOBJECT_GameTooltip + local tt = CreateFrame("GameTooltip", frameName, nil, "GameTooltipTemplate") + tt:SetScript("OnHide", function() tt:SetOwner(WorldFrame, "ANCHOR_NONE") end) + tt:Hide() + tt:SetFrameStrata("Tooltip") + return tt +end + +--[[ [ Quiver_Lib_Tooltip_Factory ] + @description Returns a function that clears the tooltip and gets a reference to it. + @param frameName string name for tooltip element +]] +Quiver_Lib_Tooltip_Factory = function(frameName) + local tooltip = nil + return function() + if not tooltip then tooltip = createTooltip(frameName) end + tooltip:SetOwner(WorldFrame, "ANCHOR_NONE") + return tooltip + end +end diff --git a/Modules/AutoShotTimer.lua b/Modules/AutoShotTimer.lua index a3a0dfc..563ddfe 100644 --- a/Modules/AutoShotTimer.lua +++ b/Modules/AutoShotTimer.lua @@ -191,7 +191,7 @@ local onSpellcast = function(spellName) if isShooting and (not isReloading) then timeStartShootOrReload = GetTime() end - castTime, timeStartCast = Quiver_Lib_Spellbook_GetCastTime(spellName) + castTime, timeStartCast = Quiver_Lib_Spellbook_CalcCastTime(spellName) end local handleEvent = function() diff --git a/Modules/Castbar.lua b/Modules/Castbar.lua index 670d25c..fea9985 100644 --- a/Modules/Castbar.lua +++ b/Modules/Castbar.lua @@ -83,12 +83,12 @@ end -- ************ Custom Event Handlers ************ local displayTime = function(current) if current < 0 then current = 0 end - frame.SpellTime:SetText(string.format("%.1f / %.1f", current, castTime)) + frame.SpellTime:SetText(string.format("%.1f / %.2f", current, castTime)) end local onSpellcast = function(spellName) if isCasting then return end isCasting = true - castTime, timeStartCasting = Quiver_Lib_Spellbook_GetCastTime(spellName) + castTime, timeStartCasting = Quiver_Lib_Spellbook_CalcCastTime(spellName) frame.SpellName:SetText(spellName) frame.Castbar:SetWidth(1) displayTime(0) diff --git a/Modules/pfUIPlugins.lua b/Modules/pfUIPlugins.lua index 1f3363c..cd73815 100644 --- a/Modules/pfUIPlugins.lua +++ b/Modules/pfUIPlugins.lua @@ -17,7 +17,7 @@ Quiver_Module_pfUITurtleTrueshot = function() -- Somehow player isn't defined, but all the other locals from pfUI work local player = UnitName("player") if begin then - local castTime, start = Quiver_Lib_Spellbook_GetCastTime(QUIVER_T.Spellbook.Trueshot) + local castTime, start = Quiver_Lib_Spellbook_CalcCastTime(QUIVER_T.Spellbook.Trueshot) local duration = duration or (castTime * 1000) -- add cast action to the database libcast.db[player].cast = trueshotName diff --git a/Quiver.lua b/Quiver.lua index 6281f5d..1febf34 100644 --- a/Quiver.lua +++ b/Quiver.lua @@ -9,12 +9,14 @@ _G.Quiver_Modules = { } local savedVariablesRestore = function() + -- If first time running Quiver, then savedVars are nil, so make defaults Quiver_Store.IsLockedFrames = Quiver_Store.IsLockedFrames == true Quiver_Store.ModuleEnabled = Quiver_Store.ModuleEnabled or {} Quiver_Store.ModuleStore = Quiver_Store.ModuleStore or {} for _k, v in _G.Quiver_Modules do Quiver_Store.ModuleEnabled[v.Id] = Quiver_Store.ModuleEnabled[v.Id] ~= false Quiver_Store.ModuleStore[v.Id] = Quiver_Store.ModuleStore[v.Id] or {} + -- Loading saved variables into each module gives them a chance to set their own defaults. v.OnSavedVariablesRestore(Quiver_Store.ModuleStore[v.Id]) end end diff --git a/Quiver.toc b/Quiver.toc index e3ff21f..d632002 100644 --- a/Quiver.toc +++ b/Quiver.toc @@ -2,13 +2,14 @@ ## Title: Quiver - |cff00ff00Hunter ## Notes: A collection of hunter utilities. ## Author: SabineWren, 2022-2023 -## Version: 2.6.1 +## Version: 2.6.2 ## SavedVariables: Quiver_Store Lib\F.lua Constants.lua Locale\enUS.lua +Lib\Tooltip.lua Lib\Aura.lua Lib\Print.lua Lib\Spellbook.lua