diff --git a/Conditionals.lua b/Conditionals.lua index a795573..fa13310 100644 --- a/Conditionals.lua +++ b/Conditionals.lua @@ -2922,7 +2922,7 @@ function CleveRoids.CountEnemiesMatching(checkFunc) local checked = {} -- 1. Current target (use "target" token for best API compatibility) - if UnitExists("target") and UnitCanAttack("player", "target") then + if UnitExists("target") and UnitCanAttack("player", "target") and not UnitIsDeadOrGhost("target") then local guid = CleveRoids.GetGUID("target") if guid then checked[guid] = true @@ -2937,6 +2937,7 @@ function CleveRoids.CountEnemiesMatching(checkFunc) local function tryUnit(unit) if not UnitExists(unit) then return end if not UnitCanAttack("player", unit) then return end + if UnitIsDeadOrGhost(unit) then return end local guid = CleveRoids.GetGUID(unit) if not guid or checked[guid] then return end checked[guid] = true @@ -7214,6 +7215,48 @@ CleveRoids.Keywords = { return UnitXP("behind", "player", unit) ~= true end, + -- [facing] - Player is facing target (target is not behind player) + -- [facing:>N] - Player is facing more than N enemies (count mode) + facing = function(conditionals) + if not CleveRoids.hasUnitXP then return false end + + -- Check for count mode: [facing:>1] + local countArgs = CleveRoids.GetCountModeArgs(conditionals.facing) + if countArgs then + local count = CleveRoids.CountEnemiesMatching(function(unit) + return UnitXP("behind", unit, "player") ~= true + end) + return CleveRoids.comparators[countArgs.operator](count, countArgs.amount) + end + + -- Original single-target behavior + local unit = conditionals.target or "target" + if not UnitExists(unit) then return false end + + return UnitXP("behind", unit, "player") ~= true + end, + + -- [nofacing] - Player is NOT facing target (target is behind player) + -- [nofacing:>N] - Player is NOT facing more than N enemies (count mode) + nofacing = function(conditionals) + if not CleveRoids.hasUnitXP then return false end + + -- Check for count mode: [nofacing:>1] + local countArgs = CleveRoids.GetCountModeArgs(conditionals.nofacing) + if countArgs then + local count = CleveRoids.CountEnemiesMatching(function(unit) + return UnitXP("behind", unit, "player") == true + end) + return CleveRoids.comparators[countArgs.operator](count, countArgs.amount) + end + + -- Original single-target behavior + local unit = conditionals.target or "target" + if not UnitExists(unit) then return false end + + return UnitXP("behind", unit, "player") == true + end, + -- [insight] - Target is in line of sight -- [insight:>N] - More than N enemies are in line of sight (count mode) insight = function(conditionals) diff --git a/Core.lua b/Core.lua index 082754b..b1f8994 100644 --- a/Core.lua +++ b/Core.lua @@ -695,6 +695,27 @@ function CleveRoids.GetReagentCount(reagentName) return total end +-- Live bag scan for item count, bypassing Items cache to avoid stale counts +-- during bag moves (especially backpack ↔ other bag transitions) +function CleveRoids.GetLiveItemCount(itemName) + if not itemName or itemName == "" then return 0 end + -- Escape Lua pattern special chars in item name to avoid crashes + local escaped = string.gsub(itemName, "([%(%)%.%%%+%-%*%?%[%]%^%$])", "%%%1") + local pattern = "%[" .. escaped .. "%]" + local total = 0 + for bag = 0, 4 do + local slots = GetContainerNumSlots(bag) or 0 + for slot = 1, slots do + local link = GetContainerItemLink and GetContainerItemLink(bag, slot) + if link and string.find(link, pattern) then + local _, count = GetContainerItemInfo(bag, slot) + total = total + (count or 0) + end + end + end + return total +end + function CleveRoids.GetSpellCost(spellSlot, bookType) -- Fast path: existing fixed-slot read CleveRoids.Frame:SetOwner(WorldFrame, "ANCHOR_NONE") @@ -4891,7 +4912,7 @@ function GetActionCount(slot) end if actionToCheck.item then - count = actionToCheck.item.count + count = CleveRoids.GetLiveItemCount(actionToCheck.item.name or actionToCheck.action) elseif actionToCheck.spell then local reagent = actionToCheck.spell.reagent