pfui nameplate tank list support for targeting conditional

This commit is contained in:
Jrc13245
2026-01-24 17:12:08 -05:00
parent 6199279272
commit 50a29e0fee
3 changed files with 301 additions and 5 deletions
+164 -4
View File
@@ -2198,6 +2198,110 @@ function CleveRoids.GetCountModeArgs(conditionalValue)
return nil
end
-- ============================================================================
-- PFUI TANK INTEGRATION
-- ============================================================================
-- Integrates with pfUI's tank systems for targeting loose mobs
-- Checks BOTH:
-- 1. pfUI.uf.raid.tankrole (raid frame right-click toggle)
-- 2. pfUI_config.nameplates.combatofftanks (nameplate off-tank names setting)
-- Cache for parsed nameplate off-tank names (lowercase)
local pfUIOfftankCache = nil
local pfUIOfftankCacheTime = 0
--- Parse pfUI nameplate off-tank names setting into a lookup table
--- @return table Lowercase name -> true lookup
local function GetPfUIOfftanks()
-- Cache for 5 seconds to avoid repeated string parsing
local now = GetTime()
if pfUIOfftankCache and (now - pfUIOfftankCacheTime) < 5 then
return pfUIOfftankCache
end
pfUIOfftankCache = {}
pfUIOfftankCacheTime = now
-- Check pfUI_config.nameplates.combatofftanks (# separated list)
if type(pfUI_config) == "table" and
type(pfUI_config.nameplates) == "table" and
type(pfUI_config.nameplates.combatofftanks) == "string" then
local list = pfUI_config.nameplates.combatofftanks
-- pfUI uses # as separator: "#Name1#Name2#Name3"
for name in string.gfind(list, "[^#]+") do
name = string.gsub(name, "^%s*(.-)%s*$", "%1") -- trim whitespace
if name ~= "" then
pfUIOfftankCache[string.lower(name)] = true
end
end
end
return pfUIOfftankCache
end
--- Check if pfUI tank data is available (either source)
--- @return boolean True if any pfUI tank system is accessible
function CleveRoids.HasPfUITanks()
-- Check raid frame tankrole
local hasRaidTanks = type(pfUI) == "table" and
type(pfUI.uf) == "table" and
type(pfUI.uf.raid) == "table" and
type(pfUI.uf.raid.tankrole) == "table"
-- Check nameplate off-tank config
local hasNameplateTanks = type(pfUI_config) == "table" and
type(pfUI_config.nameplates) == "table" and
type(pfUI_config.nameplates.combatofftanks) == "string" and
pfUI_config.nameplates.combatofftanks ~= ""
return hasRaidTanks or hasNameplateTanks
end
--- Check if a player is marked as a tank in pfUI (either source)
--- @param name string - Player name to check
--- @return boolean True if player is marked as tank
function CleveRoids.IsPlayerTank(name)
if not name then return false end
-- Check raid frame tankrole (exact case)
if type(pfUI) == "table" and
type(pfUI.uf) == "table" and
type(pfUI.uf.raid) == "table" and
type(pfUI.uf.raid.tankrole) == "table" and
pfUI.uf.raid.tankrole[name] then
return true
end
-- Check nameplate off-tank names (lowercase comparison)
local offtanks = GetPfUIOfftanks()
if offtanks[string.lower(name)] then
return true
end
return false
end
--- Check if a unit is targeting any player marked as tank
--- @param unit string - Unit token to check (e.g., "target")
--- @return boolean True if unit's target is a tank
function CleveRoids.IsTargetingAnyTank(unit)
-- Default to "target" if unit is nil
unit = unit or "target"
-- Get the unit's target
local targetOfUnit = unit .. "target"
if not UnitExists(targetOfUnit) then
return false
end
local targetName = UnitName(targetOfUnit)
if not targetName then
return false
end
return CleveRoids.IsPlayerTank(targetName)
end
-- ============================================================================
-- CURSIVE ADDON INTEGRATION
-- ============================================================================
@@ -5098,15 +5202,41 @@ CleveRoids.Keywords = {
return true
end,
-- [targeting:unit] - Target is targeting specified unit
-- [targeting:tank] - Target is targeting ANY player marked as tank in pfUI
targeting = function(conditionals)
return Or(conditionals.targeting, function (unit)
return (UnitIsUnit("targettarget", unit) == 1)
local target = conditionals.target or "target"
-- Handle single "tank" keyword directly (most common case)
local val = conditionals.targeting
if val == "tank" or (type(val) == "table" and val[1] == "tank" and not val[2]) then
return CleveRoids.IsTargetingAnyTank(target)
end
return Or(val, function (unit)
if unit == "tank" then
return CleveRoids.IsTargetingAnyTank(target)
end
return (UnitIsUnit(target .. "target", unit) == 1)
end)
end,
-- [notargeting:unit] - Target is NOT targeting specified unit
-- [notargeting:tank] - Target is NOT targeting ANY tank (loose mob!)
notargeting = function(conditionals)
return NegatedMulti(conditionals.notargeting, function (unit)
return UnitIsUnit("targettarget", unit) ~= 1
local target = conditionals.target or "target"
-- Handle single "tank" keyword directly (most common case)
local val = conditionals.notargeting
if val == "tank" or (type(val) == "table" and val[1] == "tank" and not val[2]) then
return not CleveRoids.IsTargetingAnyTank(target)
end
return NegatedMulti(val, function (unit)
if unit == "tank" then
return not CleveRoids.IsTargetingAnyTank(target)
end
return UnitIsUnit(target .. "target", unit) ~= 1
end, conditionals, "notargeting")
end,
@@ -5128,6 +5258,36 @@ CleveRoids.Keywords = {
return UnitIsPlayer(conditionals.target)
end,
-- [istank] - Target unit is marked as tank in pfUI
-- [istank:unit] - Specified unit is marked as tank
istank = function(conditionals)
if conditionals.istank and type(conditionals.istank) == "table" then
-- Check specific unit: [istank:focus]
return Or(conditionals.istank, function(unit)
local name = UnitName(unit)
return CleveRoids.IsPlayerTank(name)
end)
end
-- Check target: [istank]
local target = conditionals.target or "target"
local name = UnitName(target)
return CleveRoids.IsPlayerTank(name)
end,
-- [noistank] - Target unit is NOT marked as tank in pfUI
noistank = function(conditionals)
if conditionals.noistank and type(conditionals.noistank) == "table" then
-- Check specific unit: [noistank:focus]
return NegatedMulti(conditionals.noistank, function(unit)
return not CleveRoids.IsPlayerTank(UnitName(unit))
end, conditionals, "noistank")
end
-- Check target: [noistank]
local target = conditionals.target or "target"
local name = UnitName(target)
return not CleveRoids.IsPlayerTank(name)
end,
-- [inrange] or [inrange:Spell] - Target is in range of spell
-- [inrange:Spell>N] - More than N enemies are in range of spell (count mode)
inrange = function(conditionals)
+90
View File
@@ -5312,6 +5312,8 @@ SlashCmdList["CLEVEROID"] = function(msg)
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testtalent <spellID> - Test talent modifier for a spell')
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Debuff Tracking Debug:|r")
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid debuffdebug [spell] - Debug debuff tracking on target')
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00pfUI Tank Integration:|r")
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid tankdebug - Debug tank targeting conditionals')
return
end
@@ -5883,6 +5885,94 @@ SlashCmdList["CLEVEROID"] = function(msg)
return
end
-- tankdebug (debug pfUI tank integration)
if cmd == "tankdebug" then
CleveRoids.Print("=== Tank Debug ===")
-- Check pfUI availability
if not CleveRoids.HasPfUITanks() then
CleveRoids.Print("|cffff0000pfUI tank system not available!|r")
CleveRoids.Print(" pfUI loaded: " .. tostring(type(pfUI) == "table"))
CleveRoids.Print(" pfUI_config: " .. tostring(type(pfUI_config) == "table"))
return
end
CleveRoids.Print("|cff00ff00pfUI tank system available|r")
-- List raid frame tanks
CleveRoids.Print(" ")
CleveRoids.Print("|cffffaa00Raid Frame Tanks (right-click toggle):|r")
local raidTankCount = 0
if type(pfUI) == "table" and type(pfUI.uf) == "table" and
type(pfUI.uf.raid) == "table" and type(pfUI.uf.raid.tankrole) == "table" then
for name, isTank in pairs(pfUI.uf.raid.tankrole) do
if isTank then
CleveRoids.Print(" - " .. name)
raidTankCount = raidTankCount + 1
end
end
end
if raidTankCount == 0 then
CleveRoids.Print(" (none)")
end
-- List nameplate off-tank names
CleveRoids.Print(" ")
CleveRoids.Print("|cffffaa00Nameplate Off-Tank Names (config setting):|r")
local npTankCount = 0
if type(pfUI_config) == "table" and type(pfUI_config.nameplates) == "table" then
local list = pfUI_config.nameplates.combatofftanks or ""
if list ~= "" then
CleveRoids.Print(" Raw setting: \"" .. list .. "\"")
-- pfUI uses # as separator
for name in string.gfind(list, "[^#]+") do
name = string.gsub(name, "^%s*(.-)%s*$", "%1") -- trim
if name ~= "" then
CleveRoids.Print(" - " .. name .. " (lowercase: " .. string.lower(name) .. ")")
npTankCount = npTankCount + 1
end
end
end
end
if npTankCount == 0 then
CleveRoids.Print(" (none)")
end
-- Check current target
CleveRoids.Print(" ")
CleveRoids.Print("|cffffaa00Current Target Check:|r")
if not UnitExists("target") then
CleveRoids.Print(" No target selected")
else
local targetName = UnitName("target") or "Unknown"
CleveRoids.Print(" Your target: " .. targetName)
if UnitExists("targettarget") then
local ttName = UnitName("targettarget") or "Unknown"
CleveRoids.Print(" Target's target: " .. ttName)
local isTank = CleveRoids.IsPlayerTank(ttName)
if isTank then
CleveRoids.Print(" |cff00ff00" .. ttName .. " IS marked as tank|r")
else
CleveRoids.Print(" |cffff8800" .. ttName .. " is NOT marked as tank|r")
CleveRoids.Print(" (lowercase check: " .. string.lower(ttName) .. ")")
end
else
CleveRoids.Print(" Target's target: (none)")
end
-- Test the conditional functions
CleveRoids.Print(" ")
CleveRoids.Print("|cffffaa00Conditional Results:|r")
local isTargetingTank = CleveRoids.IsTargetingAnyTank("target")
CleveRoids.Print(" IsTargetingAnyTank('target'): " .. tostring(isTargetingTank))
CleveRoids.Print(" [targeting:tank] would be: " .. tostring(isTargetingTank))
CleveRoids.Print(" [notargeting:tank] would be: " .. tostring(not isTargetingTank))
end
return
end
-- Unknown command fallback
CleveRoids.Print("Usage:")
DEFAULT_CHAT_FRAME:AddMessage("/cleveroid - Show current settings")
+47 -1
View File
@@ -132,7 +132,8 @@ All conditionals support negation with `no` prefix (e.g., `[nocombat]`, `[nobuff
| `type` | `[type:Undead/Beast]` | Creature type |
| `isplayer` | `[isplayer]` | Target is a player |
| `isnpc` | `[isnpc]` | Target is an NPC |
| `targeting` | `[targeting:player]` | Unit targeting you |
| `targeting` | `[targeting:player]` `[targeting:tank]` | Unit targeting you / any tank |
| `istank` | `[istank]` `[@focus,istank]` | Unit is marked as tank (pfUI) |
| `casting` | `[casting:"Spell"]` | Unit casting spell |
| `party` | `[party]` `[party:focus]` | Unit in your party |
| `raid` | `[raid]` `[raid:mouseover]` | Unit in your raid |
@@ -211,6 +212,50 @@ All conditionals support negation with `no` prefix (e.g., `[nocombat]`, `[nobuff
| `tte` | TimeToKill | `[tte:<5]` | Time to execute (20% HP) |
| `cursive` | Cursive | `[cursive:Rake>3]` | GUID debuff tracking |
| `moving` | MonkeySpeed | `[moving:>100]` | Speed % (100=normal run) |
| `targeting:tank` | pfUI | `[targeting:tank]` | Target is attacking any tank |
| `istank` | pfUI | `[istank]` | Target is marked as tank |
### pfUI Tank Integration
Identify loose mobs in trash pulls by checking if enemies are targeting designated tanks. Works with pfUI's tank marking systems.
**Tank Conditionals:**
| Conditional | Description |
|-------------|-------------|
| `[targeting:tank]` | Target IS attacking any player marked as tank |
| `[notargeting:tank]` | Target is NOT attacking any tank (loose mob!) |
| `[istank]` | Target unit IS marked as tank |
| `[noistank]` | Target unit is NOT marked as tank |
**Setting Up Tanks in pfUI:**
1. **Nameplate Off-Tank Names** (recommended): `/pfui` → Nameplates → Off-Tank Names
- Add tank names separated by `#`: `#TankName1#TankName2#TankName3`
- These names will show different colored nameplates AND work with `[targeting:tank]`
2. **Raid Frame Toggle**: Right-click a player in raid frames → "Toggle as Tank"
- Only works when raid frames are visible
**Example Macros:**
```lua
-- Pick up loose mobs (not targeting any tank)
/cast [multiscan:nearest,notargeting:tank,harm] Taunt
-- Only taunt if mob is targeting you (tank)
/cast [targeting:player] Sunder Armor
-- Assist tanks - attack what they're tanking
/cast [multiscan:nearest,targeting:tank,harm] Sunder Armor
-- Emergency taunt on loose mob hitting a healer
/cast [notargeting:tank,notargeting:player] Taunt
```
**Debug Command:**
```
/cleveroid tankdebug
```
Shows all marked tanks, current target info, and conditional results.
### Warrior Slam Conditionals
For optimizing Slam rotations without clipping auto-attacks:
@@ -294,6 +339,7 @@ Scans enemies and soft-casts without changing your target. Requires UnitXP_SP3.
/cast [multiscan:skull,harm] Eviscerate
/cast [multiscan:markorder] Sinister Strike
/cast [multiscan:highesthp,noimmune:stun] Cheap Shot
/cast [multiscan:nearest,notargeting:tank,harm] Taunt -- Pick up loose mobs (pfUI)
```
**Priorities:**