mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
Add ClassicAPI dispel-type conditionals via C_UnitAuras
Introduce ClassicAPI.lua, a feature-detection layer for the ClassicAPI client mod that mirrors NampowerAPI's HasMinimumVersion pattern (IsAvailable / HasMinimumVersion / HasUnitAuras). UnitHasDispelType scans a unit's auras via C_UnitAuras and reports the dispel type, scanning debuffs or buffs based on a helpful flag. Add conditionals backed by it: - Debuff side (defensive cleanse): [magic] [curse] [disease] [poison] [dispellable] + negations - Buff side (offensive dispel/strip): [magicbuff] [dispellablebuff] + negations All are no-arg booleans, default to @target (honor @unit), and degrade gracefully without ClassicAPI: positive checks return false, negated return true, since vanilla cannot read aura dispel types. The existing ValidateAura path is untouched. MacroErrorChecker auto-accepts them via the Keywords table; they're registered in BOOLEAN_CONDITIONALS so they parse as flags. Loaded after NampowerAPI in the TOC.
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
--[[
|
||||
ClassicAPI.lua - ClassicAPI Integration Layer
|
||||
|
||||
ClassicAPI is a client mod (sibling to Nampower/SuperWoW) that backports the
|
||||
modern C_* API into the 1.12.1 Lua environment. This module provides feature
|
||||
detection and thin wrappers so every ClassicAPI-backed code path can fall
|
||||
back gracefully when the DLL is absent, mirroring NampowerAPI's
|
||||
HasMinimumVersion pattern.
|
||||
|
||||
Detection: the global CLASSIC_API_VERSION is defined once the client has
|
||||
booted, encoded as X*10000 + Y*100 + Z for a vX.Y.Z tag (untagged dev builds
|
||||
report the sentinel 99999999). See ClassicAPI docs/API.md.
|
||||
|
||||
Currently used for:
|
||||
- C_UnitAuras: dispel-type detection (Magic/Curse/Disease/Poison) on any unit,
|
||||
powering the [magic]/[curse]/[disease]/[poison]/[dispellable] conditionals.
|
||||
]]
|
||||
|
||||
local _G = _G or getfenv(0)
|
||||
local CleveRoids = _G.CleveRoids
|
||||
|
||||
-- Force table creation if not already a table (guards against addon conflicts)
|
||||
if type(CleveRoids.ClassicAPI) ~= "table" then
|
||||
CleveRoids.ClassicAPI = {}
|
||||
end
|
||||
local API = CleveRoids.ClassicAPI
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- VERSION DETECTION
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Returns the encoded version number (X*10000 + Y*100 + Z), or 0 if absent.
|
||||
function API.GetVersionNumber()
|
||||
return CLASSIC_API_VERSION or 0
|
||||
end
|
||||
|
||||
-- True if the ClassicAPI client mod is loaded at all.
|
||||
function API.IsAvailable()
|
||||
return CLASSIC_API_VERSION ~= nil
|
||||
end
|
||||
|
||||
-- Check if the loaded ClassicAPI meets a minimum version (major, minor, patch).
|
||||
function API.HasMinimumVersion(reqMajor, reqMinor, reqPatch)
|
||||
local v = CLASSIC_API_VERSION
|
||||
if not v then return false end
|
||||
local req = (reqMajor or 0) * 10000 + (reqMinor or 0) * 100 + (reqPatch or 0)
|
||||
return v >= req
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- C_UnitAuras
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Cached capability flag (C_UnitAuras is injected by the DLL before addons load).
|
||||
local _hasUnitAuras = nil
|
||||
function API.HasUnitAuras()
|
||||
if _hasUnitAuras == nil then
|
||||
_hasUnitAuras = (type(C_UnitAuras) == "table"
|
||||
and type(C_UnitAuras.GetDebuffDataByIndex) == "function"
|
||||
and type(C_UnitAuras.GetBuffDataByIndex) == "function") or false
|
||||
end
|
||||
return _hasUnitAuras
|
||||
end
|
||||
|
||||
-- Module-level scan (passed to pcall with args to avoid per-call closure alloc).
|
||||
-- indexFn is C_UnitAuras.GetBuffDataByIndex or GetDebuffDataByIndex.
|
||||
-- Vanilla descriptors hold 32 helpful / 16 harmful slots; cap as a backstop.
|
||||
local function scanDispel(indexFn, unit, dispelType, wantAny)
|
||||
local i = 1
|
||||
while i <= 48 do
|
||||
local data = indexFn(unit, i)
|
||||
if not data then return false end
|
||||
local dn = data.dispelName
|
||||
if dn and dn ~= "" and (wantAny or dn == dispelType) then
|
||||
return true
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- True if `unit` has an aura of the given dispel type.
|
||||
-- dispelType: "Magic" | "Curse" | "Disease" | "Poison", or "any"/nil for any
|
||||
-- dispellable aura (any non-empty dispelName).
|
||||
-- helpful: true -> scan buffs (offensive dispel / strip / purge)
|
||||
-- false -> scan debuffs (defensive cleanse, default)
|
||||
-- Returns false (never errors) when ClassicAPI/C_UnitAuras is unavailable or the
|
||||
-- unit doesn't exist, so callers degrade gracefully.
|
||||
function API.UnitHasDispelType(unit, dispelType, helpful)
|
||||
if not unit then return false end
|
||||
if not API.HasUnitAuras() then return false end
|
||||
if not UnitExists(unit) then return false end
|
||||
|
||||
local indexFn = helpful and C_UnitAuras.GetBuffDataByIndex
|
||||
or C_UnitAuras.GetDebuffDataByIndex
|
||||
local wantAny = (dispelType == nil or dispelType == "any")
|
||||
local ok, found = pcall(scanDispel, indexFn, unit, dispelType, wantAny)
|
||||
return (ok and found) or false
|
||||
end
|
||||
@@ -6515,6 +6515,87 @@ CleveRoids.Keywords = {
|
||||
end, conditionals, "nomydebuff")
|
||||
end,
|
||||
|
||||
-- Dispel-type conditionals (ClassicAPI C_UnitAuras).
|
||||
-- [magic]/[curse]/[disease]/[poison] = target has a debuff of that dispel
|
||||
-- type; [dispellable] = target has any dispellable debuff. These require the
|
||||
-- ClassicAPI client mod; without it the positive checks return false and the
|
||||
-- negated checks return true (graceful degradation — vanilla cannot read
|
||||
-- aura dispel types). They honor @unit like [debuff] does.
|
||||
magic = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Magic")
|
||||
end,
|
||||
|
||||
nomagic = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Magic")
|
||||
end,
|
||||
|
||||
curse = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Curse")
|
||||
end,
|
||||
|
||||
nocurse = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Curse")
|
||||
end,
|
||||
|
||||
disease = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Disease")
|
||||
end,
|
||||
|
||||
nodisease = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Disease")
|
||||
end,
|
||||
|
||||
poison = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Poison")
|
||||
end,
|
||||
|
||||
nopoison = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Poison")
|
||||
end,
|
||||
|
||||
dispellable = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "any")
|
||||
end,
|
||||
|
||||
nodispellable = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "any")
|
||||
end,
|
||||
|
||||
-- Buff-side dispel-type conditionals (offensive dispel / strip / purge).
|
||||
-- [magicbuff] = unit has a dispellable Magic buff (the only kind offensive
|
||||
-- dispel removes in 1.12); [dispellablebuff] = unit has any dispel-typed
|
||||
-- buff. Same ClassicAPI requirement and graceful degradation as the debuff
|
||||
-- variants. The `true` arg makes UnitHasDispelType scan buffs, not debuffs.
|
||||
magicbuff = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Magic", true)
|
||||
end,
|
||||
|
||||
nomagicbuff = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "Magic", true)
|
||||
end,
|
||||
|
||||
dispellablebuff = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "any", true)
|
||||
end,
|
||||
|
||||
nodispellablebuff = function(conditionals)
|
||||
if not conditionals.target then return false end
|
||||
return not CleveRoids.ClassicAPI.UnitHasDispelType(conditionals.target, "any", true)
|
||||
end,
|
||||
|
||||
power = function(conditionals)
|
||||
return Multi(conditionals.power, function(args)
|
||||
if type(args) ~= "table" then return false end
|
||||
|
||||
@@ -152,6 +152,21 @@ local BOOLEAN_CONDITIONALS = {
|
||||
nopet = true,
|
||||
bg = true,
|
||||
nobg = true,
|
||||
-- Dispel-type conditionals (ClassicAPI C_UnitAuras)
|
||||
magic = true,
|
||||
nomagic = true,
|
||||
curse = true,
|
||||
nocurse = true,
|
||||
disease = true,
|
||||
nodisease = true,
|
||||
poison = true,
|
||||
nopoison = true,
|
||||
dispellable = true,
|
||||
nodispellable = true,
|
||||
magicbuff = true,
|
||||
nomagicbuff = true,
|
||||
dispellablebuff = true,
|
||||
nodispellablebuff = true,
|
||||
}
|
||||
|
||||
local requirementCheckFrame = CreateFrame("Frame")
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
Localization.lua
|
||||
Init.lua
|
||||
NampowerAPI.lua
|
||||
ClassicAPI.lua
|
||||
Utility.lua
|
||||
Core.lua
|
||||
Conditionals.lua
|
||||
|
||||
+25
-3
@@ -20,16 +20,38 @@ API references are line numbers into `C:\Git\ClassicAPI\docs\API.md`.
|
||||
`applications` (stacks), `duration`.
|
||||
- **Unlocks:** `[dispellable]` / `[curse]` / `[magic]` target conditionals and
|
||||
spellID-based (rank/locale-proof) aura matching.
|
||||
- **Replaces today:** pfUI libdebuff + tooltip scanning (`Conditionals.lua:1815+`).
|
||||
- **Caveat:** `expirationTime` is only populated for `unit=="player"`; it's `0`
|
||||
for target/focus (vanilla server limitation). Target debuff *timers* still
|
||||
need the existing libdebuff tracking — only presence/stacks/school/spellId
|
||||
are reliable cross-unit.
|
||||
|
||||
- **DONE (slice 1 — dispel-type conditionals):** added `ClassicAPI.lua`
|
||||
detection module (`CleveRoids.ClassicAPI`, mirrors NampowerAPI's
|
||||
`HasMinimumVersion`) and the `[magic]`/`[curse]`/`[disease]`/`[poison]`/
|
||||
`[dispellable]` conditionals + negations, backed by
|
||||
`C_UnitAuras.GetDebuffDataByIndex(...).dispelName`. No-arg booleans, honor
|
||||
`@unit`, graceful fallback (positive→false, negated→true) when ClassicAPI is
|
||||
absent. Purely additive — the existing `ValidateAura` path is untouched.
|
||||
- **DONE (slice 2 — buff-side / offensive dispel):** `UnitHasDispelType` now
|
||||
takes a `helpful` flag (scans `GetBuffDataByIndex`), exposed as
|
||||
`[magicbuff]`/`[dispellablebuff]` + negations — detect a dispellable buff to
|
||||
strip off an enemy (e.g. `[harm,magicbuff] Dispel Magic`). Magic-only is the
|
||||
practical set since 1.12 offensive dispel removes Magic buffs.
|
||||
- **Follow-ups (still TODO):**
|
||||
- spellID-based aura matching via `GetUnitAuraBySpellID` (rank/locale-proof),
|
||||
optionally wired into `ValidateAura` as a fast path with libdebuff fallback.
|
||||
- more reliable cross-unit stacks via `applications`.
|
||||
- class-aware `[dispellable]` (only types this character can actually remove).
|
||||
- optional name filtering on the type keywords (e.g. `[magic:Polymorph]`).
|
||||
|
||||
### 2. `C_Item.GetWeaponEnchantInfo()` — temp-enchant IDs
|
||||
- **API:** `API.md:7159` — returns 12-tuple including `enchantID` for main/off/ranged.
|
||||
- **Unlocks:** `[poison:<id>]` / `[weaponenchant:<id>]` conditionals — detect
|
||||
*which* poison/oil/sharpening stone is applied, not just that one exists.
|
||||
- **Unlocks:** detect *which* temp enchant (poison/oil/sharpening stone) is
|
||||
applied to a weapon, not just that one exists.
|
||||
- **Naming:** `[poison]` is now taken by the target dispel-type conditional
|
||||
(slice 1 above). Use weapon-specific keywords for this — e.g.
|
||||
`[mhenchant:<id>]` / `[ohenchant:<id>]` (or `[mhpoison:<id>]`/`[ohpoison:<id>]`),
|
||||
not a bare `[poison]`.
|
||||
- Vanilla's global only reports presence; this is a genuinely new capability
|
||||
(rogue/shaman/enhance).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user