mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-06 21:50:00 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f61f94a24 | ||
|
|
65678da3d2 | ||
|
|
9b7aca8541 | ||
|
|
60525eec3a | ||
|
|
c3829c2bd2 | ||
|
|
28de6fd835 | ||
|
|
fc75e091a4 | ||
|
|
ef478b0552 | ||
|
|
760d8992b6 | ||
|
|
62a99ac410 | ||
|
|
deeec89955 | ||
|
|
cca9771ef0 | ||
|
|
371872bb90 | ||
|
|
591045a606 | ||
|
|
f657a9e7e8 | ||
|
|
0cbd9ecf98 | ||
|
|
6ca482fcaa | ||
|
|
8902d43f40 | ||
|
|
8f006c0643 |
@@ -4,16 +4,18 @@ about: Report a bug or issue with pfUI
|
|||||||
title: "[Bug Description] "
|
title: "[Bug Description] "
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!-- Please fill out ALL fields below. Issues without this info may be closed. -->
|
<!-- Please fill out ALL fields below. Issues without this info may be closed. -->
|
||||||
|
|
||||||
**pfUI Branch:**
|
**pfUI Version:**
|
||||||
- [ ] Master
|
|
||||||
- [ ] experiment
|
**Your ClassicAPI Version:**
|
||||||
|
|
||||||
|
**Your Nampower Version:**
|
||||||
|
|
||||||
|
|
||||||
**Your Nampower Version:** (e.g. latest, or specific commit/date)
|
|
||||||
<!-- Skip if using Compat branch -->
|
|
||||||
|
|
||||||
**Other Addons installed:**
|
**Other Addons installed:**
|
||||||
<!-- List any other addons you are using, or "none" -->
|
<!-- List any other addons you are using, or "none" -->
|
||||||
@@ -45,4 +47,3 @@ Paste error log here
|
|||||||
## Screenshot / Video
|
## Screenshot / Video
|
||||||
<!-- Attach a screenshot or video showing the issue. This is REQUIRED. -->
|
<!-- Attach a screenshot or video showing the issue. This is REQUIRED. -->
|
||||||
<!-- Drag & drop images here or paste a link -->
|
<!-- Drag & drop images here or paste a link -->
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ about: Suggest a new feature or improvement for pfUI
|
|||||||
title: "[Feature] "
|
title: "[Feature] "
|
||||||
labels: enhancement
|
labels: enhancement
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Feature Description
|
## Feature Description
|
||||||
@@ -20,4 +21,3 @@ assignees: ''
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
<!-- If possible, show examples from other addons or screenshots/mockups of how it could look -->
|
<!-- If possible, show examples from other addons or screenshots/mockups of how it could look -->
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -208,7 +208,7 @@ function pfUI.api.GetUnbuffedRoster(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if UnitInRaid("player") then
|
if IsInRaid() then
|
||||||
for i=1,40 do check("raid"..i) end
|
for i=1,40 do check("raid"..i) end
|
||||||
else
|
else
|
||||||
check("player")
|
check("player")
|
||||||
@@ -485,7 +485,7 @@ end
|
|||||||
-- 'msg' [string] the message to send
|
-- 'msg' [string] the message to send
|
||||||
function pfUI.api.SendChatMessageWide(msg)
|
function pfUI.api.SendChatMessageWide(msg)
|
||||||
local channel = "SAY"
|
local channel = "SAY"
|
||||||
if UnitInRaid("player") then
|
if IsInRaid() then
|
||||||
if ( IsRaidLeader() or IsRaidOfficer() ) then
|
if ( IsRaidLeader() or IsRaidOfficer() ) then
|
||||||
channel = "RAID_WARNING"
|
channel = "RAID_WARNING"
|
||||||
else
|
else
|
||||||
|
|||||||
+14
-1
@@ -748,6 +748,7 @@ function pfUI:LoadConfig()
|
|||||||
pfUI:UpdateConfig("tooltip", nil, "cursoroffset", "20")
|
pfUI:UpdateConfig("tooltip", nil, "cursoroffset", "20")
|
||||||
pfUI:UpdateConfig("tooltip", nil, "extguild", "1")
|
pfUI:UpdateConfig("tooltip", nil, "extguild", "1")
|
||||||
pfUI:UpdateConfig("tooltip", nil, "itemid", "0")
|
pfUI:UpdateConfig("tooltip", nil, "itemid", "0")
|
||||||
|
pfUI:UpdateConfig("tooltip", nil, "movespeed", "0")
|
||||||
pfUI:UpdateConfig("tooltip", nil, "alpha", "0.8")
|
pfUI:UpdateConfig("tooltip", nil, "alpha", "0.8")
|
||||||
pfUI:UpdateConfig("tooltip", nil, "alwaysperc", "0")
|
pfUI:UpdateConfig("tooltip", nil, "alwaysperc", "0")
|
||||||
pfUI:UpdateConfig("tooltip", "compare", "basestats", "1")
|
pfUI:UpdateConfig("tooltip", "compare", "basestats", "1")
|
||||||
@@ -1387,5 +1388,17 @@ function pfUI:MigrateConfig()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
pfUI_config.version = pfUI.version.string
|
-- Stamp the version we've migrated to. Dev / git-cloned builds carry
|
||||||
|
-- "@project-version@" in the toc, which pfUI.lua normalizes to "dev" —
|
||||||
|
-- writing that here would have checkversion() parse it back as 0/0/0 on
|
||||||
|
-- the next /reload and re-fire every migration block, clobbering user
|
||||||
|
-- toggles (notably the >3.6.1 buff migration that rewrites
|
||||||
|
-- buffs.{buffs,debuffs,weapons} from the deprecated global.hide{,w}buff
|
||||||
|
-- knobs). Stamp a far-future sentinel instead so checkversion() can't
|
||||||
|
-- flip true again on subsequent loads.
|
||||||
|
if pfUI.version.string == "dev" then
|
||||||
|
pfUI_config.version = "999.999.999"
|
||||||
|
else
|
||||||
|
pfUI_config.version = pfUI.version.string
|
||||||
|
end
|
||||||
end
|
end
|
||||||
+5
-7
@@ -305,12 +305,12 @@ function pfUI.uf:UpdateVisibility()
|
|||||||
local id = self.cache_raid
|
local id = self.cache_raid
|
||||||
|
|
||||||
-- always show self in raidframes
|
-- always show self in raidframes
|
||||||
if not UnitInRaid("player") and GetNumPartyMembers() == 0 and C.unitframes.selfinraid == "1" and id == 1 then
|
if not IsInRaid() and IsInGroup() and C.unitframes.selfinraid == "1" and id == 1 then
|
||||||
self.id = ""
|
self.id = ""
|
||||||
self.label = "player"
|
self.label = "player"
|
||||||
|
|
||||||
-- use raidframes for groups
|
-- use raidframes for groups
|
||||||
elseif not UnitInRaid("player") and GetNumPartyMembers() > 0 and C.unitframes.raidforgroup == "1" then
|
elseif not IsInRaid() and IsInGroup() and C.unitframes.raidforgroup == "1" then
|
||||||
if id == 1 then
|
if id == 1 then
|
||||||
self.id = ""
|
self.id = ""
|
||||||
self.label = "player"
|
self.label = "player"
|
||||||
@@ -347,12 +347,12 @@ function pfUI.uf:UpdateVisibility()
|
|||||||
-- frame shall not be visible
|
-- frame shall not be visible
|
||||||
visibility = "hide"
|
visibility = "hide"
|
||||||
self.visible = nil
|
self.visible = nil
|
||||||
elseif C["unitframes"]["group"]["hide_in_raid"] == "1" and self.label and strsub(self.label,0,5) == "party" and UnitInRaid("player") then
|
elseif C["unitframes"]["group"]["hide_in_raid"] == "1" and self.label and strsub(self.label,0,5) == "party" and IsInRaid() then
|
||||||
-- hide group while in raid and option is set
|
-- hide group while in raid and option is set
|
||||||
visibility = "hide"
|
visibility = "hide"
|
||||||
self.visible = nil
|
self.visible = nil
|
||||||
elseif ( self.fname == "Group0" or self.fname == "PartyPet0" or self.fname == "Party0Target" )
|
elseif ( self.fname == "Group0" or self.fname == "PartyPet0" or self.fname == "Party0Target" )
|
||||||
and (GetNumPartyMembers() <= 0 or (C["unitframes"]["group"]["hide_in_raid"] == "1" and UnitInRaid("player"))) then
|
and (not IsInGroup() or (C["unitframes"]["group"]["hide_in_raid"] == "1" and IsInRaid())) then
|
||||||
-- hide self in group if solo or hide in raid is set
|
-- hide self in group if solo or hide in raid is set
|
||||||
visibility = "hide"
|
visibility = "hide"
|
||||||
self.visible = nil
|
self.visible = nil
|
||||||
@@ -1773,7 +1773,7 @@ function pfUI.uf:RefreshIndicators(unit)
|
|||||||
local unitstr = unit.label .. unit.id
|
local unitstr = unit.label .. unit.id
|
||||||
|
|
||||||
if unit.leaderIcon then -- Leader Icon
|
if unit.leaderIcon then -- Leader Icon
|
||||||
if unit.config.leadericon == "1" and UnitIsPartyLeader(unitstr) and ( GetNumPartyMembers() > 0 or GetNumRaidMembers() > 0 ) then
|
if unit.config.leadericon == "1" and UnitIsPartyLeader(unitstr) and IsInGroup() then
|
||||||
unit.leaderIcon:Show()
|
unit.leaderIcon:Show()
|
||||||
else
|
else
|
||||||
unit.leaderIcon:Hide()
|
unit.leaderIcon:Hide()
|
||||||
@@ -2838,8 +2838,6 @@ function pfUI.uf:GetStatusValue(unit, pos)
|
|||||||
-- Use libhealth for mob health estimation (overrides Nampower/Standard)
|
-- Use libhealth for mob health estimation (overrides Nampower/Standard)
|
||||||
if pfUI.libhealth and pfUI.libhealth.enabled then
|
if pfUI.libhealth and pfUI.libhealth.enabled then
|
||||||
rhp, rhpmax = pfUI.libhealth:GetUnitHealth(unitstr)
|
rhp, rhpmax = pfUI.libhealth:GetUnitHealth(unitstr)
|
||||||
elseif unit.label == "target" and (MobHealth3 or MobHealthFrame) and MobHealth_GetTargetCurHP() then
|
|
||||||
rhp, rhpmax = MobHealth_GetTargetCurHP(), MobHealth_GetTargetMaxHP()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if config == "unit" then
|
if config == "unit" then
|
||||||
|
|||||||
+13
-13
@@ -427,7 +427,7 @@ local function GetDebuffSlotMap(guid)
|
|||||||
local spellId = auras[auraSlot]
|
local spellId = auras[auraSlot]
|
||||||
if spellId and spellId > 0 then
|
if spellId and spellId > 0 then
|
||||||
displaySlot = displaySlot + 1
|
displaySlot = displaySlot + 1
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
local texture = libdebuff:GetSpellIcon(spellId)
|
local texture = libdebuff:GetSpellIcon(spellId)
|
||||||
local stacks = (auraApps and auraApps[auraSlot] or 0) + 1
|
local stacks = (auraApps and auraApps[auraSlot] or 0) + 1
|
||||||
local dtype = nil
|
local dtype = nil
|
||||||
@@ -1024,7 +1024,7 @@ if hasNampower then
|
|||||||
local targetGuid = arg4
|
local targetGuid = arg4
|
||||||
local numHit = arg6 or 0
|
local numHit = arg6 or 0
|
||||||
local numMissed = arg7 or 0
|
local numMissed = arg7 or 0
|
||||||
|
|
||||||
-- Fire registered SPELL_GO_SELF hooks BEFORE miss guard
|
-- Fire registered SPELL_GO_SELF hooks BEFORE miss guard
|
||||||
-- (Swingtimer needs to see ALL casts, even misses, for swing reset)
|
-- (Swingtimer needs to see ALL casts, even misses, for swing reset)
|
||||||
if event == "SPELL_GO_SELF" and pfUI.libdebuff_spell_go_hooks then
|
if event == "SPELL_GO_SELF" and pfUI.libdebuff_spell_go_hooks then
|
||||||
@@ -1035,15 +1035,15 @@ if hasNampower then
|
|||||||
|
|
||||||
if numMissed > 0 or numHit == 0 then return end
|
if numMissed > 0 or numHit == 0 then return end
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
local spellRankString = GetSpellRecField and GetSpellRecField(spellId, "rank")
|
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
local spellRankString = C_Spell.GetSpellSubtext(spellId)
|
||||||
|
|
||||||
local castRank = 0
|
local castRank = 0
|
||||||
if spellRankString and spellRankString ~= "" then
|
if spellRankString and spellRankString ~= "" then
|
||||||
castRank = tonumber((string.gsub(spellRankString, "Rank ", ""))) or 0
|
castRank = tonumber((string.gsub(spellRankString, "Rank ", ""))) or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Store in pendingCasts for DEBUFF_ADDED correlation.
|
-- Store in pendingCasts for DEBUFF_ADDED correlation.
|
||||||
-- If this cast is a downrank of an already active debuff, fire the downrank blocked hook
|
-- If this cast is a downrank of an already active debuff, fire the downrank blocked hook
|
||||||
-- so external addons (e.g. SuperCleveRoidMacros) don't need to re-implement this check.
|
-- so external addons (e.g. SuperCleveRoidMacros) don't need to re-implement this check.
|
||||||
@@ -1209,7 +1209,7 @@ if hasNampower then
|
|||||||
if not spellId then return end
|
if not spellId then return end
|
||||||
if not targetGuid or targetGuid == "" or targetGuid == "0x0000000000000000" then return end
|
if not targetGuid or targetGuid == "" or targetGuid == "0x0000000000000000" then return end
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
-- Deduplicate: Ignore if we processed this exact cast recently (within 100ms)
|
-- Deduplicate: Ignore if we processed this exact cast recently (within 100ms)
|
||||||
@@ -1469,7 +1469,7 @@ if hasNampower then
|
|||||||
|
|
||||||
-- Invalidate slot map cache for this GUID
|
-- Invalidate slot map cache for this GUID
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
if debugStats.enabled then
|
if debugStats.enabled then
|
||||||
@@ -1599,9 +1599,9 @@ if hasNampower then
|
|||||||
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
||||||
|
|
||||||
-- Invalidate slot map cache for this GUID
|
-- Invalidate slot map cache for this GUID
|
||||||
|
|
||||||
local spellName = (GetSpellRecField and GetSpellRecField(spellId, "name")) or "?"
|
local spellName = C_Spell.GetSpellName(spellId) or "?"
|
||||||
|
|
||||||
if debugStats.enabled then
|
if debugStats.enabled then
|
||||||
debugStats.debuff_removed = debugStats.debuff_removed + 1
|
debugStats.debuff_removed = debugStats.debuff_removed + 1
|
||||||
if IsCurrentTarget(guid) then
|
if IsCurrentTarget(guid) then
|
||||||
@@ -1609,13 +1609,13 @@ if hasNampower then
|
|||||||
GetDebugTimestamp(), displaySlot, auraSlot or -1, auraSlot_0based or -1, spellName))
|
GetDebugTimestamp(), displaySlot, auraSlot or -1, auraSlot_0based or -1, spellName))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If unit is dead, cleanup all
|
-- If unit is dead, cleanup all
|
||||||
if UnitIsDead and UnitIsDead(guid) then
|
if UnitIsDead and UnitIsDead(guid) then
|
||||||
CleanupUnit(guid)
|
CleanupUnit(guid)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get auraSlot from event parameter (Nampower 2.29+)
|
-- Get auraSlot from event parameter (Nampower 2.29+)
|
||||||
-- Fallback to displayToAura mapping if not available
|
-- Fallback to displayToAura mapping if not available
|
||||||
local foundAuraSlot = auraSlot
|
local foundAuraSlot = auraSlot
|
||||||
|
|||||||
+32
-94
@@ -44,78 +44,13 @@ local healGuidToName = {} -- [casterGuid] = casterName, for SPELL_FAILED_OTHER c
|
|||||||
local ress_timers = {} -- [target][sender] = expiry_timestamp (60s rez window)
|
local ress_timers = {} -- [target][sender] = expiry_timestamp (60s rez window)
|
||||||
local RESS_TIMEOUT = 60 -- Vanilla: rez offer expires after 60s
|
local RESS_TIMEOUT = 60 -- Vanilla: rez offer expires after 60s
|
||||||
|
|
||||||
local PRAYER_OF_HEALING
|
-- Localized spell names resolved once from canonical rank-1 spellIDs.
|
||||||
do -- Prayer of Healing
|
-- Every rank shares the same name, so per-rank comparisons elsewhere can
|
||||||
local locales = {
|
-- be done against these constants without per-locale or per-rank tables.
|
||||||
["deDE"] = "Gebet der Heilung",
|
local PRAYER_OF_HEALING = C_Spell.GetSpellName(596) -- Prayer of Healing (Rank 1)
|
||||||
["enUS"] = "Prayer of Healing",
|
local REJUVENATION = C_Spell.GetSpellName(774) -- Rejuvenation (Rank 1)
|
||||||
["esES"] = "Rezo de curación",
|
local RENEW = C_Spell.GetSpellName(139) -- Renew (Rank 1)
|
||||||
["frFR"] = "Prière de soins",
|
local REGROWTH = C_Spell.GetSpellName(8936) -- Regrowth (Rank 1)
|
||||||
["koKR"] = "치유의 기원",
|
|
||||||
["ruRU"] = "Молитва исцеления",
|
|
||||||
["zhCN"] = "治疗祷言",
|
|
||||||
}
|
|
||||||
|
|
||||||
PRAYER_OF_HEALING = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
local REJUVENATION
|
|
||||||
do -- Rejuvenation
|
|
||||||
local locales = {
|
|
||||||
["deDE"] = "Verjüngung",
|
|
||||||
["enUS"] = "Rejuvenation",
|
|
||||||
["esES"] = "Rejuvenecimiento",
|
|
||||||
["frFR"] = "Récupération",
|
|
||||||
["koKR"] = "회복",
|
|
||||||
["ruRU"] = "Омоложение",
|
|
||||||
["zhCN"] = "回春术",
|
|
||||||
}
|
|
||||||
|
|
||||||
REJUVENATION = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
local RENEW
|
|
||||||
do -- Renew
|
|
||||||
local locales = {
|
|
||||||
["deDE"] = "Erneuerung",
|
|
||||||
["enUS"] = "Renew",
|
|
||||||
["esES"] = "Renovar",
|
|
||||||
["frFR"] = "Rénovation",
|
|
||||||
["koKR"] = "소생",
|
|
||||||
["ruRU"] = "Обновление",
|
|
||||||
["zhCN"] = "恢复",
|
|
||||||
}
|
|
||||||
|
|
||||||
RENEW = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
local REGROWTH
|
|
||||||
do -- Regrowth
|
|
||||||
local locales = {
|
|
||||||
["deDE"] = "Nachwachsen",
|
|
||||||
["enUS"] = "Regrowth",
|
|
||||||
["esES"] = "Recrecimiento",
|
|
||||||
["frFR"] = "Rétablissement",
|
|
||||||
["koKR"] = "재생",
|
|
||||||
["ruRU"] = "Восстановление",
|
|
||||||
["zhCN"] = "愈合",
|
|
||||||
}
|
|
||||||
|
|
||||||
REGROWTH = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Spell IDs for SPELL_GO_SELF callback (Nampower) - Instant HoT detection
|
|
||||||
local SPELL_IDS = {
|
|
||||||
-- Rejuvenation (all ranks)
|
|
||||||
[774] = "Reju", [1058] = "Reju", [1430] = "Reju", [2090] = "Reju", [2091] = "Reju",
|
|
||||||
[3627] = "Reju", [8910] = "Reju", [9839] = "Reju", [9840] = "Reju", [9841] = "Reju",
|
|
||||||
[25299] = "Reju", [26981] = "Reju", [26982] = "Reju",
|
|
||||||
-- Renew (all ranks)
|
|
||||||
[139] = "Renew", [6074] = "Renew", [6075] = "Renew", [6076] = "Renew", [6077] = "Renew",
|
|
||||||
[6078] = "Renew", [10927] = "Renew", [10928] = "Renew", [10929] = "Renew", [25315] = "Renew",
|
|
||||||
[25221] = "Renew", [25222] = "Renew",
|
|
||||||
}
|
|
||||||
|
|
||||||
local libpredict = CreateFrame("Frame")
|
local libpredict = CreateFrame("Frame")
|
||||||
libpredict:RegisterEvent("UNIT_HEALTH")
|
libpredict:RegisterEvent("UNIT_HEALTH")
|
||||||
@@ -173,7 +108,7 @@ end
|
|||||||
|
|
||||||
local function isRezSpell(spellId)
|
local function isRezSpell(spellId)
|
||||||
if not L["resurrections"] then return false end
|
if not L["resurrections"] then return false end
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
return spellName and L["resurrections"][spellName]
|
return spellName and L["resurrections"][spellName]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -192,7 +127,7 @@ end)
|
|||||||
-- SPELL_START_SELF: own cast started (heals + rez)
|
-- SPELL_START_SELF: own cast started (heals + rez)
|
||||||
pfUI.libdebuff_spell_start_self_hooks = pfUI.libdebuff_spell_start_self_hooks or {}
|
pfUI.libdebuff_spell_start_self_hooks = pfUI.libdebuff_spell_start_self_hooks or {}
|
||||||
pfUI.libdebuff_spell_start_self_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
pfUI.libdebuff_spell_start_self_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
local pendingTarget = nil
|
local pendingTarget = nil
|
||||||
@@ -255,7 +190,7 @@ pfUI.libdebuff_spell_start_self_hooks["libpredict"] = function(spellId, casterGu
|
|||||||
-- selfcast (ALT) = player, otherwise = current target
|
-- selfcast (ALT) = player, otherwise = current target
|
||||||
-- Use this to find the correct group to heal
|
-- Use this to find the correct group to heal
|
||||||
local pohTarget = target or player
|
local pohTarget = target or player
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
-- Raid: find pohTarget's subgroup and heal only those members
|
-- Raid: find pohTarget's subgroup and heal only those members
|
||||||
-- (Turtle WoW changed PoH to heal the target's group, not the caster's group)
|
-- (Turtle WoW changed PoH to heal the target's group, not the caster's group)
|
||||||
local targetGroup
|
local targetGroup
|
||||||
@@ -319,7 +254,7 @@ end
|
|||||||
-- SPELL_GO_SELF: own cast landed (HealStop + Regrowth timer)
|
-- SPELL_GO_SELF: own cast landed (HealStop + Regrowth timer)
|
||||||
pfUI.libdebuff_spell_go_hooks["libpredict_sender"] = function(spellId)
|
pfUI.libdebuff_spell_go_hooks["libpredict_sender"] = function(spellId)
|
||||||
libpredict:HealStop(player)
|
libpredict:HealStop(player)
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if spellName == REGROWTH then
|
if spellName == REGROWTH then
|
||||||
local now = pfUI.uf.now or GetTime()
|
local now = pfUI.uf.now or GetTime()
|
||||||
if libpredict.sender.regrowth_timer then
|
if libpredict.sender.regrowth_timer then
|
||||||
@@ -337,7 +272,7 @@ end
|
|||||||
-- Signature: fn(spellId, casterGuid, targetGuid, castTime)
|
-- Signature: fn(spellId, casterGuid, targetGuid, castTime)
|
||||||
pfUI.libdebuff_spell_start_other_hooks = pfUI.libdebuff_spell_start_other_hooks or {}
|
pfUI.libdebuff_spell_start_other_hooks = pfUI.libdebuff_spell_start_other_hooks or {}
|
||||||
pfUI.libdebuff_spell_start_other_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
pfUI.libdebuff_spell_start_other_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
local casterName = resolveNameFromGuid(casterGuid)
|
local casterName = resolveNameFromGuid(casterGuid)
|
||||||
@@ -364,7 +299,7 @@ pfUI.libdebuff_spell_start_other_hooks["libpredict"] = function(spellId, casterG
|
|||||||
|
|
||||||
-- Prayer of Healing: heal entire subgroup of the target
|
-- Prayer of Healing: heal entire subgroup of the target
|
||||||
if spellName == PRAYER_OF_HEALING then
|
if spellName == PRAYER_OF_HEALING then
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
local targetGroup
|
local targetGroup
|
||||||
for i = 1, GetNumRaidMembers() do
|
for i = 1, GetNumRaidMembers() do
|
||||||
local rname, _, subgroup = GetRaidRosterInfo(i)
|
local rname, _, subgroup = GetRaidRosterInfo(i)
|
||||||
@@ -404,8 +339,13 @@ end
|
|||||||
-- Signature: fn(spellId, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
-- Signature: fn(spellId, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
||||||
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
|
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
|
||||||
pfUI.libdebuff_spell_go_hooks["libpredict"] = function(spellId, a1, a2, a3, a4, a5, a6, a7)
|
pfUI.libdebuff_spell_go_hooks["libpredict"] = function(spellId, a1, a2, a3, a4, a5, a6, a7)
|
||||||
-- Instant HoTs
|
-- Instant HoTs — classify by name (rank-independent) instead of a
|
||||||
local hotType = SPELL_IDS[spellId]
|
-- hardcoded per-rank ID table.
|
||||||
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
|
local hotType
|
||||||
|
if spellName == REJUVENATION then hotType = "Reju"
|
||||||
|
elseif spellName == RENEW then hotType = "Renew"
|
||||||
|
end
|
||||||
if hotType then
|
if hotType then
|
||||||
local targetGuid = a4
|
local targetGuid = a4
|
||||||
local targetName = resolveNameFromGuid(targetGuid)
|
local targetName = resolveNameFromGuid(targetGuid)
|
||||||
@@ -426,9 +366,9 @@ pfUI.libdebuff_spell_go_hooks["libpredict"] = function(spellId, a1, a2, a3, a4,
|
|||||||
local rankStr = tostring(rank)
|
local rankStr = tostring(rank)
|
||||||
if libpredict.sender and libpredict.sender.SendHealCommMsg then
|
if libpredict.sender and libpredict.sender.SendHealCommMsg then
|
||||||
libpredict.sender:SendHealCommMsg(hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/")
|
libpredict.sender:SendHealCommMsg(hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/")
|
||||||
elseif GetNumRaidMembers() > 0 then
|
elseif IsInRaid() then
|
||||||
SendAddonMessage("HealComm", hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/", "RAID")
|
SendAddonMessage("HealComm", hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/", "RAID")
|
||||||
elseif GetNumPartyMembers() > 0 then
|
elseif IsInGroup() then
|
||||||
SendAddonMessage("HealComm", hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/", "PARTY")
|
SendAddonMessage("HealComm", hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/", "PARTY")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1019,8 +959,6 @@ hooksecurefunc("CastSpellByName", function(effect, target)
|
|||||||
if not libpredict.sender.enabled then return end
|
if not libpredict.sender.enabled then return end
|
||||||
local effect, rank = libspell.GetSpellInfo(effect)
|
local effect, rank = libspell.GetSpellInfo(effect)
|
||||||
if not effect then return end
|
if not effect then return end
|
||||||
local mouseover = pfUI and pfUI.uf and pfUI.uf.mouseover and pfUI.uf.mouseover.unit
|
|
||||||
mouseover = mouseover and UnitCanAssist("player", mouseover) and UnitName(mouseover)
|
|
||||||
|
|
||||||
local default = UnitName("target") and UnitCanAssist("player", "target") and UnitName("target") or UnitName("player")
|
local default = UnitName("target") and UnitCanAssist("player", "target") and UnitName("target") or UnitName("player")
|
||||||
|
|
||||||
@@ -1039,13 +977,13 @@ hooksecurefunc("CastSpellByName", function(effect, target)
|
|||||||
if not libpredict.sender.current_cast then
|
if not libpredict.sender.current_cast then
|
||||||
spell_queue[1] = effect
|
spell_queue[1] = effect
|
||||||
spell_queue[2] = effect.. ( rank or "" )
|
spell_queue[2] = effect.. ( rank or "" )
|
||||||
spell_queue[3] = target or mouseover or default
|
spell_queue[3] = target or default
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Instant HoTs: libdebuff/Nampower via GetHotDuration, hook method as fallback
|
-- Instant HoTs: libdebuff/Nampower via GetHotDuration, hook method as fallback
|
||||||
|
|
||||||
if effect == REJUVENATION then
|
if effect == REJUVENATION then
|
||||||
local hotTarget = target or mouseover or default
|
local hotTarget = target or default
|
||||||
local now = pfUI.uf.now or GetTime()
|
local now = pfUI.uf.now or GetTime()
|
||||||
local key = "Reju" .. hotTarget
|
local key = "Reju" .. hotTarget
|
||||||
|
|
||||||
@@ -1062,7 +1000,7 @@ hooksecurefunc("CastSpellByName", function(effect, target)
|
|||||||
local rankStr = rankNum and tostring(rankNum) or "0"
|
local rankStr = rankNum and tostring(rankNum) or "0"
|
||||||
libpredict.sender:SendHealCommMsg("Reju/"..hotTarget.."/"..rejuvDuration.."/"..rankStr.."/")
|
libpredict.sender:SendHealCommMsg("Reju/"..hotTarget.."/"..rejuvDuration.."/"..rankStr.."/")
|
||||||
elseif effect == RENEW then
|
elseif effect == RENEW then
|
||||||
local hotTarget = target or mouseover or default
|
local hotTarget = target or default
|
||||||
local now = pfUI.uf.now or GetTime()
|
local now = pfUI.uf.now or GetTime()
|
||||||
local key = "Renew" .. hotTarget
|
local key = "Renew" .. hotTarget
|
||||||
|
|
||||||
@@ -1145,10 +1083,10 @@ libpredict.sender = CreateFrame("Frame", "pfPredictionSender", UIParent)
|
|||||||
libpredict.sender.enabled = true
|
libpredict.sender.enabled = true
|
||||||
libpredict.sender.SendHealCommMsg = function(self, msg)
|
libpredict.sender.SendHealCommMsg = function(self, msg)
|
||||||
-- Smart channel selection: Only send to relevant channel to avoid duplicates
|
-- Smart channel selection: Only send to relevant channel to avoid duplicates
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
-- In raid: Only send to RAID (includes all raid members)
|
-- In raid: Only send to RAID (includes all raid members)
|
||||||
SendAddonMessage("HealComm", msg, "RAID")
|
SendAddonMessage("HealComm", msg, "RAID")
|
||||||
elseif GetNumPartyMembers() > 0 then
|
elseif IsInGroup() then
|
||||||
-- In party: Only send to PARTY
|
-- In party: Only send to PARTY
|
||||||
SendAddonMessage("HealComm", msg, "PARTY")
|
SendAddonMessage("HealComm", msg, "PARTY")
|
||||||
end
|
end
|
||||||
@@ -1157,10 +1095,10 @@ libpredict.sender.SendHealCommMsg = function(self, msg)
|
|||||||
end
|
end
|
||||||
libpredict.sender.SendResCommMsg = function(self, msg)
|
libpredict.sender.SendResCommMsg = function(self, msg)
|
||||||
-- Smart channel selection: Only send to relevant channel to avoid duplicates
|
-- Smart channel selection: Only send to relevant channel to avoid duplicates
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
-- In raid: Only send to RAID (includes all raid members)
|
-- In raid: Only send to RAID (includes all raid members)
|
||||||
SendAddonMessage("CTRA", msg, "RAID")
|
SendAddonMessage("CTRA", msg, "RAID")
|
||||||
elseif GetNumPartyMembers() > 0 then
|
elseif IsInGroup() then
|
||||||
-- In party: Only send to PARTY
|
-- In party: Only send to PARTY
|
||||||
SendAddonMessage("CTRA", msg, "PARTY")
|
SendAddonMessage("CTRA", msg, "PARTY")
|
||||||
end
|
end
|
||||||
@@ -1236,7 +1174,7 @@ libpredict.sender:SetScript("OnEvent", function()
|
|||||||
local amount = arg4
|
local amount = arg4
|
||||||
local isCrit = arg5 == 1
|
local isCrit = arg5 == 1
|
||||||
local isPeriodic = arg6 == 1
|
local isPeriodic = arg6 == 1
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if spellName and spell_queue[1] == spellName then
|
if spellName and spell_queue[1] == spellName then
|
||||||
UpdateCache(spell_queue[2], amount, isCrit)
|
UpdateCache(spell_queue[2], amount, isCrit)
|
||||||
end
|
end
|
||||||
@@ -1256,9 +1194,9 @@ libpredict.sender:SetScript("OnEvent", function()
|
|||||||
local casterName = resolveNameFromGuid(casterGuid)
|
local casterName = resolveNameFromGuid(casterGuid)
|
||||||
if not casterName or casterName == player then return end -- own heals handled by SPELL_HEAL_BY_SELF
|
if not casterName or casterName == player then return end -- own heals handled by SPELL_HEAL_BY_SELF
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
local rankStr = GetSpellRecField and GetSpellRecField(spellId, "rank") or ""
|
local rankStr = C_Spell.GetSpellSubtext(spellId)
|
||||||
local spellKey = spellName .. (rankStr or "")
|
local spellKey = spellName .. (rankStr or "")
|
||||||
|
|
||||||
foreignCache[casterName] = foreignCache[casterName] or {}
|
foreignCache[casterName] = foreignCache[casterName] or {}
|
||||||
|
|||||||
+2
-5
@@ -2380,11 +2380,7 @@ pfUI:RegisterModule("gui", function ()
|
|||||||
|
|
||||||
if c == "player" then
|
if c == "player" then
|
||||||
CreateConfig(nil, T["Player SP/Haste Display"], nil, nil, "header")
|
CreateConfig(nil, T["Player SP/Haste Display"], nil, nil, "header")
|
||||||
CreateConfig(nil, T["Haste Display"], C.unitframes[c], "display_haste", "dropdown", {
|
CreateConfig(nil, T["Haste Display"], C.unitframes[c], "display_haste", "checkbox")
|
||||||
"0:"..T["None"],
|
|
||||||
"1:"..T["Haste (cast speed increase)"],
|
|
||||||
"2:"..T["Effective Haste (Haste * cast time reduction)"], -- Only affects mages/warlocks I believe
|
|
||||||
})
|
|
||||||
CreateConfig(nil, T["Haste Display Color"], C.unitframes[c], "display_haste_color", "color")
|
CreateConfig(nil, T["Haste Display Color"], C.unitframes[c], "display_haste_color", "color")
|
||||||
CreateConfig(nil, T["Display Spell Power"], C.unitframes[c], "display_spellpower", "checkbox")
|
CreateConfig(nil, T["Display Spell Power"], C.unitframes[c], "display_spellpower", "checkbox")
|
||||||
CreateConfig(nil, T["Use Custom Spell Power Color (unchecked = biggest school color)"], C.unitframes[c], "display_sp_color_override", "checkbox")
|
CreateConfig(nil, T["Use Custom Spell Power Color (unchecked = biggest school color)"], C.unitframes[c], "display_sp_color_override", "checkbox")
|
||||||
@@ -2749,6 +2745,7 @@ pfUI:RegisterModule("gui", function ()
|
|||||||
CreateConfig(nil, T["Enable Extended Guild Information"], C.tooltip, "extguild", "checkbox")
|
CreateConfig(nil, T["Enable Extended Guild Information"], C.tooltip, "extguild", "checkbox")
|
||||||
CreateConfig(nil, T["Always Show Health In Percent"], C.tooltip, "alwaysperc", "checkbox")
|
CreateConfig(nil, T["Always Show Health In Percent"], C.tooltip, "alwaysperc", "checkbox")
|
||||||
CreateConfig(nil, T["Show Item IDs"], C.tooltip, "itemid", "checkbox")
|
CreateConfig(nil, T["Show Item IDs"], C.tooltip, "itemid", "checkbox")
|
||||||
|
CreateConfig(nil, T["Show Movement Speed"], C.tooltip, "movespeed", "checkbox")
|
||||||
CreateConfig(nil, T["Custom Transparency"], C.tooltip, "alpha")
|
CreateConfig(nil, T["Custom Transparency"], C.tooltip, "alpha")
|
||||||
CreateConfig(nil, T["Status Bar Texture"], C.tooltip.statusbar, "texture", "dropdown", pfUI.gui.dropdowns.uf_bartexture)
|
CreateConfig(nil, T["Status Bar Texture"], C.tooltip.statusbar, "texture", "dropdown", pfUI.gui.dropdowns.uf_bartexture)
|
||||||
CreateConfig(nil, T["Compare Item Base Stats"], C.tooltip.compare, "basestats", "checkbox")
|
CreateConfig(nil, T["Compare Item Base Stats"], C.tooltip.compare, "basestats", "checkbox")
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ pfUI:RegisterModule("innervatecall", function ()
|
|||||||
return "BATTLEGROUND"
|
return "BATTLEGROUND"
|
||||||
end
|
end
|
||||||
|
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
return "RAID"
|
return "RAID"
|
||||||
end
|
end
|
||||||
|
|
||||||
if GetNumPartyMembers() > 0 then
|
if IsInGroup() then
|
||||||
return "PARTY"
|
return "PARTY"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -323,7 +323,7 @@ pfUI:RegisterModule("loot", function ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function pfUI.loot:InitGroupDropDown()
|
function pfUI.loot:InitGroupDropDown()
|
||||||
local inRaid = UnitInRaid("player")
|
local inRaid = IsInRaid()
|
||||||
if UIDROPDOWNMENU_MENU_LEVEL == 1 then
|
if UIDROPDOWNMENU_MENU_LEVEL == 1 then
|
||||||
if ( inRaid ) then
|
if ( inRaid ) then
|
||||||
pfUI.loot:BuildRaidMenu(UIDROPDOWNMENU_MENU_LEVEL)
|
pfUI.loot:BuildRaidMenu(UIDROPDOWNMENU_MENU_LEVEL)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ pfUI:RegisterModule("mapcolors", function ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function UpdateUnitFrames(unit_button_name)
|
local function UpdateUnitFrames(unit_button_name)
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
for i=1, MAX_RAID_MEMBERS do
|
for i=1, MAX_RAID_MEMBERS do
|
||||||
local frame_name = unit_button_name.."Raid"..i
|
local frame_name = unit_button_name.."Raid"..i
|
||||||
local frame = _G[frame_name]
|
local frame = _G[frame_name]
|
||||||
@@ -68,7 +68,7 @@ pfUI:RegisterModule("mapcolors", function ()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif GetNumPartyMembers() > 0 then
|
elseif IsInGroup() then
|
||||||
for i=1, MAX_PARTY_MEMBERS do
|
for i=1, MAX_PARTY_MEMBERS do
|
||||||
local frame_name = unit_button_name.."Party"..i
|
local frame_name = unit_button_name.."Party"..i
|
||||||
local frame = _G[frame_name]
|
local frame = _G[frame_name]
|
||||||
|
|||||||
+9
-75
@@ -1,39 +1,6 @@
|
|||||||
pfUI:RegisterModule("mouseover", function ()
|
pfUI:RegisterModule("mouseover", function ()
|
||||||
pfUI.uf.mouseover = CreateFrame("Frame", "pfMouseOver", UIParent)
|
|
||||||
|
|
||||||
-- Prepare a list of units that can be used via SpellTargetUnit
|
|
||||||
local st_units = { [1] = "player", [2] = "target", [3] = "mouseover" }
|
|
||||||
for i=1, MAX_PARTY_MEMBERS do table.insert(st_units, "party"..i) end
|
|
||||||
for i=1, MAX_RAID_MEMBERS do table.insert(st_units, "raid"..i) end
|
|
||||||
|
|
||||||
-- Try to find a valid (friendly) unitstring that can be used for
|
|
||||||
-- SpellTargetUnit(unit) to avoid another target switch
|
|
||||||
local function GetUnitString(unit)
|
|
||||||
for index, unitstr in pairs(st_units) do
|
|
||||||
if UnitIsUnit(unit, unitstr) then
|
|
||||||
return unitstr
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Same as CastSpellByName but with disabled AutoSelfCast
|
|
||||||
local function NoSelfCast(spell, onself)
|
|
||||||
local cvar_selfcast = GetCVar("AutoSelfCast")
|
|
||||||
|
|
||||||
if cvar_selfcast ~= "0" then
|
|
||||||
SetCVar("AutoSelfCast", "0")
|
|
||||||
pcall(CastSpellByName, spell, onself)
|
|
||||||
SetCVar("AutoSelfCast", cvar_selfcast)
|
|
||||||
else
|
|
||||||
CastSpellByName(spell, onself)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
_G.SLASH_PFCAST1, _G.SLASH_PFCAST2 = "/pfcast", "/pfmouse"
|
_G.SLASH_PFCAST1, _G.SLASH_PFCAST2 = "/pfcast", "/pfmouse"
|
||||||
function SlashCmdList.PFCAST(msg)
|
function SlashCmdList.PFCAST(msg)
|
||||||
local restore_target = true
|
|
||||||
local func = pfUI.api.TryMemoizedFuncLoadstringForSpellCasts(msg)
|
local func = pfUI.api.TryMemoizedFuncLoadstringForSpellCasts(msg)
|
||||||
local unit = "mouseover"
|
local unit = "mouseover"
|
||||||
|
|
||||||
@@ -50,51 +17,18 @@ pfUI:RegisterModule("mouseover", function ()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Nampower: CastSpellByName supports a second unit parameter directly.
|
-- Spell-name path: Nampower's CastSpellByName takes a second unit
|
||||||
-- unit is already resolved to "mouseover", "target" or "player" at this point.
|
-- parameter directly, no target swap dance required.
|
||||||
if not func and GetNampowerVersion then
|
if not func then
|
||||||
CastSpellByName(msg, unit)
|
CastSpellByName(msg, unit)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If target and mouseover are friendly units, we can't use spell target as it
|
-- Macro path: switch target so the macro's spell calls land on `unit`,
|
||||||
-- would cast on the target instead of the mouseover. However, if the mouseover
|
-- then restore.
|
||||||
-- is friendly and the target is not, we can try to obtain the best unitstring
|
local restore_target = not UnitIsUnit("target", unit)
|
||||||
-- for the later SpellTargetUnit() call.
|
if restore_target then TargetUnit(unit) end
|
||||||
local unitstr = not UnitCanAssist("player", "target") and UnitCanAssist("player", unit) and GetUnitString(unit)
|
func()
|
||||||
|
if restore_target then TargetLastTarget() end
|
||||||
if UnitIsUnit("target", unit) or (not func and unitstr) then
|
|
||||||
-- no target change required, we can either use spell target
|
|
||||||
-- or the unit is already our current target.
|
|
||||||
restore_target = false
|
|
||||||
else
|
|
||||||
-- The spelltarget can't be used here, we need to switch
|
|
||||||
-- and restore the target during spell cast
|
|
||||||
TargetUnit(unit)
|
|
||||||
end
|
|
||||||
|
|
||||||
if func then
|
|
||||||
func()
|
|
||||||
else
|
|
||||||
-- write temporary unit name
|
|
||||||
pfUI.uf.mouseover.unit = unit
|
|
||||||
|
|
||||||
-- cast without self cast cvar setting
|
|
||||||
-- to allow spells to use spelltarget
|
|
||||||
NoSelfCast(msg)
|
|
||||||
|
|
||||||
-- set spell target to unitstring (or selfcast)
|
|
||||||
if SpellIsTargeting() then SpellTargetUnit(unitstr or "player") end
|
|
||||||
|
|
||||||
-- clean up spell target in error case
|
|
||||||
if SpellIsTargeting() then SpellStopTargeting() end
|
|
||||||
|
|
||||||
-- remove temporary mouseover unit
|
|
||||||
pfUI.uf.mouseover.unit = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if restore_target then
|
|
||||||
TargetLastTarget()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
@@ -937,10 +937,15 @@ end
|
|||||||
-- name — name alone misses pool reuse between same-named units (e.g. plate
|
-- name — name alone misses pool reuse between same-named units (e.g. plate
|
||||||
-- held a player "Ironforge Guard" and is now reassigned to the NPC by the
|
-- held a player "Ironforge Guard" and is now reassigned to the NPC by the
|
||||||
-- same name), which would leak a stale "PLAYER" hint into GetUnitInfo.
|
-- same name), which would leak a stale "PLAYER" hint into GetUnitInfo.
|
||||||
|
-- Wipe the whole cache table: the PERF gates below ("only update X when
|
||||||
|
-- X changed") would otherwise skip bar/color/text updates when the new
|
||||||
|
-- unit happens to share a cached value with the previous occupant
|
||||||
|
-- (e.g., both at 60% HP percentage on plate pool reuse → bar stays at
|
||||||
|
-- the old fill until the new mob actually changes HP).
|
||||||
if plate.cache.name ~= name or plate.cache.guid ~= plate.cachedGuid then
|
if plate.cache.name ~= name or plate.cache.guid ~= plate.cachedGuid then
|
||||||
|
table.wipe(plate.cache)
|
||||||
plate.cache.name = name
|
plate.cache.name = name
|
||||||
plate.cache.guid = plate.cachedGuid
|
plate.cache.guid = plate.cachedGuid
|
||||||
plate.cache.player = nil
|
|
||||||
plate.cdCache = nil -- new unit, reset spell-keyed timer cache
|
plate.cdCache = nil -- new unit, reset spell-keyed timer cache
|
||||||
plate.name:SetText(GetNameString(name))
|
plate.name:SetText(GetNameString(name))
|
||||||
end
|
end
|
||||||
@@ -987,12 +992,6 @@ end
|
|||||||
-- remove unitstr on unit name mismatch
|
-- remove unitstr on unit name mismatch
|
||||||
if unitstr and UnitName(unitstr) ~= name then unitstr = nil end
|
if unitstr and UnitName(unitstr) ~= name then unitstr = nil end
|
||||||
|
|
||||||
-- use mobhealth values if addon is running
|
|
||||||
if (MobHealth3 or MobHealthFrame) and target and name == UnitName('target') and MobHealth_GetTargetCurHP() then
|
|
||||||
hp = MobHealth_GetTargetCurHP() > 0 and MobHealth_GetTargetCurHP() or hp
|
|
||||||
hpmax = MobHealth_GetTargetMaxHP() > 0 and MobHealth_GetTargetMaxHP() or hpmax
|
|
||||||
end
|
|
||||||
|
|
||||||
-- always make sure to keep plate visible
|
-- always make sure to keep plate visible
|
||||||
plate:Show()
|
plate:Show()
|
||||||
|
|
||||||
|
|||||||
+16
-49
@@ -38,38 +38,6 @@ pfUI:RegisterModule("player", function ()
|
|||||||
playerFrame.myclass = myclass
|
playerFrame.myclass = myclass
|
||||||
playerFrame.isSpellCaster = myclass ~= "WARRIOR" and myclass ~= "ROGUE" and myclass ~= "HUNTER"
|
playerFrame.isSpellCaster = myclass ~= "WARRIOR" and myclass ~= "ROGUE" and myclass ~= "HUNTER"
|
||||||
|
|
||||||
-- Compute class-based casting speed modifier and cache on the frame.
|
|
||||||
-- This is re-evaluated on LEARNED_SPELL_IN_TAB (with 1s delay) so talent changes are handled.
|
|
||||||
-- Not sure if there are any other effects that give % cast reduction time
|
|
||||||
local function UpdatePlayerModCastingTime()
|
|
||||||
playerFrame.modCastingTime = 1
|
|
||||||
if myclass == "MAGE" then
|
|
||||||
local _, _, _, _, acceleratedArcana = GetTalentInfo(1, 16)
|
|
||||||
if acceleratedArcana and acceleratedArcana > 0 then
|
|
||||||
playerFrame.modCastingTime = 0.95
|
|
||||||
end
|
|
||||||
elseif myclass == "WARLOCK" then
|
|
||||||
local _, _, _, _, rapidDeter = GetTalentInfo(1, 14)
|
|
||||||
if rapidDeter and rapidDeter > 0 then
|
|
||||||
playerFrame.modCastingTime = 1 - (rapidDeter * 0.03)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local talentFrame = CreateFrame("Frame")
|
|
||||||
talentFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
||||||
talentFrame:RegisterEvent("LEARNED_SPELL_IN_TAB")
|
|
||||||
talentFrame:SetScript("OnEvent", function()
|
|
||||||
-- Delay 1s for both PLAYER_ENTERING_WORLD and LEARNED_SPELL_IN_TAB
|
|
||||||
local checkAt = GetTime() + 1
|
|
||||||
talentFrame:SetScript("OnUpdate", function()
|
|
||||||
if GetTime() >= checkAt then
|
|
||||||
talentFrame:SetScript("OnUpdate", nil)
|
|
||||||
UpdatePlayerModCastingTime()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Convert "r,g,b,a" config color string to a 6-char hex string, or nil if unset
|
-- Convert "r,g,b,a" config color string to a 6-char hex string, or nil if unset
|
||||||
local function cfgColorToHex(colorStr)
|
local function cfgColorToHex(colorStr)
|
||||||
if not colorStr or colorStr == "" then return nil end
|
if not colorStr or colorStr == "" then return nil end
|
||||||
@@ -98,26 +66,25 @@ pfUI:RegisterModule("player", function ()
|
|||||||
if not cfg then
|
if not cfg then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local hasteMode = cfg.display_haste -- "0"=none, "1"=modCastSpeed, "2"=modCastSpeed*modCastingTime
|
-- display_haste: "0"=hidden, "1"=show modCastSpeed (gear haste). Talent-
|
||||||
|
-- side cast-time reductions show up in the actual cast bar via
|
||||||
|
-- C_Spell.UnitCastingInfo; double-folding them into this overlay was
|
||||||
|
-- mixing two different concepts into one number.
|
||||||
|
local showHaste = cfg.display_haste == "1"
|
||||||
local showSP = cfg.display_spellpower == "1"
|
local showSP = cfg.display_spellpower == "1"
|
||||||
|
|
||||||
local isSpellCaster = playerFrame.isSpellCaster
|
local isSpellCaster = playerFrame.isSpellCaster
|
||||||
if (hasteMode == "0" or not isSpellCaster) and not showSP then
|
if (not showHaste or not isSpellCaster) and not showSP then
|
||||||
playerFrame.infoTopCenterText:SetText("")
|
playerFrame.infoTopCenterText:SetText("")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local haste = GetUnitField("player", "modCastSpeed")
|
local haste = GetUnitField("player", "modCastSpeed")
|
||||||
local modCastingTime = playerFrame.modCastingTime or 1
|
|
||||||
local text = ""
|
local text = ""
|
||||||
|
|
||||||
if isSpellCaster and haste then
|
if showHaste and isSpellCaster and haste then
|
||||||
local hasteHex = cfgColorToHex(cfg.display_haste_color) or "FFFFFF"
|
local hasteHex = cfgColorToHex(cfg.display_haste_color) or "FFFFFF"
|
||||||
if hasteMode == "1" then
|
text = string.format("|cff%s%.1f%%|r", hasteHex, (1 / haste - 1) * 100)
|
||||||
text = string.format("|cff%s%.1f%%|r", hasteHex, (1 / haste - 1) * 100)
|
|
||||||
elseif hasteMode == "2" then
|
|
||||||
text = string.format("|cff%s%.1f%%|r", hasteHex, (1 / (haste * modCastingTime) - 1) * 100)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if showSP and isSpellCaster then
|
if showSP and isSpellCaster then
|
||||||
@@ -151,21 +118,21 @@ pfUI:RegisterModule("player", function ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Add throttle to player frame OnUpdate
|
-- Add throttle to player frame OnUpdate
|
||||||
|
-- Throttle the unit frame's existing OnUpdate to ~20 FPS so the per-frame
|
||||||
|
-- work stays cheap.
|
||||||
if pfUI.uf.player:GetScript("OnUpdate") then
|
if pfUI.uf.player:GetScript("OnUpdate") then
|
||||||
local originalOnUpdate = pfUI.uf.player:GetScript("OnUpdate")
|
local originalOnUpdate = pfUI.uf.player:GetScript("OnUpdate")
|
||||||
pfUI.uf.player:SetScript("OnUpdate", function()
|
pfUI.uf.player:SetScript("OnUpdate", function()
|
||||||
if (this.throttleTick or 0) > GetTime() then
|
if (this.throttleTick or 0) > GetTime() then return end
|
||||||
return
|
this.throttleTick = GetTime() + 0.05
|
||||||
end
|
|
||||||
this.throttleTick = GetTime() + 0.05 -- Default: 20 FPS
|
|
||||||
originalOnUpdate()
|
originalOnUpdate()
|
||||||
if (this.infoTextTick or 0) <= GetTime() then
|
|
||||||
this.infoTextTick = GetTime() + 0.25 -- Don't need to update haste/SP text as often
|
|
||||||
UpdateInfoText()
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Haste / spell-power overlay text — refreshes 4×/sec on its own ticker,
|
||||||
|
-- independent of the unit frame's OnUpdate cadence.
|
||||||
|
C_Timer.NewTicker(0.25, UpdateInfoText)
|
||||||
|
|
||||||
-- Replace default's RESET_INSTANCES button with an always working one
|
-- Replace default's RESET_INSTANCES button with an always working one
|
||||||
UnitPopupButtons["RESET_INSTANCES_FIX"] = { text = RESET_INSTANCES, dist = 0 }
|
UnitPopupButtons["RESET_INSTANCES_FIX"] = { text = RESET_INSTANCES, dist = 0 }
|
||||||
for id, text in pairs(UnitPopupMenus["SELF"]) do
|
for id, text in pairs(UnitPopupMenus["SELF"]) do
|
||||||
|
|||||||
+1
-1
@@ -106,7 +106,7 @@ pfUI:RegisterModule("raid", function ()
|
|||||||
this.pendingUpdate = nil
|
this.pendingUpdate = nil
|
||||||
|
|
||||||
-- don't proceed without raid
|
-- don't proceed without raid
|
||||||
if not UnitInRaid("player") then return end
|
if not IsInRaid() then return end
|
||||||
|
|
||||||
-- clear all existing frames
|
-- clear all existing frames
|
||||||
for i=1, maxraid do SetRaidIndex(pfUI.uf.raid[i], 0) end
|
for i=1, maxraid do SetRaidIndex(pfUI.uf.raid[i], 0) end
|
||||||
|
|||||||
@@ -23,6 +23,13 @@ SlashCmdList["PFDLLSTATUS"] = function()
|
|||||||
chat:AddMessage(" |cffff0000Nampower|r: Not detected")
|
chat:AddMessage(" |cffff0000Nampower|r: Not detected")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ClassicAPI
|
||||||
|
if CLASSIC_API_VERSION then
|
||||||
|
chat:AddMessage(" |cff00ff00ClassicAPI|r: v" .. CLASSIC_API_VERSION)
|
||||||
|
else
|
||||||
|
chat:AddMessage(" |cffff0000ClassicAPI|r: Not detected")
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if castbar exists for indicator positioning
|
-- Check if castbar exists for indicator positioning
|
||||||
if pfUI.castbar and pfUI.castbar.player then
|
if pfUI.castbar and pfUI.castbar.player then
|
||||||
chat:AddMessage(" |cff00ff00Castbar|r: Available for indicator anchoring")
|
chat:AddMessage(" |cff00ff00Castbar|r: Available for indicator anchoring")
|
||||||
|
|||||||
+101
-89
@@ -10,6 +10,11 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
local ON_SWING_QUEUED = 0
|
local ON_SWING_QUEUED = 0
|
||||||
local ON_SWING_QUEUE_POPPED = 1
|
local ON_SWING_QUEUE_POPPED = 1
|
||||||
|
|
||||||
|
-- Spell.dbc bits used to mirror server-side swing-reset rules.
|
||||||
|
local FLAG_AUTOATTACK = tonumber("0x08", 16) -- SPELL_INTERRUPT_FLAG_AUTOATTACK
|
||||||
|
local ATTR_KEEP_SWINGS = tonumber("0x20000", 16) -- SPELL_ATTR_EX2_NOT_RESET_AUTO_ACTIONS
|
||||||
|
local ATTR_ON_NEXT_SWING = tonumber("0x04", 16) -- SPELL_ATTR_ON_NEXT_SWING
|
||||||
|
|
||||||
-- Consolidate state into a table to avoid Lua 5.0 upvalue limit (32 max)
|
-- Consolidate state into a table to avoid Lua 5.0 upvalue limit (32 max)
|
||||||
local S = {
|
local S = {
|
||||||
mhTimer = 0, mhTimerMax = 1,
|
mhTimer = 0, mhTimerMax = 1,
|
||||||
@@ -32,51 +37,26 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
onSwingCache = {},
|
onSwingCache = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Ranged spell IDs
|
-- Wand "Shoot" runs on the ranged bar but is INDEPENDENT of the melee
|
||||||
local RANGED_SPELLIDS = {
|
-- swing clock — casters melee-weave between mainhand swings and wand
|
||||||
[75] = true, -- Auto Shot (Hunter)
|
-- fires, both timers tick concurrently. Every other ranged-auto-attack
|
||||||
[2764] = true, -- Throw (Warrior/Rogue)
|
-- (Hunter Auto Shot, any future auto-repeat ranged spell) replaces MH.
|
||||||
}
|
local WAND_SHOOT_SPELLID = 5019
|
||||||
|
local THROW_SPELLID = 2764 -- one-shot ranged, not auto-repeat
|
||||||
|
|
||||||
-- Spells that DELAY the swing timer by their cast duration but do NOT reset it.
|
-- ATTR_ON_NEXT_SWING: spell replaces next auto-attack swing.
|
||||||
-- Slam: vanilla behavior on Turtle WoW - delays swing, does not reset.
|
|
||||||
-- Hammer of Wrath: Turtle WoW changed behavior - does not reset swing timer.
|
|
||||||
local swingDelaySpells = {
|
|
||||||
[1464] = true, [8820] = true, [11604] = true, [11605] = true, -- Slam R1-R4
|
|
||||||
[24275] = true, [24274] = true, [24239] = true, -- Hammer of Wrath R1-R3
|
|
||||||
}
|
|
||||||
|
|
||||||
-- SPELL_ATTR_ON_NEXT_SWING (bit 2, value 4): spell replaces next auto-attack swing.
|
|
||||||
-- Covers Raptor Strike, Maul, Mongoose Bite, Holy Strike, etc. automatically.
|
-- Covers Raptor Strike, Maul, Mongoose Bite, Holy Strike, etc. automatically.
|
||||||
local ATTR_ON_NEXT_SWING = 4
|
|
||||||
local function IsOnSwingSpell(spellId)
|
local function IsOnSwingSpell(spellId)
|
||||||
if S.onSwingCache[spellId] ~= nil then return S.onSwingCache[spellId] end
|
if S.onSwingCache[spellId] ~= nil then return S.onSwingCache[spellId] end
|
||||||
local rec = GetSpellRec(spellId)
|
local attr = GetSpellRecField(spellId, "attributes") or 0
|
||||||
local result = rec and bit.band(rec.attributes, ATTR_ON_NEXT_SWING) ~= 0 or false
|
local result = bit.band(attr, ATTR_ON_NEXT_SWING) ~= 0
|
||||||
S.onSwingCache[spellId] = result
|
S.onSwingCache[spellId] = result
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Heroic Strike spell IDs (all ranks)
|
-- HS / Cleave / Maul are detected dynamically via IsOnSwingSpell (the
|
||||||
local hsSpellIDs = {
|
-- SPELL_ATTR_ON_NEXT_SWING bit) + name comparison against the rank-1
|
||||||
[78] = true, [284] = true, [285] = true, [1608] = true,
|
-- canonical names cached below — no per-rank ID maintenance.
|
||||||
[11564] = true, [11565] = true, [11566] = true, [11567] = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Cleave spell IDs (all ranks)
|
|
||||||
local cleaveSpellIDs = {
|
|
||||||
[845] = true, [7369] = true, [11608] = true, [11609] = true,
|
|
||||||
[20569] = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Maul spell IDs (all ranks 1 to 7)
|
|
||||||
local maulSpellIDs = {
|
|
||||||
[6807] = true,
|
|
||||||
[6808] = true,
|
|
||||||
[6809] = true,
|
|
||||||
[8972] = true,
|
|
||||||
[9745] = true, [9880] = true, [9881] = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Read config
|
-- Read config
|
||||||
local sw_width = tonumber(C.unitframes.swingtimerwidth) or 200
|
local sw_width = tonumber(C.unitframes.swingtimerwidth) or 200
|
||||||
@@ -355,14 +335,17 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
pfUI.swingtimer:Show()
|
pfUI.swingtimer:Show()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reset ranged countdown
|
-- Reset ranged countdown. replaceMH=true (Hunter Auto Shot, Throw) stops
|
||||||
local function ResetRanged()
|
-- the melee swing clock while ranged ticks; replaceMH=false (wand Shoot)
|
||||||
|
-- leaves it running for melee weaving.
|
||||||
|
local function ResetRanged(replaceMH)
|
||||||
if not sw_showranged then return end
|
if not sw_showranged then return end
|
||||||
UpdateWeaponSpeeds()
|
UpdateWeaponSpeeds()
|
||||||
if S.raSpeed <= 0 then return end
|
if S.raSpeed <= 0 then return end
|
||||||
-- Ranged replaces MH bar
|
if replaceMH then
|
||||||
S.mhActive = false
|
S.mhActive = false
|
||||||
pfUI.swingtimer.mainhand:Hide()
|
pfUI.swingtimer.mainhand:Hide()
|
||||||
|
end
|
||||||
S.raTimerMax = S.raSpeed
|
S.raTimerMax = S.raSpeed
|
||||||
S.raTimer = S.raSpeed
|
S.raTimer = S.raSpeed
|
||||||
S.raActive = true
|
S.raActive = true
|
||||||
@@ -406,11 +389,35 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
pfUI.swingtimer:Hide()
|
pfUI.swingtimer:Hide()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- HS/Cleave helpers. Canonical rank-1 spellIDs resolve to the localized
|
-- HS/Cleave/Maul helpers. Canonical rank-1 spellIDs resolve to the
|
||||||
-- spell name once, so the per-slot comparison is locale-independent without
|
-- localized spell name once, so per-spell classification is rank- and
|
||||||
-- per-rank hardcoding (every rank of Heroic Strike returns the same name).
|
-- locale-independent without per-rank ID hardcoding (every rank of
|
||||||
local HS_NAME = C_Spell.GetSpellName(78) -- Heroic Strike (Rank 1)
|
-- Heroic Strike etc. returns the same name).
|
||||||
local CLEAVE_NAME = C_Spell.GetSpellName(845) -- Cleave (Rank 1)
|
local HS_NAME = C_Spell.GetSpellName(78) -- Heroic Strike (Rank 1)
|
||||||
|
local CLEAVE_NAME = C_Spell.GetSpellName(845) -- Cleave (Rank 1)
|
||||||
|
local MAUL_NAME = C_Spell.GetSpellName(6807) -- Maul (Rank 1)
|
||||||
|
|
||||||
|
-- Classify an on-next-swing spell as "hs" / "cleave" / "maul" / nil.
|
||||||
|
-- IsOnSwingSpell gates the family (ATTR_ON_NEXT_SWING bit 0x04) so
|
||||||
|
-- unrelated spells return nil cheaply.
|
||||||
|
local function ClassifyOnSwingSpell(spellId)
|
||||||
|
if not IsOnSwingSpell(spellId) then return nil end
|
||||||
|
local name = C_Spell.GetSpellName(spellId)
|
||||||
|
if name == HS_NAME then return "hs"
|
||||||
|
elseif name == CLEAVE_NAME then return "cleave"
|
||||||
|
elseif name == MAUL_NAME then return "maul"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set the queue flags from a ClassifyOnSwingSpell result. nil = no-op
|
||||||
|
-- (preserves prior flag state when the queued spell isn't one we
|
||||||
|
-- color-code, matching the legacy table-lookup behavior).
|
||||||
|
local function SetQueuedKind(kind)
|
||||||
|
if not kind then return end
|
||||||
|
S.hsQueued = (kind == "hs")
|
||||||
|
S.cleaveQueued = (kind == "cleave")
|
||||||
|
S.maulQueued = (kind == "maul")
|
||||||
|
end
|
||||||
|
|
||||||
local function RebuildQueueSlotCache()
|
local function RebuildQueueSlotCache()
|
||||||
if not S.isWarrior or not sw_hsqueue or S.useSpellQueueEvent then return end
|
if not S.isWarrior or not sw_hsqueue or S.useSpellQueueEvent then return end
|
||||||
@@ -694,11 +701,17 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
local spellStartFrame = CreateFrame("Frame")
|
local spellStartFrame = CreateFrame("Frame")
|
||||||
spellStartFrame:RegisterEvent("SPELL_START_SELF")
|
spellStartFrame:RegisterEvent("SPELL_START_SELF")
|
||||||
spellStartFrame:SetScript("OnEvent", function()
|
spellStartFrame:SetScript("OnEvent", function()
|
||||||
if arg1 and arg1 > 0 then
|
if not (arg1 and arg1 > 0) then return end
|
||||||
S.pendingCastSpellId = arg1
|
S.pendingCastSpellId = arg1
|
||||||
-- Slam (and other delay-only spells): freeze the swing timer during cast
|
-- Freeze the swing timer for cast-time spells that DON'T reset auto-
|
||||||
-- so it pauses instead of ticking down and expiring mid-cast
|
-- attack on completion (Slam, Hammer of Wrath on Turtle, etc.) — those
|
||||||
if swingDelaySpells[arg1] and S.mhActive then
|
-- let the swing resume from where it paused. Detect dynamically via the
|
||||||
|
-- absent AUTOATTACK interrupt flag (8); spells with that bit reset on
|
||||||
|
-- SPELL_GO_SELF so freezing isn't necessary. Subsumes the old hardcoded
|
||||||
|
-- swingDelaySpells list (no list maintenance for new Slam-style spells).
|
||||||
|
if S.mhActive then
|
||||||
|
local iflags = GetSpellRecField(arg1, "interruptFlags") or 0
|
||||||
|
if bit.band(iflags, FLAG_AUTOATTACK) == 0 then
|
||||||
S.mhFrozenAt = GetTime()
|
S.mhFrozenAt = GetTime()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -718,52 +731,57 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
-- SPELL_GO hook via libdebuff
|
-- SPELL_GO hook via libdebuff
|
||||||
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
|
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
|
||||||
pfUI.libdebuff_spell_go_hooks["swingtimer"] = function(spellId)
|
pfUI.libdebuff_spell_go_hooks["swingtimer"] = function(spellId)
|
||||||
if RANGED_SPELLIDS[spellId] then
|
-- C_Spell.IsRangedAutoAttackSpell catches both Auto Shot (75) and
|
||||||
ResetRanged()
|
-- wand Shoot (5019) via Spell.dbc's AUTO_REPEAT attribute (covers
|
||||||
|
-- any future auto-repeat ranged spell automatically). Wand is the
|
||||||
|
-- one independent of the MH swing — everything else replaces it.
|
||||||
|
-- Throw isn't auto-repeat (single-shot) so it's handled explicitly.
|
||||||
|
if C_Spell.IsRangedAutoAttackSpell(spellId) then
|
||||||
|
ResetRanged(spellId ~= WAND_SHOOT_SPELLID)
|
||||||
return
|
return
|
||||||
elseif swingDelaySpells[spellId] then
|
elseif spellId == THROW_SPELLID then
|
||||||
-- Swing-delay spells (Slam, Hammer of Wrath on Turtle WoW):
|
ResetRanged(true)
|
||||||
-- Delay the swing timer by cast duration, do NOT reset it.
|
|
||||||
if S.mhFrozenAt then
|
|
||||||
local castDuration = GetTime() - S.mhFrozenAt
|
|
||||||
S.mhTimer = S.mhTimer + castDuration
|
|
||||||
S.mhTimerMax = S.mhTimerMax + castDuration
|
|
||||||
S.mhFrozenAt = nil
|
|
||||||
end
|
|
||||||
S.pendingCastSpellId = nil
|
|
||||||
return
|
return
|
||||||
elseif hsSpellIDs[spellId] or cleaveSpellIDs[spellId] or maulSpellIDs[spellId] or IsOnSwingSpell(spellId) then
|
elseif IsOnSwingSpell(spellId) then
|
||||||
S.hsQueued = false; S.cleaveQueued = false
|
-- On-next-swing ability (HS / Cleave / Maul / Raptor Strike / etc.)
|
||||||
S.maulQueued = false
|
-- — the swing fires as the spell consumes it. Drop the queued color.
|
||||||
ResetMH()
|
S.hsQueued = false; S.cleaveQueued = false; S.maulQueued = false
|
||||||
elseif cleaveSpellIDs[spellId] then
|
|
||||||
S.hsQueued = false; S.cleaveQueued = false
|
|
||||||
ResetMH()
|
ResetMH()
|
||||||
else
|
else
|
||||||
-- Any spell with interruptFlags > 0 resets the swing timer
|
-- Mirror the server rule for "does this spell reset the auto-attack
|
||||||
-- (Moonfire, Faerie Fire, Wrath, Starfire etc. - NOT Insect Swarm which has flags=0)
|
-- swing" (Spell::IsMeleeAttackResetSpell in Turtle's core):
|
||||||
local _rec = GetSpellRec(spellId)
|
-- InterruptFlags has SPELL_INTERRUPT_FLAG_AUTOATTACK (0x08)
|
||||||
if _rec and _rec.interruptFlags and _rec.interruptFlags > 0 then
|
-- AND AttributesEx2 lacks NOT_RESET_AUTO_ACTIONS (0x20000).
|
||||||
|
-- If neither path resets and we're holding a frozen-swing-during-cast
|
||||||
|
-- (mhFrozenAt set by SPELL_START_SELF for non-AUTOATTACK spells), this
|
||||||
|
-- is a Slam-style cast — push the timer forward by the cast duration
|
||||||
|
-- so the bar resumes from where it paused.
|
||||||
|
local iflags = GetSpellRecField(spellId, "interruptFlags") or 0
|
||||||
|
if bit.band(iflags, FLAG_AUTOATTACK) ~= 0
|
||||||
|
and bit.band(GetSpellRecField(spellId, "attributesEx2") or 0, ATTR_KEEP_SWINGS) == 0 then
|
||||||
if S.mhActive and S.mhSpeed > 0 then
|
if S.mhActive and S.mhSpeed > 0 then
|
||||||
UpdateWeaponSpeeds()
|
UpdateWeaponSpeeds()
|
||||||
S.mhTimerMax = S.mhSpeed
|
S.mhTimerMax = S.mhSpeed
|
||||||
S.mhTimer = S.mhSpeed
|
S.mhTimer = S.mhSpeed
|
||||||
end
|
end
|
||||||
|
if S.ohActive and S.ohSpeed > 0 then
|
||||||
|
S.ohTimerMax = S.ohSpeed
|
||||||
|
S.ohTimer = S.ohSpeed
|
||||||
|
end
|
||||||
|
elseif S.mhFrozenAt then
|
||||||
|
local castDuration = GetTime() - S.mhFrozenAt
|
||||||
|
S.mhTimer = S.mhTimer + castDuration
|
||||||
|
S.mhTimerMax = S.mhTimerMax + castDuration
|
||||||
|
S.mhFrozenAt = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
S.pendingCastSpellId = nil
|
S.pendingCastSpellId = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- SPELL_CAST_EVENT hook: HS/Cleave queue tracking
|
-- SPELL_CAST_EVENT hook: HS/Cleave/Maul queue tracking
|
||||||
pfUI.libdebuff_spell_cast_hooks = pfUI.libdebuff_spell_cast_hooks or {}
|
pfUI.libdebuff_spell_cast_hooks = pfUI.libdebuff_spell_cast_hooks or {}
|
||||||
pfUI.libdebuff_spell_cast_hooks["swingtimer"] = function(success, spellId)
|
pfUI.libdebuff_spell_cast_hooks["swingtimer"] = function(success, spellId)
|
||||||
if hsSpellIDs[spellId] then
|
SetQueuedKind(ClassifyOnSwingSpell(spellId))
|
||||||
S.hsQueued = true; S.cleaveQueued = false; S.maulQueued = false
|
|
||||||
elseif cleaveSpellIDs[spellId] then
|
|
||||||
S.cleaveQueued = true; S.hsQueued = false; S.maulQueued = false
|
|
||||||
elseif maulSpellIDs[spellId] then
|
|
||||||
S.maulQueued = true; S.hsQueued = false; S.cleaveQueued = false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -847,13 +865,7 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
local spellId = arg2 or 0
|
local spellId = arg2 or 0
|
||||||
if eventCode == ON_SWING_QUEUED then
|
if eventCode == ON_SWING_QUEUED then
|
||||||
S.useSpellQueueEvent = true
|
S.useSpellQueueEvent = true
|
||||||
if hsSpellIDs[spellId] then
|
SetQueuedKind(ClassifyOnSwingSpell(spellId))
|
||||||
S.hsQueued = true; S.cleaveQueued = false; S.maulQueued = false
|
|
||||||
elseif cleaveSpellIDs[spellId] then
|
|
||||||
S.cleaveQueued = true; S.hsQueued = false; S.maulQueued = false
|
|
||||||
elseif maulSpellIDs[spellId] then
|
|
||||||
S.maulQueued = true; S.hsQueued = false; S.cleaveQueued = false
|
|
||||||
end
|
|
||||||
elseif eventCode == ON_SWING_QUEUE_POPPED then
|
elseif eventCode == ON_SWING_QUEUE_POPPED then
|
||||||
S.hsQueued = false; S.cleaveQueued = false; S.maulQueued = false
|
S.hsQueued = false; S.cleaveQueued = false; S.maulQueued = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1182,7 +1182,7 @@ pfUI:RegisterModule("thirdparty-vanilla", function()
|
|||||||
-- use pfUI frames to draw healComm predictions
|
-- use pfUI frames to draw healComm predictions
|
||||||
local pfHookHealCommSendAddonMessage = HealComm.SendAddonMessage
|
local pfHookHealCommSendAddonMessage = HealComm.SendAddonMessage
|
||||||
function HealComm.SendAddonMessage(this, msg)
|
function HealComm.SendAddonMessage(this, msg)
|
||||||
if not UnitInRaid("player") and GetNumPartyMembers() < 1 then
|
if not IsInGroup() then
|
||||||
libpredict:ParseChatMessage(UnitName("player"), msg, "HealComm")
|
libpredict:ParseChatMessage(UnitName("player"), msg, "HealComm")
|
||||||
end
|
end
|
||||||
pfHookHealCommSendAddonMessage(this, msg)
|
pfHookHealCommSendAddonMessage(this, msg)
|
||||||
|
|||||||
+8
-8
@@ -146,14 +146,6 @@ pfUI:RegisterModule("tooltip", function ()
|
|||||||
rhp, rhpmax = hp, hpmax
|
rhp, rhpmax = hp, hpmax
|
||||||
elseif pfUI.libhealth and pfUI.libhealth.enabled then
|
elseif pfUI.libhealth and pfUI.libhealth.enabled then
|
||||||
rhp, rhpmax, estimated = pfUI.libhealth:GetUnitHealthByName(this.name, this.level, tonumber(hp), tonumber(hpmax))
|
rhp, rhpmax, estimated = pfUI.libhealth:GetUnitHealthByName(this.name, this.level, tonumber(hp), tonumber(hpmax))
|
||||||
elseif MobHealthFrame then
|
|
||||||
local index = (this.name or "") .. ":" .. (this.level or "")
|
|
||||||
local ppp = MobHealth_PPP(index)
|
|
||||||
if perc and ppp and ppp > 0 and not UnitIsUnit("mouseover", "pet") then
|
|
||||||
rhp = round(hp * ppp)
|
|
||||||
rhpmax = round(100 * ppp)
|
|
||||||
estimated = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if C.tooltip.alwaysperc == "0" and ( estimated or hpmax > 100 or round(hpmax/100*hp) ~= hp ) then
|
if C.tooltip.alwaysperc == "0" and ( estimated or hpmax > 100 or round(hpmax/100*hp) ~= hp ) then
|
||||||
@@ -241,6 +233,14 @@ pfUI:RegisterModule("tooltip", function ()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if C.tooltip.movespeed == "1" then
|
||||||
|
local currentSpeed = GetUnitSpeed(unit)
|
||||||
|
if currentSpeed and currentSpeed > 0 then
|
||||||
|
local pct = floor(currentSpeed / 7 * 100 + 0.5)
|
||||||
|
GameTooltip:AddLine(T["Speed"] .. ": " .. pct .. "%", 0.7, 0.7, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if hp and hpm then
|
if hp and hpm then
|
||||||
if hp >= 1000 then hp = round(hp / 1000, 1) .. "k" end
|
if hp >= 1000 then hp = round(hp / 1000, 1) .. "k" end
|
||||||
if hpm >= 1000 then hpm = round(hpm / 1000, 1) .. "k" end
|
if hpm >= 1000 then hpm = round(hpm / 1000, 1) .. "k" end
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pfUI:RegisterModule("turtle-wow", function ()
|
|||||||
-- Check if pfUI is handling group or raid for the current situation
|
-- Check if pfUI is handling group or raid for the current situation
|
||||||
local function pfUIHandlesGroupOrRaid()
|
local function pfUIHandlesGroupOrRaid()
|
||||||
local disabled = C["disabled"] or {}
|
local disabled = C["disabled"] or {}
|
||||||
if GetNumRaidMembers() > 0 then
|
if IsInRaid() then
|
||||||
if not C.unitframes.raid then return false end
|
if not C.unitframes.raid then return false end
|
||||||
-- Hide Turtle frames if: pfUI raid module is active, OR player disabled visibility
|
-- Hide Turtle frames if: pfUI raid module is active, OR player disabled visibility
|
||||||
if disabled["raid"] == "1" then
|
if disabled["raid"] == "1" then
|
||||||
|
|||||||
@@ -2,25 +2,13 @@ pfUI:RegisterSkin("Character", function ()
|
|||||||
local rawborder, border = GetBorderSize()
|
local rawborder, border = GetBorderSize()
|
||||||
local bpad = rawborder > 1 and border - GetPerfectPixel() or GetPerfectPixel()
|
local bpad = rawborder > 1 and border - GetPerfectPixel() or GetPerfectPixel()
|
||||||
|
|
||||||
-- Compatibility
|
-- Honor Tab
|
||||||
if PlayerTitleDropDown then -- tbc, wotlk
|
StripTextures(HonorFrame)
|
||||||
-- Character Tab
|
StripTextures(ArenaFrame)
|
||||||
SkinDropDown(PlayerTitleDropDown)
|
|
||||||
PlayerTitleDropDown:SetPoint("TOP", CharacterLevelText, "BOTTOM", 0, -2)
|
|
||||||
PlayerTitleDropDownText:SetPoint("LEFT", PlayerTitleDropDown.backdrop, "LEFT", 6, 2)
|
|
||||||
SkinDropDown(PlayerStatFrameLeftDropDown)
|
|
||||||
SkinDropDown(PlayerStatFrameRightDropDown)
|
|
||||||
|
|
||||||
-- Honor Tab
|
HonorFrameProgressBar:SetStatusBarTexture(pfUI.media["img:bar"])
|
||||||
StripTextures(PVPFrame)
|
CreateBackdrop(HonorFrameProgressBar)
|
||||||
else -- vanilla
|
HonorFrameProgressBar:SetHeight(24)
|
||||||
-- Honor Tab
|
|
||||||
StripTextures(HonorFrame)
|
|
||||||
|
|
||||||
HonorFrameProgressBar:SetStatusBarTexture(pfUI.media["img:bar"])
|
|
||||||
CreateBackdrop(HonorFrameProgressBar)
|
|
||||||
HonorFrameProgressBar:SetHeight(24)
|
|
||||||
end
|
|
||||||
|
|
||||||
local magicResTextureCords = {
|
local magicResTextureCords = {
|
||||||
{0.21875, 0.78125, 0.25, 0.3203125},
|
{0.21875, 0.78125, 0.25, 0.3203125},
|
||||||
|
|||||||
Reference in New Issue
Block a user