mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
crowd control conditionals
This commit is contained in:
@@ -149,6 +149,7 @@ end
|
||||
|
||||
-- PERFORMANCE: Equipment cache for HasGearEquipped (avoids 19-slot scan per call)
|
||||
-- Invalidated on UNIT_INVENTORY_CHANGED via CleveRoids.InvalidateEquipmentCache()
|
||||
-- Enhanced with Nampower v2.18+ GetEquippedItems when available
|
||||
local _equippedItemIDs = {} -- [slot] = itemID (number)
|
||||
local _equippedItemNames = {} -- [slot] = itemName (lowercase string)
|
||||
local _equipmentCacheValid = false
|
||||
@@ -166,6 +167,32 @@ local function BuildEquipmentCache()
|
||||
local string_find = string.find
|
||||
local string_lower = string.lower
|
||||
|
||||
-- Try Nampower v2.18+ GetEquippedItems for faster enumeration
|
||||
if GetEquippedItems then
|
||||
local items = GetEquippedItems("player")
|
||||
if items then
|
||||
for nampowerSlot, itemInfo in pairs(items) do
|
||||
-- Nampower uses 0-indexed slots, WoW API uses 1-indexed
|
||||
local slot = nampowerSlot + 1
|
||||
if slot >= 1 and slot <= 19 and itemInfo.itemId then
|
||||
_equippedItemIDs[slot] = itemInfo.itemId
|
||||
|
||||
-- Get item name via Nampower API or GetItemInfo
|
||||
local API = CleveRoids.NampowerAPI
|
||||
local itemName = API and API.GetItemName and API.GetItemName(itemInfo.itemId)
|
||||
if not itemName then
|
||||
itemName = GetItemInfo(itemInfo.itemId)
|
||||
end
|
||||
if itemName then
|
||||
_equippedItemNames[slot] = string_lower(itemName)
|
||||
end
|
||||
end
|
||||
end
|
||||
return -- Done with Nampower path
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: manual slot enumeration
|
||||
for slot = 1, 19 do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
@@ -197,6 +224,7 @@ end
|
||||
-- PERFORMANCE: Unified item location lookup using CleveRoids.Items cache
|
||||
-- Returns: { type="inventory"|"bag", inventoryID=N } or { type="bag", bag=N, slot=N }
|
||||
-- Returns nil if item not found
|
||||
-- Enhanced with Nampower v2.18+ FindPlayerItemSlot when available
|
||||
-- ============================================================================
|
||||
local string_lower = string.lower
|
||||
local string_find = string.find
|
||||
@@ -205,6 +233,29 @@ local string_find = string.find
|
||||
-- @param item: item ID (number) or item name (string)
|
||||
-- @return table with location info, or nil if not found
|
||||
function CleveRoids.FindItemLocation(item)
|
||||
-- Try Nampower v2.18+ native lookup first (much faster for item ID/name)
|
||||
if FindPlayerItemSlot and item then
|
||||
local numericItem = tonumber(item)
|
||||
|
||||
-- Skip native lookup for equipment slot numbers (1-19)
|
||||
if not (numericItem and numericItem >= 1 and numericItem <= 19) then
|
||||
local bag, slot = FindPlayerItemSlot(item)
|
||||
|
||||
if slot then
|
||||
if bag == nil then
|
||||
-- Equipped item - Nampower returns 1-indexed slot
|
||||
return { type = "inventory", inventoryID = slot }
|
||||
else
|
||||
-- Bag item
|
||||
return { type = "bag", bag = bag, slot = slot }
|
||||
end
|
||||
end
|
||||
-- If Nampower lookup failed, fall through to cache lookup
|
||||
-- (might find via substring match or cached alias)
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to CleveRoids.Items cache
|
||||
local Items = CleveRoids.Items
|
||||
if not Items then return nil end
|
||||
|
||||
@@ -269,6 +320,7 @@ function CleveRoids.HasItemCached(item)
|
||||
end
|
||||
|
||||
-- Fast item cooldown lookup using cache
|
||||
-- Enhanced with Nampower v2.18+ GetItemIdCooldown for detailed info
|
||||
-- @param item: item ID (number) or item name (string)
|
||||
-- @return remainingSeconds, totalDuration, enabled
|
||||
function CleveRoids.GetItemCooldownCached(item)
|
||||
@@ -277,6 +329,42 @@ function CleveRoids.GetItemCooldownCached(item)
|
||||
return 0, 0, 0
|
||||
end
|
||||
|
||||
-- Try Nampower v2.18+ GetItemIdCooldown for more detailed info
|
||||
-- This requires knowing the item ID
|
||||
if GetItemIdCooldown then
|
||||
local itemId = nil
|
||||
|
||||
-- Get item ID from location or input
|
||||
if location.itemData and location.itemData.id then
|
||||
itemId = location.itemData.id
|
||||
elseif type(item) == "number" and item > 19 then
|
||||
itemId = item
|
||||
else
|
||||
-- Extract item ID from inventory/bag link
|
||||
local link
|
||||
if location.type == "inventory" then
|
||||
link = GetInventoryItemLink("player", location.inventoryID)
|
||||
else
|
||||
link = GetContainerItemLink(location.bag, location.slot)
|
||||
end
|
||||
if link then
|
||||
local _, _, id = string.find(link, "item:(%d+)")
|
||||
if id then itemId = tonumber(id) end
|
||||
end
|
||||
end
|
||||
|
||||
if itemId then
|
||||
local cdInfo = GetItemIdCooldown(itemId)
|
||||
if cdInfo then
|
||||
local remaining = (cdInfo.cooldownRemainingMs or 0) / 1000
|
||||
local duration = (cdInfo.individualDurationMs or cdInfo.categoryDurationMs or 0) / 1000
|
||||
local enabled = (cdInfo.isOnCooldown == 1) and 1 or 0
|
||||
return remaining, duration, enabled
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback to standard WoW API
|
||||
local start, duration, enable
|
||||
if location.type == "inventory" then
|
||||
start, duration, enable = GetInventoryItemCooldown("player", location.inventoryID)
|
||||
@@ -2411,6 +2499,346 @@ function CleveRoids.CheckSpellCast(unit, spell)
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================================================
|
||||
-- CC (Crowd Control) Mechanic Detection
|
||||
-- Uses BuffLib if available, otherwise uses built-in spell database
|
||||
-- ============================================================================
|
||||
|
||||
-- Maps CC type names to mechanic constants (matches DBC mechanic IDs)
|
||||
CleveRoids.CCMechanics = {
|
||||
-- Movement/control impairment
|
||||
charm = 1, -- Mind Control, Seduction
|
||||
disoriented = 2, -- Scatter Shot, Blind (disorient component)
|
||||
disorient = 2, -- Alias for disoriented
|
||||
disarm = 3, -- Disarm, Riposte disarm
|
||||
distract = 4, -- Distract (Rogue ability)
|
||||
incapacitate = 4, -- Alias - some incaps use distract mechanic
|
||||
fear = 5, -- Fear, Psychic Scream, Howl of Terror
|
||||
grip = 6, -- Grip effects
|
||||
root = 7, -- Entangling Roots, Frost Nova, Improved Hamstring
|
||||
pacify = 8, -- Pacify effects
|
||||
silence = 9, -- Silence, Kick, Counterspell (lockout)
|
||||
sleep = 10, -- Hibernate, Wyvern Sting sleep
|
||||
snare = 11, -- Hamstring, Wing Clip, Crippling Poison
|
||||
slow = 11, -- Alias for snare
|
||||
stun = 12, -- Cheap Shot, Kidney Shot, Hammer of Justice, Bash
|
||||
freeze = 13, -- Freeze effects (Frost Nova freeze)
|
||||
knockout = 14, -- Gouge, Sap (incapacitate mechanic)
|
||||
incap = 14, -- Alias for knockout (Gouge, Sap type)
|
||||
bleed = 15, -- Rend, Garrote, Deep Wounds
|
||||
polymorph = 17, -- Polymorph (all variants)
|
||||
banish = 18, -- Banish (Warlock)
|
||||
shackle = 20, -- Shackle Undead
|
||||
horror = 24, -- Death Coil (Warlock), Intimidating Shout (horror)
|
||||
daze = 27, -- Dazed effects
|
||||
sap = 30, -- Sap (has its own mechanic in Turtle WoW)
|
||||
sapped = 30, -- Alias for sap
|
||||
}
|
||||
|
||||
-- CC types that count as "crowd controlled" (loss of control)
|
||||
CleveRoids.CCTypesLossOfControl = {
|
||||
[1] = true, -- charm
|
||||
[2] = true, -- disoriented
|
||||
[5] = true, -- fear
|
||||
[10] = true, -- sleep
|
||||
[12] = true, -- stun
|
||||
[13] = true, -- freeze
|
||||
[14] = true, -- knockout/incapacitate
|
||||
[17] = true, -- polymorph
|
||||
[18] = true, -- banish
|
||||
[20] = true, -- shackle
|
||||
[24] = true, -- horror
|
||||
[30] = true, -- sapped
|
||||
}
|
||||
|
||||
-- Complete spell ID to mechanic mapping from DBC data
|
||||
-- Extracted from BuffLib SpellData - 785 spells with mechanics
|
||||
-- Mechanic IDs: 1=Charm, 2=Disorient, 3=Disarm, 5=Fear, 7=Root, 9=Silence,
|
||||
-- 10=Sleep, 11=Snare, 12=Stun, 13=Freeze, 14=Knockout,
|
||||
-- 15=Bleed, 17=Polymorph, 18=Banish, 20=Shackle, 21=Mount,
|
||||
-- 23=Turn, 24=Horror, 25=Invuln, 27=Daze
|
||||
CleveRoids.CCSpellMechanics = {
|
||||
[17] = 19, [56] = 12, [89] = 11, [113] = 7, [118] = 17, [228] = 17,
|
||||
[246] = 11, [339] = 7, [408] = 12, [451] = 9, [458] = 21, [459] = 21,
|
||||
[468] = 21, [470] = 21, [471] = 21, [472] = 21, [474] = 6, [498] = 25,
|
||||
[507] = 6, [512] = 7, [578] = 21, [579] = 21, [580] = 21, [581] = 21,
|
||||
[592] = 19, [593] = 6, [600] = 19, [605] = 1, [642] = 25, [676] = 3,
|
||||
[700] = 10, [703] = 15, [710] = 18, [745] = 7, [746] = 16, [771] = 1,
|
||||
[772] = 15, [835] = 12, [851] = 17, [853] = 12, [861] = 9, [867] = 6,
|
||||
[998] = 6, [1020] = 25, [1022] = 25, [1062] = 7, [1079] = 15, [1090] = 10,
|
||||
[1098] = 1, [1159] = 16, [1513] = 5, [1776] = 14, [1777] = 14, [1833] = 12,
|
||||
[1943] = 15, [2070] = 14, [2094] = 2, [2637] = 10, [2878] = 23, [2880] = 12,
|
||||
[2937] = 10, [3109] = 5, [3143] = 12, [3147] = 15, [3242] = 12, [3263] = 12,
|
||||
[3267] = 16, [3268] = 16, [3355] = 13, [3363] = 21, [3409] = 11, [3410] = 11,
|
||||
[3446] = 12, [3542] = 7, [3551] = 12, [3589] = 9, [3600] = 11, [3604] = 11,
|
||||
[3609] = 12, [3635] = 12, [3636] = 10, [3747] = 19, [4060] = 17, [4064] = 12,
|
||||
[4065] = 12, [4066] = 12, [4067] = 12, [4068] = 12, [4069] = 12, [4102] = 15,
|
||||
[4244] = 15, [4962] = 7, [5106] = 12, [5116] = 11, [5134] = 5, [5159] = 11,
|
||||
[5164] = 12, [5195] = 7, [5196] = 7, [5211] = 12, [5246] = 5, [5259] = 3,
|
||||
[5276] = 12, [5376] = 4, [5403] = 12, [5484] = 5, [5530] = 12, [5531] = 12,
|
||||
[5567] = 7, [5573] = 25, [5588] = 12, [5589] = 12, [5597] = 15, [5598] = 15,
|
||||
[5599] = 25, [5627] = 23, [5648] = 12, [5649] = 12, [5703] = 12, [5708] = 12,
|
||||
[5782] = 5, [5784] = 21, [5917] = 6, [5918] = 12, [6065] = 19, [6066] = 19,
|
||||
[6136] = 11, [6146] = 11, [6213] = 5, [6215] = 5, [6253] = 12, [6266] = 12,
|
||||
[6304] = 12, [6358] = 1, [6388] = 11, [6409] = 12, [6435] = 12, [6466] = 12,
|
||||
[6524] = 12, [6533] = 7, [6546] = 15, [6547] = 15, [6548] = 15, [6605] = 5,
|
||||
[6607] = 12, [6608] = 3, [6648] = 21, [6653] = 21, [6654] = 21, [6713] = 3,
|
||||
[6726] = 9, [6728] = 12, [6730] = 12, [6749] = 12, [6770] = 14, [6777] = 21,
|
||||
[6788] = 19, [6798] = 12, [6896] = 21, [6897] = 21, [6898] = 21, [6899] = 21,
|
||||
[6927] = 12, [6942] = 9, [6945] = 12, [6982] = 12, [6984] = 11, [6985] = 11,
|
||||
[7074] = 9, [7093] = 5, [7139] = 12, [7279] = 11, [7321] = 11, [7399] = 5,
|
||||
[7645] = 1, [7803] = 12, [7922] = 12, [7926] = 16, [7927] = 16, [7964] = 12,
|
||||
[7967] = 10, [7992] = 11, [8040] = 10, [8122] = 5, [8124] = 5, [8142] = 7,
|
||||
[8150] = 12, [8208] = 12, [8225] = 5, [8242] = 12, [8281] = 9, [8285] = 12,
|
||||
[8312] = 7, [8346] = 7, [8377] = 7, [8379] = 3, [8391] = 12, [8394] = 21,
|
||||
[8395] = 21, [8396] = 21, [8399] = 10, [8629] = 14, [8631] = 15, [8632] = 15,
|
||||
[8633] = 15, [8639] = 15, [8640] = 15, [8643] = 12, [8646] = 12, [8715] = 5,
|
||||
[8716] = 11, [8818] = 15, [8901] = 10, [8902] = 10, [8980] = 21, [8983] = 12,
|
||||
[8988] = 9, [8994] = 18, [9005] = 12, [9007] = 15, [9080] = 11, [9159] = 10,
|
||||
[9484] = 20, [9485] = 20, [9552] = 9, [9823] = 12, [9824] = 15, [9826] = 15,
|
||||
[9827] = 12, [9852] = 7, [9853] = 7, [9896] = 15, [9915] = 7, [10017] = 7,
|
||||
[10234] = 10, [10253] = 17, [10266] = 15, [10278] = 25, [10308] = 12,
|
||||
[10326] = 23, [10787] = 21, [10788] = 21, [10789] = 21, [10790] = 21,
|
||||
[10792] = 21, [10793] = 21, [10795] = 21, [10796] = 21, [10798] = 21,
|
||||
[10799] = 21, [10800] = 21, [10801] = 21, [10802] = 21, [10803] = 21,
|
||||
[10804] = 21, [10838] = 16, [10839] = 16, [10851] = 3, [10852] = 7,
|
||||
[10855] = 11, [10856] = 12, [10873] = 21, [10888] = 5, [10890] = 5,
|
||||
[10898] = 19, [10899] = 19, [10900] = 19, [10901] = 19, [10911] = 1,
|
||||
[10912] = 1, [10955] = 20, [10969] = 21, [10987] = 11, [11020] = 12,
|
||||
[11201] = 11, [11264] = 7, [11273] = 15, [11274] = 15, [11275] = 15,
|
||||
[11285] = 14, [11286] = 14, [11289] = 15, [11290] = 15, [11297] = 14,
|
||||
[11428] = 12, [11430] = 12, [11436] = 11, [11446] = 1, [11572] = 15,
|
||||
[11573] = 15, [11574] = 15, [11578] = 12, [11579] = 12, [11641] = 17, [11650] = 12, [11725] = 1,
|
||||
[11726] = 1, [11820] = 7, [11831] = 7, [11836] = 12, [11876] = 12,
|
||||
[11879] = 3, [11922] = 7, [11958] = 13, [11977] = 15, [12023] = 7,
|
||||
[12024] = 7, [12054] = 15, [12096] = 5, [12098] = 10, [12252] = 7,
|
||||
[12323] = 11, [12355] = 12, [12421] = 12, [12461] = 12, [12484] = 11,
|
||||
[12485] = 11, [12486] = 11, [12494] = 7, [12528] = 9, [12531] = 11,
|
||||
[12540] = 14, [12542] = 5, [12543] = 12, [12551] = 11, [12562] = 12,
|
||||
[12674] = 7, [12705] = 11, [12721] = 15, [12730] = 5, [12734] = 12,
|
||||
[12747] = 7, [12748] = 7, [12798] = 12, [12809] = 12, [12824] = 17,
|
||||
[12825] = 17, [12826] = 17, [12946] = 9, [13005] = 12, [13099] = 7,
|
||||
[13119] = 7, [13138] = 7, [13181] = 1, [13237] = 12, [13318] = 15,
|
||||
[13323] = 17, [13327] = 14, [13443] = 15, [13445] = 15, [13534] = 3,
|
||||
[13579] = 14, [13608] = 7, [13704] = 5, [13738] = 15, [13747] = 11,
|
||||
[13808] = 12, [13810] = 11, [13819] = 21, [13902] = 12, [14030] = 7,
|
||||
[14087] = 15, [14100] = 5, [14102] = 12, [14118] = 15, [14180] = 3,
|
||||
[14207] = 11, [14308] = 13, [14309] = 13, [14326] = 5, [14327] = 5,
|
||||
[14331] = 15, [14515] = 1, [14621] = 17, [14874] = 15, [14897] = 11,
|
||||
[14902] = 12, [14903] = 15, [14907] = 7, [15063] = 7, [15091] = 14,
|
||||
[15269] = 12, [15283] = 12, [15398] = 12, [15471] = 7, [15474] = 7,
|
||||
[15487] = 9, [15531] = 7, [15532] = 7, [15534] = 17, [15535] = 12,
|
||||
[15583] = 15, [15593] = 12, [15609] = 7, [15618] = 12, [15621] = 12,
|
||||
[15652] = 12, [15655] = 12, [15744] = 14, [15752] = 3, [15753] = 12,
|
||||
[15779] = 21, [15780] = 21, [15781] = 21, [15822] = 10, [15859] = 1,
|
||||
[15878] = 12, [15970] = 10, [15976] = 15, [16045] = 18, [16046] = 14,
|
||||
[16050] = 11, [16053] = 1, [16055] = 21, [16056] = 21, [16058] = 21,
|
||||
[16059] = 21, [16060] = 21, [16075] = 12, [16080] = 21, [16081] = 21,
|
||||
[16082] = 21, [16083] = 21, [16084] = 21, [16095] = 15, [16096] = 5,
|
||||
[16097] = 17, [16104] = 12, [16350] = 12, [16393] = 15, [16403] = 15,
|
||||
[16406] = 15, [16451] = 18, [16469] = 7, [16497] = 12, [16508] = 5,
|
||||
[16509] = 15, [16566] = 7, [16568] = 11, [16600] = 12, [16707] = 17,
|
||||
[16708] = 17, [16709] = 17, [16727] = 12, [16790] = 12, [16798] = 10,
|
||||
[16803] = 12, [16838] = 9, [16869] = 12, [16922] = 12, [17011] = 12,
|
||||
[17145] = 14, [17153] = 15, [17165] = 11, [17172] = 17, [17174] = 11,
|
||||
[17229] = 21, [17276] = 12, [17277] = 14, [17286] = 12, [17293] = 12,
|
||||
[17308] = 12, [17405] = 1, [17450] = 21, [17453] = 21, [17454] = 21,
|
||||
[17455] = 21, [17456] = 21, [17458] = 21, [17459] = 21, [17460] = 21,
|
||||
[17461] = 21, [17462] = 21, [17463] = 21, [17464] = 21, [17465] = 21,
|
||||
[17481] = 21, [17500] = 12, [17504] = 15, [17738] = 17, [17928] = 5,
|
||||
[18075] = 15, [18078] = 15, [18093] = 12, [18103] = 12, [18106] = 15,
|
||||
[18118] = 11, [18144] = 12, [18200] = 15, [18202] = 15, [18223] = 11,
|
||||
[18278] = 9, [18327] = 9, [18328] = 11, [18363] = 21, [18395] = 12,
|
||||
[18425] = 9, [18431] = 5, [18469] = 9, [18498] = 9, [18503] = 17,
|
||||
[18608] = 16, [18610] = 16, [18647] = 18, [18657] = 10, [18658] = 10,
|
||||
[18763] = 12, [18802] = 11, [18812] = 12, [18972] = 11, [18989] = 21,
|
||||
[18990] = 21, [18991] = 21, [18992] = 21, [19128] = 12, [19134] = 5,
|
||||
[19136] = 12, [19137] = 11, [19185] = 7, [19229] = 7, [19364] = 12,
|
||||
[19386] = 10, [19393] = 9, [19408] = 5, [19410] = 12, [19469] = 1,
|
||||
[19482] = 12, [19496] = 11, [19501] = 2, [19503] = 2, [19641] = 12,
|
||||
[19718] = 3, [19769] = 12, [19771] = 15, [19780] = 12, [19784] = 12,
|
||||
[19821] = 9, [19970] = 7, [19971] = 7, [19972] = 7, [19973] = 7,
|
||||
[19974] = 7, [19975] = 7, [20066] = 14, [20170] = 12, [20253] = 12,
|
||||
[20276] = 12, [20277] = 12, [20310] = 12, [20511] = 5, [20549] = 12,
|
||||
[20604] = 1, [20614] = 12, [20615] = 12, [20654] = 7, [20663] = 10,
|
||||
[20669] = 10, [20683] = 12, [20685] = 12, [20699] = 7, [20706] = 19,
|
||||
[20740] = 1, [20882] = 1, [20907] = 15, [20908] = 15, [20989] = 10,
|
||||
[21099] = 12, [21152] = 12, [21330] = 5, [21331] = 7, [21748] = 12,
|
||||
[21749] = 12, [21869] = 5, [21898] = 5, [21949] = 15, [21990] = 12,
|
||||
[22127] = 7, [22274] = 17, [22289] = 12, [22356] = 11, [22415] = 7,
|
||||
[22419] = 3, [22424] = 14, [22427] = 12, [22519] = 7, [22566] = 17,
|
||||
[22570] = 14, [22592] = 12, [22639] = 11, [22645] = 7, [22666] = 9,
|
||||
[22678] = 5, [22686] = 5, [22691] = 3, [22692] = 12, [22717] = 21,
|
||||
[22718] = 21, [22719] = 21, [22720] = 21, [22721] = 21, [22722] = 21,
|
||||
[22723] = 21, [22724] = 21, [22744] = 7, [22752] = 19, [22800] = 7,
|
||||
[22884] = 5, [22914] = 11, [22915] = 12, [22919] = 11, [22924] = 7,
|
||||
[22994] = 7, [23039] = 14, [23103] = 12, [23113] = 14, [23161] = 21,
|
||||
[23207] = 9, [23214] = 21, [23219] = 21, [23220] = 21, [23221] = 21,
|
||||
[23222] = 21, [23223] = 21, [23225] = 21, [23227] = 21, [23228] = 21,
|
||||
[23229] = 21, [23238] = 21, [23239] = 21, [23240] = 21, [23241] = 21,
|
||||
[23242] = 21, [23243] = 21, [23246] = 21, [23247] = 21, [23248] = 21,
|
||||
[23249] = 21, [23250] = 21, [23251] = 21, [23252] = 21, [23275] = 5,
|
||||
[23338] = 21, [23364] = 12, [23365] = 3, [23454] = 12, [23509] = 21,
|
||||
[23510] = 21, [23567] = 16, [23568] = 16, [23569] = 16, [23600] = 11,
|
||||
[23603] = 17, [23618] = 12, [23694] = 7, [23696] = 16, [23918] = 9,
|
||||
[23919] = 12, [23953] = 11, [24004] = 10, [24053] = 17, [24110] = 7,
|
||||
[24118] = 15, [24119] = 15, [24120] = 15, [24132] = 10, [24133] = 10,
|
||||
[24152] = 7, [24192] = 15, [24213] = 12, [24225] = 11, [24242] = 21,
|
||||
[24252] = 21, [24259] = 9, [24327] = 1, [24331] = 15, [24332] = 15,
|
||||
[24333] = 12, [24335] = 10, [24360] = 10, [24375] = 12, [24394] = 12,
|
||||
[24412] = 16, [24413] = 16, [24414] = 16, [24415] = 11, [24576] = 21,
|
||||
[24600] = 12, [24648] = 7, [24664] = 10, [24671] = 12, [24687] = 9,
|
||||
[24698] = 14, [24712] = 17, [24713] = 17, [24735] = 17, [24736] = 17,
|
||||
[24778] = 10, [25022] = 11, [25049] = 14, [25056] = 12, [25057] = 3,
|
||||
[25187] = 11, [25189] = 12, [25260] = 5, [25654] = 12, [25655] = 3,
|
||||
[25675] = 21, [25771] = 25, [25809] = 11, [25815] = 5, [25852] = 12,
|
||||
[25858] = 21, [25859] = 21, [25863] = 21, [25953] = 21, [25999] = 7,
|
||||
[26042] = 5, [26054] = 21, [26055] = 21, [26056] = 21, [26069] = 9,
|
||||
[26070] = 5, [26071] = 7, [26078] = 11, [26108] = 2, [26141] = 11,
|
||||
[26143] = 11, [26157] = 17, [26180] = 10, [26211] = 11, [26272] = 17,
|
||||
[26273] = 17, [26274] = 17, [26379] = 11, [26580] = 5, [26641] = 5,
|
||||
[26655] = 21, [26740] = 1, [27555] = 15, [27556] = 15, [27559] = 9,
|
||||
[27565] = 18, [27581] = 3, [27607] = 19, [27610] = 5, [27615] = 12,
|
||||
[27619] = 13, [27634] = 11, [27638] = 15, [27640] = 11, [27641] = 5,
|
||||
[27758] = 12, [27760] = 17, [27880] = 12, [27990] = 5, [27993] = 11,
|
||||
[28270] = 17, [28271] = 17, [28272] = 17, [28314] = 12, [28315] = 5,
|
||||
[28445] = 12, [28456] = 14, [28725] = 12, [28858] = 7, [28911] = 15,
|
||||
[28913] = 15, [28991] = 7, [29059] = 21, [29168] = 5, [29407] = 11,
|
||||
[29419] = 5, [29544] = 5, [29685] = 5, [29848] = 17, [29849] = 7,
|
||||
[29915] = 15, [29943] = 9, [30001] = 5, [30002] = 5, [30020] = 16,
|
||||
[30094] = 7, [30174] = 21, [30225] = 9, [30285] = 15, [31365] = 5,
|
||||
[31700] = 21,
|
||||
}
|
||||
|
||||
-- Check if BuffLib is available with full mechanic support
|
||||
function CleveRoids.HasBuffLib()
|
||||
return BuffLib and BuffLib.GetUnitDebuffsByMechanic and BuffLib.SpellData and BuffLib.SpellData.GetMechanic
|
||||
end
|
||||
|
||||
-- Get mechanic for a spell ID (uses BuffLib if available, otherwise built-in table)
|
||||
function CleveRoids.GetSpellMechanic(spellID)
|
||||
if not spellID or spellID <= 0 then return 0 end
|
||||
|
||||
-- Try BuffLib first (has complete DBC data)
|
||||
if BuffLib and BuffLib.SpellData and BuffLib.SpellData.GetMechanic then
|
||||
local mechanic = BuffLib.SpellData:GetMechanic(spellID)
|
||||
if mechanic and mechanic > 0 then
|
||||
return mechanic
|
||||
end
|
||||
end
|
||||
|
||||
-- Fall back to built-in table
|
||||
return CleveRoids.CCSpellMechanics[spellID] or 0
|
||||
end
|
||||
|
||||
-- Validate CC on a unit (target, focus, player, etc.)
|
||||
-- Returns true if the unit has the specified CC mechanic active
|
||||
function CleveRoids.ValidateUnitCC(unit, ccType)
|
||||
if not unit or not UnitExists(unit) then return false end
|
||||
|
||||
-- Get mechanic number from CC type name
|
||||
local mechanic = CleveRoids.CCMechanics[string.lower(ccType or "")]
|
||||
if not mechanic then return false end
|
||||
|
||||
-- Special case: "cc" means any loss-of-control effect
|
||||
if ccType == "cc" or ccType == "any" then
|
||||
return CleveRoids.ValidateUnitAnyCrowdControl(unit)
|
||||
end
|
||||
|
||||
-- Use BuffLib if available (most accurate - tracks overflow debuffs and hidden auras)
|
||||
if CleveRoids.HasBuffLib() then
|
||||
local _, guid = UnitExists(unit)
|
||||
if not guid then return false end
|
||||
|
||||
if unit == "player" then
|
||||
return BuffLib:HasDebuffOfMechanic(mechanic)
|
||||
else
|
||||
local debuffs = BuffLib:GetUnitDebuffsByMechanic(guid, mechanic)
|
||||
return debuffs and table.getn(debuffs) > 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: scan unit debuffs directly
|
||||
return CleveRoids.ValidateUnitCCDirect(unit, mechanic)
|
||||
end
|
||||
|
||||
-- Check if unit has any crowd control (loss of control) effect
|
||||
function CleveRoids.ValidateUnitAnyCrowdControl(unit)
|
||||
if not unit or not UnitExists(unit) then return false end
|
||||
|
||||
-- Use BuffLib if available
|
||||
if CleveRoids.HasBuffLib() then
|
||||
local _, guid = UnitExists(unit)
|
||||
if not guid then return false end
|
||||
|
||||
if unit == "player" then
|
||||
for mechanic, _ in pairs(CleveRoids.CCTypesLossOfControl) do
|
||||
if BuffLib:HasDebuffOfMechanic(mechanic) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
else
|
||||
for mechanic, _ in pairs(CleveRoids.CCTypesLossOfControl) do
|
||||
local debuffs = BuffLib:GetUnitDebuffsByMechanic(guid, mechanic)
|
||||
if debuffs and table.getn(debuffs) > 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Fallback: check all loss-of-control mechanics directly
|
||||
for mechanic, _ in pairs(CleveRoids.CCTypesLossOfControl) do
|
||||
if CleveRoids.ValidateUnitCCDirect(unit, mechanic) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Direct CC check - scans unit debuffs using SuperWoW API
|
||||
-- Works without BuffLib by using built-in spell mechanic table
|
||||
function CleveRoids.ValidateUnitCCDirect(unit, mechanic)
|
||||
if not CleveRoids.hasSuperwow then return false end
|
||||
|
||||
-- Players only have 16 debuff slots, no overflow
|
||||
-- Non-player units can have overflow debuffs in buff slots (17-48)
|
||||
local isPlayer = (unit == "player")
|
||||
local maxDebuffSlots = 16
|
||||
local maxOverflowSlots = isPlayer and 0 or 32
|
||||
|
||||
-- Scan regular debuff slots (1-16)
|
||||
for i = 1, maxDebuffSlots do
|
||||
local texture, stacks, debuffType, spellID = UnitDebuff(unit, i)
|
||||
if not texture then break end
|
||||
|
||||
if spellID and spellID > 0 then
|
||||
local spellMechanic = CleveRoids.GetSpellMechanic(spellID)
|
||||
if spellMechanic == mechanic then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Scan overflow slots in buff bar (non-player units only)
|
||||
if maxOverflowSlots > 0 then
|
||||
for i = 1, maxOverflowSlots do
|
||||
local texture, stacks, spellID = UnitBuff(unit, i)
|
||||
if not texture then break end
|
||||
|
||||
if spellID and spellID > 0 then
|
||||
local spellMechanic = CleveRoids.GetSpellMechanic(spellID)
|
||||
if spellMechanic == mechanic then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- A list of Conditionals and their functions to validate them
|
||||
CleveRoids.Keywords = {
|
||||
exists = function(conditionals)
|
||||
@@ -4203,5 +4631,73 @@ CleveRoids.Keywords = {
|
||||
|
||||
return true
|
||||
end, conditionals, "nopowertype")
|
||||
end,
|
||||
|
||||
-- ========================================================================
|
||||
-- CC (Crowd Control) Conditionals - Requires BuffLib for full functionality
|
||||
-- ========================================================================
|
||||
|
||||
-- [cc:type] - Check if target has a specific CC effect
|
||||
-- Types: stun, fear, root, snare/slow, sleep, charm, polymorph, banish, horror,
|
||||
-- disarm, silence, daze, sap, freeze, knockout/incap, disorient, shackle
|
||||
-- Special: [cc] or [cc:any] checks for any loss-of-control effect
|
||||
-- Examples: [cc:stun] [@focus,cc:fear] [cc:stun/fear/root]
|
||||
cc = function(conditionals)
|
||||
local target = conditionals.target or "target"
|
||||
|
||||
-- If no specific CC type, check for ANY loss-of-control
|
||||
if not conditionals.cc or (type(conditionals.cc) == "table" and table.getn(conditionals.cc) == 0) then
|
||||
return CleveRoids.ValidateUnitAnyCrowdControl(target)
|
||||
end
|
||||
|
||||
-- Check for specific CC type(s) - OR logic
|
||||
return Or(conditionals.cc, function(ccType)
|
||||
return CleveRoids.ValidateUnitCC(target, ccType)
|
||||
end)
|
||||
end,
|
||||
|
||||
-- [nocc:type] - Check if target does NOT have a specific CC effect
|
||||
-- Uses AND logic for negation: [nocc:stun/fear] = not stunned AND not feared
|
||||
nocc = function(conditionals)
|
||||
local target = conditionals.target or "target"
|
||||
|
||||
-- If no specific CC type, check for NO loss-of-control
|
||||
if not conditionals.nocc or (type(conditionals.nocc) == "table" and table.getn(conditionals.nocc) == 0) then
|
||||
return not CleveRoids.ValidateUnitAnyCrowdControl(target)
|
||||
end
|
||||
|
||||
-- Check for absence of specific CC type(s) - AND logic (must be missing ALL)
|
||||
return NegatedMulti(conditionals.nocc, function(ccType)
|
||||
return not CleveRoids.ValidateUnitCC(target, ccType)
|
||||
end, conditionals, "nocc")
|
||||
end,
|
||||
|
||||
-- [mycc:type] - Check if PLAYER has a specific CC effect
|
||||
-- Same types as [cc], but always checks the player
|
||||
-- Examples: [mycc:stun] [mycc:fear/charm] [mycc] (any CC)
|
||||
mycc = function(conditionals)
|
||||
-- If no specific CC type, check for ANY loss-of-control on player
|
||||
if not conditionals.mycc or (type(conditionals.mycc) == "table" and table.getn(conditionals.mycc) == 0) then
|
||||
return CleveRoids.ValidateUnitAnyCrowdControl("player")
|
||||
end
|
||||
|
||||
-- Check for specific CC type(s) - OR logic
|
||||
return Or(conditionals.mycc, function(ccType)
|
||||
return CleveRoids.ValidateUnitCC("player", ccType)
|
||||
end)
|
||||
end,
|
||||
|
||||
-- [nomycc:type] - Check if PLAYER does NOT have a specific CC effect
|
||||
-- Uses AND logic for negation: [nomycc:stun/fear] = not stunned AND not feared
|
||||
nomycc = function(conditionals)
|
||||
-- If no specific CC type, check for NO loss-of-control on player
|
||||
if not conditionals.nomycc or (type(conditionals.nomycc) == "table" and table.getn(conditionals.nomycc) == 0) then
|
||||
return not CleveRoids.ValidateUnitAnyCrowdControl("player")
|
||||
end
|
||||
|
||||
-- Check for absence of specific CC type(s) - AND logic
|
||||
return NegatedMulti(conditionals.nomycc, function(ccType)
|
||||
return not CleveRoids.ValidateUnitCC("player", ccType)
|
||||
end, conditionals, "nomycc")
|
||||
end
|
||||
}
|
||||
|
||||
+307
-28
@@ -4,16 +4,34 @@
|
||||
Provides wrapper functions for Nampower's extended Lua API with fallbacks
|
||||
for older versions or when functions are unavailable.
|
||||
|
||||
New Nampower Functions Wrapped:
|
||||
Core Nampower Functions Wrapped (v2.8+):
|
||||
- GetSpellRec / GetSpellRecField - Spell record data from client DB
|
||||
- GetItemStats / GetItemStatsField - Item stats from client DB
|
||||
- GetUnitData / GetUnitField - Low-level unit field access
|
||||
- GetSpellModifiers - Spell modifier calculations (talents, buffs, etc.)
|
||||
|
||||
Enhanced Functions (now accept spell name or "spellId:number"):
|
||||
Inventory/Equipment Functions (v2.18+):
|
||||
- FindPlayerItemSlot - Fast item location lookup
|
||||
- GetEquippedItems / GetEquippedItem - Equipment inspection
|
||||
- GetBagItems / GetBagItem - Bag contents inspection
|
||||
- GetCastInfo - Detailed cast/channel/GCD information
|
||||
- GetSpellIdCooldown / GetItemIdCooldown - Detailed cooldown info
|
||||
|
||||
Trinket/Item Functions (v2.20+):
|
||||
- GetTrinkets - Enumerate equipped and bagged trinkets
|
||||
- GetTrinketCooldown - Get trinket cooldown by slot/ID/name
|
||||
- UseTrinket - Use trinket by slot/ID/name with optional target
|
||||
- UseItemIdOrName - Use any item by ID/name with optional target
|
||||
|
||||
Enhanced Functions (accept spell name or "spellId:number"):
|
||||
- GetSpellTexture, GetSpellName, GetSpellCooldown, GetSpellAutocast
|
||||
- ToggleSpellAutocast, PickupSpell, CastSpell, IsCurrentCast, IsSpellPassive
|
||||
|
||||
Copy Parameter (v2.20+):
|
||||
- Most table-returning functions now accept [copy] parameter
|
||||
- Pass 1 to get independent copy safe for storage
|
||||
- Without copy, table references are reused - extract values immediately!
|
||||
|
||||
Settings Integration:
|
||||
- Reads from NampowerSettings addon when available
|
||||
- Falls back to CVars when addon not present
|
||||
@@ -87,6 +105,12 @@ API.features = {
|
||||
hasGetSpellIdCooldown = (GetSpellIdCooldown ~= nil),
|
||||
hasGetItemIdCooldown = (GetItemIdCooldown ~= nil),
|
||||
hasChannelStopCastingNextTick = (ChannelStopCastingNextTick ~= nil),
|
||||
|
||||
-- v2.20+ APIs (trinkets, item usage, enhanced cooldowns)
|
||||
hasGetTrinkets = (GetTrinkets ~= nil),
|
||||
hasGetTrinketCooldown = (GetTrinketCooldown ~= nil),
|
||||
hasUseTrinket = (UseTrinket ~= nil),
|
||||
hasUseItemIdOrName = (UseItemIdOrName ~= nil),
|
||||
}
|
||||
|
||||
-- Detect if enhanced spell functions are available (accept name/spellId:number)
|
||||
@@ -141,6 +165,9 @@ API.defaultSettings = {
|
||||
NP_SpamProtectionEnabled = "1",
|
||||
NP_ChannelLatencyReductionPercentage = "75",
|
||||
NP_NameplateDistance = "41",
|
||||
-- v2.20+ CVars
|
||||
NP_PreventMountingWhenBuffCapped = "1", -- Prevent mounting when buff capped (32 buffs)
|
||||
NP_EnableAuraCastEvents = "0", -- Enable AURA_CAST_ON_SELF/OTHER events
|
||||
}
|
||||
|
||||
-- Get a Nampower setting value
|
||||
@@ -243,19 +270,23 @@ API.spellRecCache = {}
|
||||
|
||||
-- Get full spell record data
|
||||
-- Returns nil if spell not found or API unavailable
|
||||
function API.GetSpellRecord(spellId)
|
||||
-- Pass copy=1 to get an independent copy safe for storage (v2.20+)
|
||||
-- WARNING: Without copy, table references are reused - extract values immediately!
|
||||
function API.GetSpellRecord(spellId, copy)
|
||||
if not spellId or spellId == 0 then return nil end
|
||||
|
||||
-- Check cache first
|
||||
if API.spellRecCache[spellId] then
|
||||
-- Check cache first (only for non-copy requests)
|
||||
if not copy and API.spellRecCache[spellId] then
|
||||
return API.spellRecCache[spellId]
|
||||
end
|
||||
|
||||
-- Use native function if available
|
||||
if GetSpellRec then
|
||||
local rec = GetSpellRec(spellId)
|
||||
local rec = GetSpellRec(spellId, copy)
|
||||
if rec then
|
||||
API.spellRecCache[spellId] = rec
|
||||
if not copy then
|
||||
API.spellRecCache[spellId] = rec
|
||||
end
|
||||
return rec
|
||||
end
|
||||
end
|
||||
@@ -265,12 +296,13 @@ end
|
||||
|
||||
-- Get a specific field from spell record
|
||||
-- Returns nil if not found, raises error if field name invalid (native behavior)
|
||||
function API.GetSpellField(spellId, fieldName)
|
||||
-- Pass copy=1 to get an independent copy for array fields (v2.20+)
|
||||
function API.GetSpellField(spellId, fieldName, copy)
|
||||
if not spellId or spellId == 0 then return nil end
|
||||
|
||||
-- Use native function if available (more efficient for single field)
|
||||
if GetSpellRecField then
|
||||
local success, result = pcall(GetSpellRecField, spellId, fieldName)
|
||||
local success, result = pcall(GetSpellRecField, spellId, fieldName, copy)
|
||||
if success then
|
||||
return result
|
||||
end
|
||||
@@ -280,7 +312,7 @@ function API.GetSpellField(spellId, fieldName)
|
||||
end
|
||||
|
||||
-- Fallback to full record lookup
|
||||
local rec = API.GetSpellRecord(spellId)
|
||||
local rec = API.GetSpellRecord(spellId, copy)
|
||||
if rec then
|
||||
return rec[fieldName]
|
||||
end
|
||||
@@ -494,19 +526,23 @@ end
|
||||
API.itemStatsCache = {}
|
||||
|
||||
-- Get full item stats data
|
||||
function API.GetItemRecord(itemId)
|
||||
-- Pass copy=1 to get an independent copy safe for storage (v2.20+)
|
||||
-- WARNING: Without copy, table references are reused - extract values immediately!
|
||||
function API.GetItemRecord(itemId, copy)
|
||||
if not itemId or itemId == 0 then return nil end
|
||||
|
||||
-- Check cache first
|
||||
if API.itemStatsCache[itemId] then
|
||||
-- Check cache first (only for non-copy requests)
|
||||
if not copy and API.itemStatsCache[itemId] then
|
||||
return API.itemStatsCache[itemId]
|
||||
end
|
||||
|
||||
-- Use native function if available (wrapped in pcall for safety)
|
||||
if GetItemStats then
|
||||
local ok, stats = pcall(GetItemStats, itemId)
|
||||
local ok, stats = pcall(GetItemStats, itemId, copy)
|
||||
if ok and stats then
|
||||
API.itemStatsCache[itemId] = stats
|
||||
if not copy then
|
||||
API.itemStatsCache[itemId] = stats
|
||||
end
|
||||
return stats
|
||||
end
|
||||
end
|
||||
@@ -515,12 +551,13 @@ function API.GetItemRecord(itemId)
|
||||
end
|
||||
|
||||
-- Get a specific field from item stats
|
||||
function API.GetItemField(itemId, fieldName)
|
||||
-- Pass copy=1 to get an independent copy for array fields (v2.20+)
|
||||
function API.GetItemField(itemId, fieldName, copy)
|
||||
if not itemId or itemId == 0 then return nil end
|
||||
|
||||
-- Use native function if available (more efficient)
|
||||
if GetItemStatsField then
|
||||
local success, result = pcall(GetItemStatsField, itemId, fieldName)
|
||||
local success, result = pcall(GetItemStatsField, itemId, fieldName, copy)
|
||||
if success then
|
||||
return result
|
||||
end
|
||||
@@ -528,7 +565,7 @@ function API.GetItemField(itemId, fieldName)
|
||||
end
|
||||
|
||||
-- Fallback to full record lookup
|
||||
local stats = API.GetItemRecord(itemId)
|
||||
local stats = API.GetItemRecord(itemId, copy)
|
||||
if stats then
|
||||
return stats[fieldName]
|
||||
end
|
||||
@@ -627,23 +664,26 @@ end
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Get full unit data (no caching - unit data changes frequently)
|
||||
function API.GetUnitRecord(unitToken)
|
||||
-- Pass copy=1 to get an independent copy safe for storage (v2.20+)
|
||||
-- WARNING: Without copy, table references are reused - extract values immediately!
|
||||
function API.GetUnitRecord(unitToken, copy)
|
||||
if not unitToken then return nil end
|
||||
|
||||
if GetUnitData then
|
||||
return GetUnitData(unitToken)
|
||||
return GetUnitData(unitToken, copy)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Get a specific unit field
|
||||
function API.GetUnitFieldValue(unitToken, fieldName)
|
||||
-- Pass copy=1 to get an independent copy for array fields (v2.20+)
|
||||
function API.GetUnitFieldValue(unitToken, fieldName, copy)
|
||||
if not unitToken then return nil end
|
||||
|
||||
-- Use native function if available (more efficient)
|
||||
if GetUnitField then
|
||||
local success, result = pcall(GetUnitField, unitToken, fieldName)
|
||||
local success, result = pcall(GetUnitField, unitToken, fieldName, copy)
|
||||
if success then
|
||||
return result
|
||||
end
|
||||
@@ -651,7 +691,7 @@ function API.GetUnitFieldValue(unitToken, fieldName)
|
||||
end
|
||||
|
||||
-- Fallback to full record
|
||||
local data = API.GetUnitRecord(unitToken)
|
||||
local data = API.GetUnitRecord(unitToken, copy)
|
||||
if data then
|
||||
return data[fieldName]
|
||||
end
|
||||
@@ -660,13 +700,15 @@ function API.GetUnitFieldValue(unitToken, fieldName)
|
||||
end
|
||||
|
||||
-- Get unit's current auras as spell IDs
|
||||
function API.GetUnitAuras(unitToken)
|
||||
return API.GetUnitFieldValue(unitToken, "aura")
|
||||
-- Pass copy=1 to get an independent copy safe for storage (v2.20+)
|
||||
function API.GetUnitAuras(unitToken, copy)
|
||||
return API.GetUnitFieldValue(unitToken, "aura", copy)
|
||||
end
|
||||
|
||||
-- Get unit resistances table
|
||||
function API.GetUnitResistances(unitToken)
|
||||
return API.GetUnitFieldValue(unitToken, "resistances")
|
||||
-- Pass copy=1 to get an independent copy safe for storage (v2.20+)
|
||||
function API.GetUnitResistances(unitToken, copy)
|
||||
return API.GetUnitFieldValue(unitToken, "resistances", copy)
|
||||
end
|
||||
|
||||
-- Get specific resistance value
|
||||
@@ -1262,7 +1304,222 @@ function API.StopChannelNextTick()
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- EVENT CONSTANTS (v2.18+)
|
||||
-- TRINKET API (v2.20+)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Trinket slot constants
|
||||
API.TRINKET_SLOT = {
|
||||
FIRST = 13, -- First trinket slot (slot 13 in equipment)
|
||||
SECOND = 14, -- Second trinket slot (slot 14 in equipment)
|
||||
}
|
||||
|
||||
-- Get all trinkets (equipped and in bags)
|
||||
-- Returns table with: itemId, trinketName, texture, itemLevel, bagIndex (nil=equipped), slotIndex
|
||||
-- Pass copy=1 to get an independent copy safe for storage
|
||||
function API.GetTrinkets(copy)
|
||||
-- Use native function if available (v2.20+)
|
||||
if GetTrinkets then
|
||||
return GetTrinkets(copy)
|
||||
end
|
||||
|
||||
-- Fallback: manual enumeration
|
||||
local trinkets = {}
|
||||
local index = 1
|
||||
|
||||
-- Check equipped trinket slots (13 and 14)
|
||||
for _, slot in ipairs({13, 14}) do
|
||||
local link = GetInventoryItemLink("player", slot)
|
||||
if link then
|
||||
local _, _, itemId = string.find(link, "item:(%d+)")
|
||||
local _, _, name = string.find(link, "|h%[(.-)%]|h")
|
||||
local texture = GetInventoryItemTexture("player", slot)
|
||||
if itemId then
|
||||
trinkets[index] = {
|
||||
itemId = tonumber(itemId),
|
||||
trinketName = name or "Unknown",
|
||||
texture = texture,
|
||||
bagIndex = nil, -- nil means equipped
|
||||
slotIndex = slot == 13 and 1 or 2,
|
||||
}
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check bags for trinkets (inventoryType 12 = Trinket)
|
||||
for bag = 0, 4 do
|
||||
local numSlots = GetContainerNumSlots(bag) or 0
|
||||
for slot = 1, numSlots do
|
||||
local link = GetContainerItemLink(bag, slot)
|
||||
if link then
|
||||
local _, _, itemId = string.find(link, "item:(%d+)")
|
||||
if itemId then
|
||||
local invType = API.GetItemInventoryType(tonumber(itemId))
|
||||
if invType == 12 then -- Trinket
|
||||
local _, _, name = string.find(link, "|h%[(.-)%]|h")
|
||||
local texture = GetContainerItemInfo(bag, slot)
|
||||
trinkets[index] = {
|
||||
itemId = tonumber(itemId),
|
||||
trinketName = name or "Unknown",
|
||||
texture = texture,
|
||||
bagIndex = bag,
|
||||
slotIndex = slot,
|
||||
}
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return trinkets
|
||||
end
|
||||
|
||||
-- Get cooldown for an equipped trinket
|
||||
-- slot: 1 or 13 = first trinket, 2 or 14 = second trinket
|
||||
-- OR item ID (number) or item name (string) to match
|
||||
-- Returns cooldown detail table (same as GetSpellIdCooldown/GetItemIdCooldown)
|
||||
-- Returns -1 if no matching trinket is equipped
|
||||
function API.GetTrinketCooldown(slot)
|
||||
-- Use native function if available (v2.20+)
|
||||
if GetTrinketCooldown then
|
||||
return GetTrinketCooldown(slot)
|
||||
end
|
||||
|
||||
-- Normalize slot number
|
||||
local equipSlot
|
||||
if type(slot) == "number" then
|
||||
if slot == 1 or slot == 13 then
|
||||
equipSlot = 13
|
||||
elseif slot == 2 or slot == 14 then
|
||||
equipSlot = 14
|
||||
else
|
||||
-- Treat as item ID - find in trinket slots
|
||||
for _, checkSlot in ipairs({13, 14}) do
|
||||
local link = GetInventoryItemLink("player", checkSlot)
|
||||
if link then
|
||||
local _, _, currentId = string.find(link, "item:(%d+)")
|
||||
if currentId and tonumber(currentId) == slot then
|
||||
equipSlot = checkSlot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif type(slot) == "string" then
|
||||
-- Match by name
|
||||
local slotLower = string.lower(slot)
|
||||
for _, checkSlot in ipairs({13, 14}) do
|
||||
local link = GetInventoryItemLink("player", checkSlot)
|
||||
if link then
|
||||
local _, _, name = string.find(link, "|h%[(.-)%]|h")
|
||||
if name and string.lower(name) == slotLower then
|
||||
equipSlot = checkSlot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not equipSlot then
|
||||
return -1 -- No matching trinket found
|
||||
end
|
||||
|
||||
-- Get item ID from equipped slot
|
||||
local link = GetInventoryItemLink("player", equipSlot)
|
||||
if not link then
|
||||
return -1
|
||||
end
|
||||
|
||||
local _, _, itemId = string.find(link, "item:(%d+)")
|
||||
if not itemId then
|
||||
return -1
|
||||
end
|
||||
|
||||
-- Get cooldown info
|
||||
return API.GetItemCooldownInfo(tonumber(itemId))
|
||||
end
|
||||
|
||||
-- Use an equipped trinket
|
||||
-- slot: 1 or 13 = first trinket, 2 or 14 = second trinket
|
||||
-- OR item ID (number) or item name (string) to match
|
||||
-- target: optional unit token or GUID
|
||||
-- Returns: 1 if used, 0 if use failed, -1 if trinket not found
|
||||
function API.UseTrinket(slot, target)
|
||||
-- Use native function if available (v2.20+)
|
||||
if UseTrinket then
|
||||
return UseTrinket(slot, target)
|
||||
end
|
||||
|
||||
-- Normalize slot number
|
||||
local equipSlot
|
||||
if type(slot) == "number" then
|
||||
if slot == 1 or slot == 13 then
|
||||
equipSlot = 13
|
||||
elseif slot == 2 or slot == 14 then
|
||||
equipSlot = 14
|
||||
else
|
||||
-- Treat as item ID - find in trinket slots
|
||||
for _, checkSlot in ipairs({13, 14}) do
|
||||
local link = GetInventoryItemLink("player", checkSlot)
|
||||
if link then
|
||||
local _, _, currentId = string.find(link, "item:(%d+)")
|
||||
if currentId and tonumber(currentId) == slot then
|
||||
equipSlot = checkSlot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif type(slot) == "string" then
|
||||
-- Match by name
|
||||
local slotLower = string.lower(slot)
|
||||
for _, checkSlot in ipairs({13, 14}) do
|
||||
local link = GetInventoryItemLink("player", checkSlot)
|
||||
if link then
|
||||
local _, _, name = string.find(link, "|h%[(.-)%]|h")
|
||||
if name and string.lower(name) == slotLower then
|
||||
equipSlot = checkSlot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not equipSlot then
|
||||
return -1 -- No matching trinket found
|
||||
end
|
||||
|
||||
-- Use the trinket
|
||||
ClearCursor()
|
||||
UseInventoryItem(equipSlot)
|
||||
return 1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- ITEM USAGE API (v2.20+)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Use an item by ID or name
|
||||
-- itemIdOrName: item ID (number) or item name (string)
|
||||
-- target: optional unit token or GUID
|
||||
-- Returns: 1 if used successfully, 0 if not found or use failed
|
||||
function API.UseItemIdOrName(itemIdOrName, target)
|
||||
-- Use native function if available (v2.20+)
|
||||
if UseItemIdOrName then
|
||||
return UseItemIdOrName(itemIdOrName, target)
|
||||
end
|
||||
|
||||
-- Fallback: use existing API.UseItem
|
||||
if API.UseItem(itemIdOrName) then
|
||||
return 1
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- EVENT CONSTANTS (v2.18+, updated v2.20)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Spell queue event codes
|
||||
@@ -1286,6 +1543,7 @@ API.CAST_TYPE = {
|
||||
}
|
||||
|
||||
-- Buff/debuff event names (v2.18+)
|
||||
-- Parameters: guid, slot, spellId, stackCount, auraLevel (v2.20+)
|
||||
API.AURA_EVENTS = {
|
||||
"BUFF_ADDED_SELF",
|
||||
"BUFF_REMOVED_SELF",
|
||||
@@ -1297,6 +1555,27 @@ API.AURA_EVENTS = {
|
||||
"DEBUFF_REMOVED_OTHER",
|
||||
}
|
||||
|
||||
-- Aura cast event names (v2.20+, requires NP_EnableAuraCastEvents=1)
|
||||
-- Parameters: spellId, casterGuid, targetGuid, effect, effectAuraName,
|
||||
-- effectAmplitude, effectMiscValue, durationMs, auraCapStatus
|
||||
-- auraCapStatus bitfield: 1 = buff bar full, 2 = debuff bar full
|
||||
API.AURA_CAST_EVENTS = {
|
||||
"AURA_CAST_ON_SELF", -- Fires when aura lands on active player
|
||||
"AURA_CAST_ON_OTHER", -- Fires when aura lands on other units
|
||||
}
|
||||
|
||||
-- Aura cap status bitfield values (for AURA_CAST events)
|
||||
API.AURA_CAP_STATUS = {
|
||||
BUFF_BAR_FULL = 1,
|
||||
DEBUFF_BAR_FULL = 2,
|
||||
BOTH_FULL = 3,
|
||||
}
|
||||
|
||||
-- Unit events (v2.20+)
|
||||
API.UNIT_EVENTS = {
|
||||
"UNIT_DIED", -- Parameters: guid
|
||||
}
|
||||
|
||||
-- Spell school constants (for reference)
|
||||
API.SPELL_SCHOOL = {
|
||||
PHYSICAL = 0,
|
||||
|
||||
@@ -519,6 +519,7 @@ Default `[noimmune]` checks the debuff school (bleed).
|
||||
| mybuff | [mybuff:"Name"<X] | * | * | Player buff |
|
||||
| mybuffcount | [mybuffcount:>=X] | * | | Total buff count |
|
||||
| mydebuff | [mydebuff:"Name"<X] | * | * | Player debuff |
|
||||
| mycc | [mycc:stun/fear] | * | * | Player has CC effect |
|
||||
| myhp | [myhp:<=50] | * | | Player HP % |
|
||||
| myhplost | [myhplost:>=X] | * | | Player HP lost |
|
||||
| mylevel | [mylevel:>=60] | * | | Player level |
|
||||
@@ -560,6 +561,7 @@ Default `@unitid` is usually `@target` if not specified.
|
||||
| combat | [combat:target] | * | * | Unit in combat |
|
||||
| dead | [dead] | | * | Dead or ghost |
|
||||
| debuff | [debuff:"Name"<X] | * | * | Unit debuff |
|
||||
| cc | [cc:stun/fear] | * | * | Unit has CC effect |
|
||||
| distance | [distance:<40] | * | * | Distance in yards |
|
||||
| exists | [exists] | | * | Unit exists |
|
||||
| hastarget | [hastarget] | | | Player has a target |
|
||||
@@ -642,6 +644,46 @@ Revenge, Overpower, Riposte, Lacerate, Baited Shot, Counterattack, Arcane Surge
|
||||
|
||||
str/strength, agi/agility, stam/stamina, int/intellect, spi/spirit, ap/attackpower, rap/rangedattackpower, healing/healingpower, arcane_power, fire_power, frost_power, nature_power, shadow_power, armor, defense, arcane_res, fire_res, frost_res, nature_res, shadow_res
|
||||
|
||||
## CC Types (cc/mycc conditionals)
|
||||
|
||||
Crowd control detection using DBC spell mechanic data (785 spells).
|
||||
|
||||
| Type | Aliases | Examples |
|
||||
|------|---------|----------|
|
||||
| charm | | Mind Control, Seduction |
|
||||
| disorient | disoriented | Scatter Shot, Blind |
|
||||
| disarm | | Disarm |
|
||||
| distract | incapacitate | Distract (Rogue) |
|
||||
| fear | | Fear, Psychic Scream, Howl of Terror, Intimidating Shout |
|
||||
| grip | | Grip effects |
|
||||
| root | | Entangling Roots, Frost Nova, Improved Hamstring |
|
||||
| pacify | | Pacify effects |
|
||||
| silence | | Silence, Counterspell, Kick, Spell Lock |
|
||||
| sleep | | Hibernate, Wyvern Sting |
|
||||
| snare | slow | Hamstring, Wing Clip, Crippling Poison, Frostbolt |
|
||||
| stun | | Cheap Shot, Kidney Shot, Hammer of Justice, Bash, War Stomp |
|
||||
| freeze | | Frost Nova freeze |
|
||||
| knockout | incap | Gouge, Sap |
|
||||
| bleed | | Rend, Garrote, Deep Wounds |
|
||||
| polymorph | | Polymorph (all variants) |
|
||||
| banish | | Banish |
|
||||
| shackle | | Shackle Undead |
|
||||
| horror | | Death Coil |
|
||||
| daze | | Daze effects |
|
||||
| sap | sapped | Sap |
|
||||
|
||||
**Usage:**
|
||||
```lua
|
||||
/cast [cc:stun] Blessing of Freedom -- Target is stunned
|
||||
/cast [mycc:fear] Will of the Forsaken -- Player is feared
|
||||
/cast [@focus,nocc:polymorph] Fireball -- Focus not polymorphed
|
||||
/cast [cc:stun/fear/root] Dispel -- Any of these CCs
|
||||
/cast [nocc] Spell -- No loss-of-control CC
|
||||
```
|
||||
|
||||
`[cc]` or `[nocc]` without a type checks for any **loss-of-control** effect:
|
||||
stun, fear, sleep, charm, polymorph, banish, horror, freeze, knockout, disorient, shackle, sapped
|
||||
|
||||
---
|
||||
|
||||
# Supported Addons
|
||||
|
||||
Reference in New Issue
Block a user