From 2cf4886b0154b54346a6646dad875bc969494c03 Mon Sep 17 00:00:00 2001 From: Brues <5278969+brues-code@users.noreply.github.com> Date: Mon, 27 Jul 2026 20:10:20 -0500 Subject: [PATCH] Add [mana]/[rage]/[energy] type-specific power conditionals Read a SPECIFIC power slot (Enum.PowerType) as a percentage via ClassicAPI UnitPower/UnitPowerMax, rather than the unit's primary power. Adds mana/ mymana, rage/myrage, energy/myenergy (no-prefix = target, @unit-overridable; my = player), each supporting operators and multi-comparison like [power]/ [mypower]. Works cross-form (druid mana in Cat) and cross-unit -- the standout being [@target,mana:<15] to catch a caster near OOM. A unit with no such pool (max <= 0) fails rather than reading 0%. Registered in the macro error checker (needsArgs + operator hint); VALID_CONDITIONALS auto-populates from Keywords. --- Conditionals.lua | 58 +++++++++++++++++++++++++++++++++++++++++++ MacroErrorChecker.lua | 4 +++ 2 files changed, 62 insertions(+) diff --git a/Conditionals.lua b/Conditionals.lua index 58adce5..5bd365b 100644 --- a/Conditionals.lua +++ b/Conditionals.lua @@ -3310,6 +3310,26 @@ function CleveRoids.ValidatePower(unit, operator, amount) return false end +-- Validates a SPECIFIC power slot (Enum.PowerType: 0=Mana, 1=Rage, 3=Energy) as a +-- percentage, regardless of the unit's primary power -- so [mana]/[energy]/[rage] +-- read the right pool cross-form (druid mana in cat) and cross-unit (@target mana). +-- A unit with no such pool (max <= 0) fails rather than reading as 0% (avoids a +-- rageless caster satisfying [rage:<10]). +function CleveRoids.ValidateTypedPower(unit, powerType, operator, amount) + if not unit or not operator or not amount then return false end + if not UnitExists(unit) then return false end + local API = CleveRoids.ClassicAPI + local maxPower = API.UnitPowerMax(unit, powerType) + if not maxPower or maxPower <= 0 then return false end + local powerPercent = 100 * API.UnitPower(unit, powerType) / maxPower + + if CleveRoids.operators[operator] then + return CleveRoids.comparators[operator](powerPercent, amount) + end + + return false +end + -- Checks whether or not the given unit has current power vs the given amount -- unit: The unit we're checking -- operator: valid comparitive operator symbol @@ -5411,6 +5431,33 @@ local function ResolveFocusUnit(unit) return unit end +-- Builds a Keyword validator for a specific power slot (Enum.PowerType) read as a +-- percentage, mirroring [power]/[mypower]. condKey is the conditional name; +-- unitDefault is "player" (self) or "target" (@unit-overridable); powerType is the +-- Enum.PowerType id. Handles the multi-comparison (>50&<80) branch like [power]. +local function MakeTypedPowerKeyword(condKey, unitDefault, powerType) + return function(conditionals) + return Multi(conditionals[condKey], function(args) + if type(args) ~= "table" then return false end + local unit = (unitDefault == "player") and "player" or (conditionals.target or "target") + + if args.comparisons and type(args.comparisons) == "table" then + if not UnitExists(unit) then return false end + local maxPower = CleveRoids.ClassicAPI.UnitPowerMax(unit, powerType) + if not maxPower or maxPower <= 0 then return false end + local powerPercent = 100 * CleveRoids.ClassicAPI.UnitPower(unit, powerType) / maxPower + for _, comp in ipairs(args.comparisons) do + if not CleveRoids.operators[comp.operator] then return false end + if not CleveRoids.comparators[comp.operator](powerPercent, comp.amount) then return false end + end + return true + end + + return CleveRoids.ValidateTypedPower(unit, powerType, args.operator, args.amount) + end, conditionals, condKey) + end +end + -- A list of Conditionals and their functions to validate them CleveRoids.Keywords = { exists = function(conditionals) @@ -6257,6 +6304,17 @@ CleveRoids.Keywords = { end, conditionals, "mypower") end, + -- Type-specific power reads (percentage), for the SPECIFIC slot rather than the + -- unit's primary power. No prefix = target (@unit-overridable), my = player. + -- e.g. [@target,mana:<15] catches a near-OOM caster; [myenergy:>50] gates a + -- druid's cat rotation regardless of form. + mana = MakeTypedPowerKeyword("mana", "target", 0), + mymana = MakeTypedPowerKeyword("mymana", "player", 0), + rage = MakeTypedPowerKeyword("rage", "target", 1), + myrage = MakeTypedPowerKeyword("myrage", "player", 1), + energy = MakeTypedPowerKeyword("energy", "target", 3), + myenergy = MakeTypedPowerKeyword("myenergy", "player", 3), + rawpower = function(conditionals) return Multi(conditionals.rawpower, function(args) if type(args) ~= "table" then return false end diff --git a/MacroErrorChecker.lua b/MacroErrorChecker.lua index 471a607..e39797d 100644 --- a/MacroErrorChecker.lua +++ b/MacroErrorChecker.lua @@ -651,6 +651,8 @@ local function validateConditional(conditional, args, action) combo = true, hp = true, myhp = true, rawhp = true, myrawhp = true, power = true, mypower = true, rawpower = true, myrawpower = true, + mana = true, mymana = true, rage = true, myrage = true, + energy = true, myenergy = true, hplost = true, myhplost = true, powerlost = true, mypowerlost = true, stat = true, @@ -678,6 +680,8 @@ local function validateConditional(conditional, args, action) -- Check operator syntax for numeric comparisons if args and type(args) == "string" then local hasHpOrPower = safeStringFind(baseCond, "hp") or safeStringFind(baseCond, "power") or + safeStringFind(baseCond, "mana") or safeStringFind(baseCond, "energy") or + safeStringFind(baseCond, "rage") or safeStringFind(baseCond, "combo") or baseCond == "stat" if hasHpOrPower then local hasOperator = safeStringFind(args, "[<>=~]+")