10 Commits
Author SHA1 Message Date
Brues 86fb0254e6 Show autoattack icon and glow 2026-06-30 12:34:34 -05:00
Brues fc640abb07 Render known-spell action tooltips via spellbook slot, not spellID
GameTooltip.SetAction used GameTooltip:SetSpellByID for spell actions, which
renders the static DBC tooltip. For spells we resolved from the player's own
spellbook, use GameTooltip:SetSpell(spellSlot, bookType) instead so the
tooltip shows live player-accurate data (mana cost, cooldown, range coloring,
reagent counts). spellSlot/bookType/id all come from the same spellbook index
entry, so it renders the identical spell and rank. SetSpellByID remains as a
defensive fallback for entries without a slot. Applied to both the direct and
nested-macro tooltip paths.
2026-06-23 12:41:17 -05:00
Brues 3384765faa dont need pcall around registering events 2026-06-22 13:04:05 -05:00
Brues ceaf7c2c43 Refresh [moving] macro icons on movement via ClassicAPI
Register PLAYER_STARTED_MOVING (ClassicAPI, edge-detected off the WASD/
autorun key state) and queue an action update so [moving]/[nomoving] macro
icons repaint when movement starts.

PLAYER_STOPPED_MOVING is deliberately NOT used -- it's key-release based and
misses real stops (running into geometry, click-to-move, roots, knockback).
Instead, STARTED kicks off a 0.1s C_Timer.NewTicker that watches
IsPlayerMoving() (the same speed>0/falling signal [moving] evaluates) and, on
the actual stop, refreshes once and cancels itself. No timer exists while
stopped, so there's no idle cost; guarded on isShuttingDown and event-driven
mode (realtime==0).
2026-06-22 12:58:59 -05:00
Brues 963ad21297 Show resolved icon for question-mark macros in the macro list
Macros with no chosen icon (e.g. "#showtooltip Shoot") display Blizzard's
default question mark in the macro UI. After each MacroFrame_Update, swap
that placeholder for the icon the action bar would show, resolved from the
macro's #showtooltip/first action via GetMacroByIndex.

- Only replaces icons that are currently the question mark, so user-chosen
  icons are never touched.
- Covers both the list buttons (MacroButtonNIcon) and the selected-macro
  detail icon.
- Purely cosmetic: never changes the saved icon; Blizzard repaints the
  default on the next refresh if resolution fails or the macro changes.
- Installed in MacroErrorUI's existing hook path (gated on Blizzard_MacroUI
  load and the SuperMacro guard).
2026-06-22 00:35:19 -05:00
Brues ae09b23afd Resolve item sets via ClassicAPI; drop Reliquary dependency
Item-set membership and set info now read ItemSet.dbc directly through
ClassicAPI instead of the nampower/Reliquary glue, so set features no
longer require the Reliquary DLL to be installed.

- ClassicAPI.lua: add GetItemSetIDByID and GetItemSetInfo wrappers.
- Utility.lua: repoint ResolveSetItems, CountEquippedSetItemsBySetId,
  GetEquippedItemSetInfo, and GetEquippedSetPieceCount at the ClassicAPI
  accessors. Set-name matching now uses the DBC name (localized; identical
  to the old enUS path on English clients).
- NampowerAPI.lua: remove the now-unused GetItemSet/GetItemSetId/
  GetItemSetItems/GetItemSetBonuses, the dead GetSpellEffectRadius (no
  callers, only radius source was Reliquary), and the orphaned RQ_SafeCall.
- Init.lua: drop hasReliquary detection and its startup feature line.
- Conditionals.lua: update the [set:] comment (no longer Reliquary-gated).
2026-06-21 14:29:28 -05:00
Brues a8bf7fbc0f Identify equipped weapon type by item subclass, not localized name
HasWeaponEquipped matched the localized GetItemInfo subtype string, which
required a hand-maintained translation of all 13 weapon/shield subtypes per
locale plus brittle "^Fist"/last-word string parsing.

Use the locale-independent class/subclass IDs from C_Item.GetItemInfoInstant
instead:
- Init.lua: WeaponTypeNames entries now carry numeric class + subClass set
  (Axes/Swords/Maces span their 1H+2H subclasses; Shields are armor class 4).
- Conditionals.lua: HasWeaponEquipped resolves the slot's itemID via
  ClassicAPI GetInventoryItemID, then compares classID/subClassID -- no link
  parsing, no string munging.
- Localization.lua: drop the now-unused weapon-subtype strings from every
  locale block (112 lines).
2026-06-21 14:16:56 -05:00
Brues f0f57330c5 Drop dead localization entries
Remove localization data with no consumers anywhere in the addon:
- ItemTypes tables (Consumable/Reagent/Projectile/Trade Goods) - unused
- SpellRank patterns - unused (the live GetSpellRank is a BuffLib method)
- Spells keys Revenge, Overpower, Riposte, Surprise Attack, Lacerate,
  Baited Shot, Counterattack, Arcane Surge - unused; only Shadowform,
  Stealth, Prowl, Shadowmeld are referenced.

133 lines removed across all locale blocks; no behavior change.
2026-06-21 14:12:33 -05:00
Brues f21f90d0f1 Adopt ClassicAPI accessors: cursor, item IDs, spell mechanic
Lean on ClassicAPI's backported readers instead of link-string parsing
and a hand-maintained mechanic table.

- ClassicAPI.lua: add wrappers GetCursorInfo/CursorHoldsItemID,
  GetContainerItemID, GetInventoryItemID, and GetSpellMechanicByID.
- Core.lua: in the manual equip fallback, verify the cursor holds the
  intended item (CursorHoldsItemID) before EquipCursorItem, aborting only
  on a definitive mismatch so empty/unknown cursors behave as before.
- NampowerAPI.lua / Utility.lua: replace GetContainerItemLink /
  GetInventoryItemLink + "item:(%d+)" parsing with direct C_Container/
  inventory ID lookups at the sites that only need the itemID; route the
  equipped-set scans through the GetEquippedItemID helper.
- Conditionals.lua / Utility.lua: replace the 785-entry CCSpellMechanics
  fallback table with C_Spell.GetSpellMechanicByID in GetSpellMechanic and
  GetSpellCCType (BuffLib / nampower paths unchanged); delete the table.
2026-06-21 14:02:49 -05:00
Brues d435d90871 useless comment 2026-06-21 03:38:50 -05:00
9 changed files with 365 additions and 753 deletions
-2
View File
@@ -20,6 +20,4 @@ jobs:
- name: Package and release to GitHub - name: Package and release to GitHub
uses: BigWigsMods/packager@v2 uses: BigWigsMods/packager@v2
env: env:
# Only GITHUB_OAUTH is set, so the packager attaches the zip to a
# GitHub Release and uploads nothing to CurseForge/WoWInterface/Wago.
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }}
+71
View File
@@ -119,6 +119,55 @@ function API.GetActionInfo(slot)
return GetActionInfo(slot) return GetActionInfo(slot)
end end
--------------------------------------------------------------------------------
-- Container
--------------------------------------------------------------------------------
-- Base itemID in (bagID, slot), or nil for an empty/invalid slot. Same value
-- the "item:(%d+)" parse of GetContainerItemLink yields, but resolved straight
-- from the CGItem -- no link string built, no Lua pattern match.
function API.GetContainerItemID(bagID, slot)
return C_Container.GetContainerItemID(bagID, slot)
end
-- Base itemID equipped in `unit`'s 1-based inventory `slot` (1-19), or nil for
-- an empty slot / NPC unit. Same arg shape as GetInventoryItemLink and the same
-- value its "item:(%d+)" parse yields, resolved straight from the item instance.
function API.GetInventoryItemID(unit, slot)
return GetInventoryItemID(unit, slot)
end
--------------------------------------------------------------------------------
-- Item Set
--------------------------------------------------------------------------------
-- ItemSet.dbc ID that `itemID` belongs to, or nil if it isn't part of a set
-- (or isn't cached yet). Reads the item's m_itemSet field directly -- no
-- Reliquary, no per-set ItemID[] scan.
function API.GetItemSetIDByID(itemID)
return C_Item.GetItemSetIDByID(itemID)
end
-- Table describing an ItemSet.dbc row, or nil if `setID` doesn't resolve:
-- { setID, name (localized), requiredSkill, requiredSkillRank,
-- items = { itemID, ... }, bonuses = { { spellID, threshold }, ... } }
function API.GetItemSetInfo(setID)
return C_Item.GetItemSetInfo(setID)
end
--------------------------------------------------------------------------------
-- Spell
--------------------------------------------------------------------------------
-- WoW SpellMechanic enum ID for a spell, read straight from Spell.dbc -- covers
-- every spell the client knows, not just the spellbook (1=Charm, 5=Fear,
-- 7=Root, 12=Stun, 17=Polymorph, ...). Returns (mechanicID, enUS name); the ID
-- is 0 for a known spell with no mechanic, and the whole call is nil for an
-- invalid spell ID. Replaces hand-maintained spellID -> mechanic tables.
function API.GetSpellMechanicByID(spellID)
return C_Spell.GetSpellMechanicByID(spellID)
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- State -- State
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -133,6 +182,28 @@ function API.IsSwimming()
return IsSwimming() and true or false return IsSwimming() and true or false
end end
--------------------------------------------------------------------------------
-- Cursor
--------------------------------------------------------------------------------
function API.GetCursorInfo()
return GetCursorInfo()
end
-- Tri-state check of whether the cursor holds the item with `itemID`:
-- true -> cursor holds exactly that item
-- false -> cursor holds a DIFFERENT item
-- nil -> can't tell (cursor empty / not an item / itemID unknown)
-- Callers should only act on an explicit `false`, leaving the nil case to the
-- existing CursorHasItem() behavior.
function API.CursorHoldsItemID(itemID)
if not itemID then return nil end
local kind, id = GetCursorInfo()
if kind ~= "item" then return nil end
if not id then return nil end
return id == itemID
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- NamePlate -- NamePlate
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
+14 -186
View File
@@ -2094,34 +2094,21 @@ end
-- weaponType: The name of the weapon's type (e.g. Axe, Shield, etc.) -- weaponType: The name of the weapon's type (e.g. Axe, Shield, etc.)
-- returns: True when equipped, otherwhise false -- returns: True when equipped, otherwhise false
function CleveRoids.HasWeaponEquipped(weaponType) function CleveRoids.HasWeaponEquipped(weaponType)
if not CleveRoids.WeaponTypeNames[weaponType] then local def = CleveRoids.WeaponTypeNames[weaponType]
if not def then
return false return false
end end
local slotName = CleveRoids.WeaponTypeNames[weaponType].slot local slotId = GetInventorySlotInfo(def.slot)
local localizedName = CleveRoids.WeaponTypeNames[weaponType].name local itemId = CleveRoids.ClassicAPI.GetInventoryItemID("player", slotId)
local slotId = GetInventorySlotInfo(slotName) if not itemId then
local slotLink = GetInventoryItemLink("player",slotId)
if not slotLink then
return false return false
end end
local _,_,itemId = string.find(slotLink,"item:(%d+)") -- Compare locale-independent item class/subclass instead of matching the
if not itemId then -- Also good to check if itemId was found -- localized subtype string (GetItemInfoInstant: ..., classID, subClassID).
return false local _, _, _, _, _, classID, subClassID = C_Item.GetItemInfoInstant(itemId)
end return classID == def.class and def.subClass[subClassID] == true
local _name,_link,_,_lvl,_type,subtype = GetItemInfo(itemId)
-- just had to be special huh?
local fist = string.find(subtype,"^Fist")
-- drops things like the One-Handed prefix
local _,_,subtype = string.find(subtype,"%s?(%S+)$")
if subtype == localizedName or (fist and (CleveRoids.WeaponTypeNames[weaponType].name == CleveRoids.Localized.FistWeapon)) then
return true
end
return false
end end
-- Checks whether or not the given UnitId is in your party or your raid -- Checks whether or not the given UnitId is in your party or your raid
@@ -5187,165 +5174,6 @@ CleveRoids.CCTypesLossOfControl = {
[30] = true, -- sap (now part of stun group) [30] = true, -- sap (now part of stun group)
} }
-- 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 -- Check if BuffLib is available with full mechanic support
function CleveRoids.HasBuffLib() function CleveRoids.HasBuffLib()
-- Defensive: ensure BuffLib.SpellData is a table, not a function -- Defensive: ensure BuffLib.SpellData is a table, not a function
@@ -5354,7 +5182,7 @@ function CleveRoids.HasBuffLib()
and BuffLib.SpellData.GetMechanic and BuffLib.SpellData.GetMechanic
end end
-- Get mechanic for a spell ID (uses BuffLib if available, otherwise built-in table) -- Get mechanic for a spell ID (uses BuffLib if available, otherwise ClassicAPI's DBC reader)
function CleveRoids.GetSpellMechanic(spellID) function CleveRoids.GetSpellMechanic(spellID)
if not spellID or spellID <= 0 then return 0 end if not spellID or spellID <= 0 then return 0 end
@@ -5367,8 +5195,8 @@ function CleveRoids.GetSpellMechanic(spellID)
end end
end end
-- Fall back to built-in table -- Fall back to ClassicAPI's Spell.dbc reader (always present; covers every spell)
return CleveRoids.CCSpellMechanics[spellID] or 0 return CleveRoids.ClassicAPI.GetSpellMechanicByID(spellID) or 0
end end
-- Validate CC on a unit (target, focus, player, etc.) -- Validate CC on a unit (target, focus, player, etc.)
@@ -5923,8 +5751,8 @@ CleveRoids.Keywords = {
-- [set:SetName>=N] — true if equipped piece count of named set meets comparison -- [set:SetName>=N] — true if equipped piece count of named set meets comparison
-- [set:SetName] — true if any pieces of that set are equipped (count > 0) -- [set:SetName] — true if any pieces of that set are equipped (count > 0)
-- [set:123>=3] — numeric IDs also supported (Nampower only, no Reliquary needed) -- [set:123>=3] — numeric IDs also supported
-- Name lookup requires Reliquary (for DBC set name); ID lookup requires Nampower -- Both name and ID lookups resolve from ItemSet.dbc via ClassicAPI
set = function(conditionals) set = function(conditionals)
return Multi(conditionals.set, function(args) return Multi(conditionals.set, function(args)
if type(args) == "table" and args.operator and args.amount then if type(args) == "table" and args.operator and args.amount then
+89 -7
View File
@@ -3721,6 +3721,19 @@ function CleveRoids.EquipBagItem(msg, slotOrOffhand)
return false return false
end end
-- Verify the cursor holds the item we meant to pick up. The bag can shift
-- between the lookup and the pickup (item consumed/moved/reorganized), in
-- which case we'd otherwise equip whatever landed on the cursor. Only abort
-- on a definitive mismatch (false); nil = can't tell -> trust CursorHasItem.
if item.id and CleveRoids.ClassicAPI.CursorHoldsItemID(item.id) == false then
if CleveRoids.equipDebugLog then
CleveRoids.Print("|cffff8800[EquipLog] Cursor holds wrong item after pickup; aborting equip|r")
end
ClearCursor()
CleveRoids.equipInProgress = false
return false
end
EquipCursorItem(invslot) EquipCursorItem(invslot)
ClearCursor() ClearCursor()
@@ -4412,9 +4425,11 @@ function GameTooltip.SetAction(self, slot)
local current_spell_data = CleveRoids.GetSpell(action_name) local current_spell_data = CleveRoids.GetSpell(action_name)
if current_spell_data and current_spell_data.id then if current_spell_data and current_spell_data.id then
-- ClassicAPI: render by spellID (rank included) instead of routing if current_spell_data.spellSlot and current_spell_data.bookType then
-- through the spellbook slot via SetSpell(spellSlot, bookType). GameTooltip:SetSpell(current_spell_data.spellSlot, current_spell_data.bookType)
GameTooltip:SetSpellByID(current_spell_data.id) else
GameTooltip:SetSpellByID(current_spell_data.id)
end
GameTooltip:Show() GameTooltip:Show()
return return
end end
@@ -4440,7 +4455,11 @@ function GameTooltip.SetAction(self, slot)
current_spell_data = CleveRoids.GetSpell(nested_action_name) current_spell_data = CleveRoids.GetSpell(nested_action_name)
if current_spell_data and current_spell_data.id then if current_spell_data and current_spell_data.id then
GameTooltip:SetSpellByID(current_spell_data.id) if current_spell_data.spellSlot and current_spell_data.bookType then
GameTooltip:SetSpell(current_spell_data.spellSlot, current_spell_data.bookType)
else
GameTooltip:SetSpellByID(current_spell_data.id)
end
GameTooltip:Show() GameTooltip:Show()
return return
end end
@@ -4637,6 +4656,10 @@ function IsCurrentAction(slot)
else else
local name local name
if actionToCheck.spell then if actionToCheck.spell then
if CleveRoids.IsAutoAttackSpell(actionToCheck.spell) then
return CleveRoids.CurrentSpell.autoAttack and 1 or nil
end
local rank = actionToCheck.spell.rank or actionToCheck.spell.highest.rank local rank = actionToCheck.spell.rank or actionToCheck.spell.highest.rank
name = actionToCheck.spell.name..(rank and ("("..rank..")")) name = actionToCheck.spell.name..(rank and ("("..rank..")"))
@@ -4679,9 +4702,6 @@ function IsCurrentAction(slot)
end end
end end
-- Macro icon for an action slot, via ClassicAPI's GetActionInfo (macro slot
-- directly, no GetActionText -> GetMacroIndexByName name round-trip).
-- Returns the macro texture, or nil if the slot isn't a macro / has no icon.
local function GetSlotMacroTexture(slot) local function GetSlotMacroTexture(slot)
local kind, macroId = CleveRoids.ClassicAPI.GetActionInfo(slot) local kind, macroId = CleveRoids.ClassicAPI.GetActionInfo(slot)
if kind == "macro" and macroId then if kind == "macro" and macroId then
@@ -4691,6 +4711,18 @@ local function GetSlotMacroTexture(slot)
return nil return nil
end end
local function IsAutoAttackSpell(spell)
if not spell then return false end
if C_Spell and C_Spell.IsAutoAttackSpell and spell.id then
return C_Spell.IsAutoAttackSpell(spell.id)
end
if C_SpellBook and C_SpellBook.IsAutoAttackSpellBookItem and spell.spellSlot then
return C_SpellBook.IsAutoAttackSpellBookItem(spell.spellSlot, spell.bookType)
end
return false
end
CleveRoids.IsAutoAttackSpell = IsAutoAttackSpell
CleveRoids.Hooks.GetActionTexture = GetActionTexture CleveRoids.Hooks.GetActionTexture = GetActionTexture
function GetActionTexture(slot) function GetActionTexture(slot)
if not slot then return nil end if not slot then return nil end
@@ -4779,6 +4811,13 @@ function GetActionTexture(slot)
end end
end end
if a and a.spell and CleveRoids.IsAutoAttackSpell(a.spell) then
local mainHandTexture = GetInventoryItemTexture("player", 16)
if mainHandTexture then
texture = mainHandTexture
end
end
if texture then if texture then
return texture return texture
end end
@@ -5075,6 +5114,7 @@ CleveRoids.Frame:RegisterEvent("PLAYER_REGEN_DISABLED") -- Entered actual combat
CleveRoids.Frame:RegisterEvent("PLAYER_REGEN_ENABLED") -- Left actual combat (no threat) CleveRoids.Frame:RegisterEvent("PLAYER_REGEN_ENABLED") -- Left actual combat (no threat)
CleveRoids.Frame:RegisterEvent("UPDATE_SHAPESHIFT_FORM") CleveRoids.Frame:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
CleveRoids.Frame:RegisterEvent("SPELL_UPDATE_COOLDOWN") CleveRoids.Frame:RegisterEvent("SPELL_UPDATE_COOLDOWN")
CleveRoids.Frame:RegisterEvent("PLAYER_STARTED_MOVING")
-- Use GUID events when available (v2.39+), fall back to standard per-token events -- Use GUID events when available (v2.39+), fall back to standard per-token events
if CleveRoids.NampowerAPI.features.hasUnitGuidEvents then if CleveRoids.NampowerAPI.features.hasUnitGuidEvents then
CleveRoids.Frame:RegisterEvent("UNIT_AURA_GUID") CleveRoids.Frame:RegisterEvent("UNIT_AURA_GUID")
@@ -5791,6 +5831,48 @@ function CleveRoids.Frame:PLAYER_REGEN_ENABLED()
end end
end end
-- Movement -> [moving]/[nomoving] icon refresh.
-- PLAYER_STARTED_MOVING is reliable; PLAYER_STOPPED_MOVING is not (key-release
-- based, misses geometry/click-to-move/root/knockback stops). So STARTED flips
-- the icon to "moving" and starts a bounded poll; the poll detects the real
-- stop from IsPlayerMoving() (the signal [moving] uses), refreshes once, and
-- shuts itself off. Only runs while actually moving, so no idle cost.
local MOVE_POLL_INTERVAL = 0.1
local moveTicker = nil
local function StopMovePoll()
if moveTicker then
moveTicker:Cancel()
moveTicker = nil
end
end
local function StartMovePoll()
if moveTicker then return end -- already polling this movement
moveTicker = C_Timer.NewTicker(MOVE_POLL_INTERVAL, function()
if CleveRoids.isShuttingDown then
StopMovePoll()
return
end
if not CleveRoids.IsPlayerMoving() then
-- Movement actually ended -- repaint [moving]/[nomoving] icons, stop polling.
StopMovePoll()
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
end
end
end)
end
function CleveRoids.Frame:PLAYER_STARTED_MOVING()
-- Started moving: flip to the [moving] icon now...
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
end
-- ...and watch for the (unreliable-event) stop ourselves.
StartMovePoll()
end
function CleveRoids.Frame:PLAYER_TARGET_CHANGED() function CleveRoids.Frame:PLAYER_TARGET_CHANGED()
CleveRoids.CurrentSpell.autoAttack = false CleveRoids.CurrentSpell.autoAttack = false
CleveRoids.CurrentSpell.autoAttackLock = false CleveRoids.CurrentSpell.autoAttackLock = false
+59
View File
@@ -1274,6 +1274,56 @@ end
-- Hook Installation -- Hook Installation
-- ============================================================================ -- ============================================================================
-- ============================================================================
-- Dynamic macro-list icons
-- Blizzard shows the default question-mark icon for macros with no chosen icon
-- (e.g. "#showtooltip Shoot"). Replace it with the icon the action bar would
-- show -- resolved from the macro's #showtooltip/first action -- but ONLY when
-- the saved icon is the question mark, so user-chosen icons are never touched.
-- Purely cosmetic: Blizzard repaints from GetMacroInfo on the next update, so
-- if resolution fails or the macro changes, the default simply returns.
-- ============================================================================
local QUESTION_MARK = string.lower(CleveRoids.unknownTexture or "Interface\\Icons\\INV_Misc_QuestionMark")
local function IsQuestionMark(iconTexture)
local tex = iconTexture and iconTexture:GetTexture()
return type(tex) == "string" and string.lower(tex) == QUESTION_MARK
end
-- Resolved tooltip texture for a Blizzard macro index, or nil when it resolves
-- to nothing better than the question mark (no #showtooltip, unresolved spell).
local function ResolveMacroIcon(macroIndex)
if not macroIndex or macroIndex < 1 then return nil end
local ok, macro = pcall(CleveRoids.GetMacroByIndex, macroIndex)
if not ok or not macro or not macro.actions or not macro.actions.tooltip then return nil end
local tex = macro.actions.tooltip.texture
if type(tex) == "string" and string.lower(tex) ~= QUESTION_MARK then
return tex
end
return nil
end
local function FixMacroListIcons()
if not MacroFrame or not MacroFrame:IsVisible() then return end
local base = MacroFrame.macroBase or 0
for i = 1, (MAX_MACROS or 18) do
local icon = getglobal("MacroButton" .. i .. "Icon")
if icon and IsQuestionMark(icon) then
local tex = ResolveMacroIcon(base + i)
if tex then icon:SetTexture(tex) end
end
end
-- Large icon for the currently-selected macro (details pane).
if MacroFrame.selectedMacro and MacroFrameSelectedMacroButtonIcon
and IsQuestionMark(MacroFrameSelectedMacroButtonIcon) then
local tex = ResolveMacroIcon(MacroFrame.selectedMacro)
if tex then MacroFrameSelectedMacroButtonIcon:SetTexture(tex) end
end
end
local function InstallHooks() local function InstallHooks()
if hooked then return end if hooked then return end
if not MacroFrameText or not MacroFrame then return end if not MacroFrameText or not MacroFrame then return end
@@ -1325,6 +1375,15 @@ local function InstallHooks()
end end
end) end)
-- After every Blizzard macro-list refresh, swap question-mark icons for the
-- dynamically-resolved ones. Post-hook so Blizzard has already set the
-- default texture we test against.
if hooksecurefunc and type(MacroFrame_Update) == "function" then
hooksecurefunc("MacroFrame_Update", function()
pcall(FixMacroListIcons)
end)
end
hooked = true hooked = true
end end
+23 -28
View File
@@ -22,7 +22,6 @@ CleveRoids.mouseOverUnit = nil
-- Environment flags -- Environment flags
CleveRoids.hasSuperwow = SetAutoloot and true or false CleveRoids.hasSuperwow = SetAutoloot and true or false
CleveRoids.hasTurtle = (type(_G.TURTLE_WOW_VERSION) ~= "nil") CleveRoids.hasTurtle = (type(_G.TURTLE_WOW_VERSION) ~= "nil")
CleveRoids.hasReliquary = (RQ_GetVersion ~= nil)
CleveRoids.supported = CleveRoids.hasTurtle CleveRoids.supported = CleveRoids.hasTurtle
CleveRoids.ParsedMsg = {} CleveRoids.ParsedMsg = {}
@@ -242,28 +241,32 @@ CleveRoids.auraTextures = {
-- I need to make a 2h modifier -- I need to make a 2h modifier
-- Maps easy to use weapon type names (e.g. Axes, Shields) to their inventory slot name and their localized tooltip name -- Maps easy-to-use weapon type names (e.g. Axes, Shields) to their inventory
-- slot plus the locale-independent item class/subclass IDs that identify them
-- (read via C_Item.GetItemInfoInstant). class 2 = Weapon, 4 = Armor (shields).
-- subClass is a set because the logical "Axes"/"Swords"/"Maces" types span both
-- the one-handed and two-handed weapon subclasses.
CleveRoids.WeaponTypeNames = { CleveRoids.WeaponTypeNames = {
Daggers = { slot = "MainHandSlot", name = CleveRoids.Localized.Dagger }, Daggers = { slot = "MainHandSlot", class = 2, subClass = { [15] = true } },
Fists = { slot = "MainHandSlot", name = CleveRoids.Localized.FistWeapon }, Fists = { slot = "MainHandSlot", class = 2, subClass = { [13] = true } },
Axes = { slot = "MainHandSlot", name = CleveRoids.Localized.Axe }, Axes = { slot = "MainHandSlot", class = 2, subClass = { [0] = true, [1] = true } },
Swords = { slot = "MainHandSlot", name = CleveRoids.Localized.Sword }, Swords = { slot = "MainHandSlot", class = 2, subClass = { [7] = true, [8] = true } },
Staves = { slot = "MainHandSlot", name = CleveRoids.Localized.Staff }, Staves = { slot = "MainHandSlot", class = 2, subClass = { [10] = true } },
Maces = { slot = "MainHandSlot", name = CleveRoids.Localized.Mace }, Maces = { slot = "MainHandSlot", class = 2, subClass = { [4] = true, [5] = true } },
Polearms = { slot = "MainHandSlot", name = CleveRoids.Localized.Polearm }, Polearms = { slot = "MainHandSlot", class = 2, subClass = { [6] = true } },
-- OH -- OH
Daggers2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Dagger }, Daggers2 = { slot = "SecondaryHandSlot", class = 2, subClass = { [15] = true } },
Fists2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.FistWeapon }, Fists2 = { slot = "SecondaryHandSlot", class = 2, subClass = { [13] = true } },
Axes2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Axe }, Axes2 = { slot = "SecondaryHandSlot", class = 2, subClass = { [0] = true, [1] = true } },
Swords2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Sword }, Swords2 = { slot = "SecondaryHandSlot", class = 2, subClass = { [7] = true, [8] = true } },
Maces2 = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Mace }, Maces2 = { slot = "SecondaryHandSlot", class = 2, subClass = { [4] = true, [5] = true } },
Shields = { slot = "SecondaryHandSlot", name = CleveRoids.Localized.Shield }, Shields = { slot = "SecondaryHandSlot", class = 4, subClass = { [6] = true } },
-- ranged -- ranged
Guns = { slot = "RangedSlot", name = CleveRoids.Localized.Gun }, Guns = { slot = "RangedSlot", class = 2, subClass = { [3] = true } },
Crossbows = { slot = "RangedSlot", name = CleveRoids.Localized.Crossbow }, Crossbows = { slot = "RangedSlot", class = 2, subClass = { [18] = true } },
Bows = { slot = "RangedSlot", name = CleveRoids.Localized.Bow }, Bows = { slot = "RangedSlot", class = 2, subClass = { [2] = true } },
Thrown = { slot = "RangedSlot", name = CleveRoids.Localized.Thrown }, Thrown = { slot = "RangedSlot", class = 2, subClass = { [16] = true } },
Wands = { slot = "RangedSlot", name = CleveRoids.Localized.Wand }, Wands = { slot = "RangedSlot", class = 2, subClass = { [19] = true } },
} }
-- Detect available features -- Detect available features
@@ -287,14 +290,6 @@ local function PrintFeatures()
end end
end end
if CleveRoids.hasUnitXP then table.insert(features, "UnitXP") end if CleveRoids.hasUnitXP then table.insert(features, "UnitXP") end
if CleveRoids.hasReliquary then
local ok, major, minor, patch = pcall(RQ_GetVersion)
if ok and major then
table.insert(features, string.format("Reliquary v%d.%d.%d", major, minor, patch))
else
table.insert(features, "Reliquary")
end
end
if CleveRoids.hasTurtle then table.insert(features, "Turtle") end if CleveRoids.hasTurtle then table.insert(features, "Turtle") end
if table.getn(features) > 0 then if table.getn(features) > 0 then
-245
View File
@@ -8,26 +8,9 @@ CleveRoids.Locale = GetLocale()
CleveRoids.Localized = {} CleveRoids.Localized = {}
if CleveRoids.Locale == "enUS" or CleveRoids.Locale == "enGB" then if CleveRoids.Locale == "enUS" or CleveRoids.Locale == "enGB" then
-- place item in backpack slot 1 and run:
-- /script local l=GetContainerItemLink(0,1);local _,_,id=string.find(l,"item:(%d+)");local n,_,_,_,t,st=GetItemInfo(id);DEFAULT_CHAT_FRAME:AddMessage("\n\nID: ["..id.."]\nName: ["..n.."]\nType: ["..t.."]\nSub Type: ["..st.."]\n\n");
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack" CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot" CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot" CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
-- target creature and run: -- target creature and run:
-- /script local ct, uc = UnitCreatureType("target"),UnitClassification("target"); DEFAULT_CHAT_FRAME:AddMessage("\n\nUnitCreatureType: ["..ct.."]\nUnitClassificationType: ["..uc.."]\n\n"); -- /script local ct, uc = UnitCreatureType("target"),UnitClassification("target"); DEFAULT_CHAT_FRAME:AddMessage("\n\nUnitCreatureType: ["..ct.."]\nUnitClassificationType: ["..uc.."]\n\n");
@@ -50,43 +33,11 @@ if CleveRoids.Locale == "enUS" or CleveRoids.Locale == "enGB" then
["Stealth"] = "Stealth", ["Stealth"] = "Stealth",
["Prowl"] = "Prowl", ["Prowl"] = "Prowl",
["Shadowmeld"] = "Shadowmeld", ["Shadowmeld"] = "Shadowmeld",
["Revenge"] = "Revenge",
["Overpower"] = "Overpower",
["Riposte"] = "Riposte",
["Surprise Attack"] = "Surprise Attack",
["Lacerate"] = "Lacerate",
["Baited Shot"] = "Baited Shot",
["Counterattack"] = "Counterattack",
["Arcane Surge"] = "Arcane Surge",
}
-- place item in backpack slot 1 and run:
-- /script local l=GetContainerItemLink(0,1);local _,_,id=string.find(l,"item:(%d+)");local n,_,_,_,t,st=GetItemInfo(id);DEFAULT_CHAT_FRAME:AddMessage("\n\nID: ["..id.."]\nName: ["..n.."]\nType: ["..t.."]\nSub Type: ["..st.."]\n\n");
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Consumable",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Trade Goods",
} }
elseif CleveRoids.Locale == "deDE" then elseif CleveRoids.Locale == "deDE" then
CleveRoids.Localized.Shield = "Schilde"
CleveRoids.Localized.Bow = "Bögen"
CleveRoids.Localized.Crossbow = "Armbrüste"
CleveRoids.Localized.Gun = "Waffen"
CleveRoids.Localized.Thrown = "Geworfen"
CleveRoids.Localized.Wand = "Zauberstäbe"
CleveRoids.Localized.Sword = "Schwerter"
CleveRoids.Localized.Staff = "Dauben"
CleveRoids.Localized.Polearm = "Stangenwaffen"
CleveRoids.Localized.Mace = "Streitkolben"
CleveRoids.Localized.FistWeapon = "Faustwaffen"
CleveRoids.Localized.Dagger = "Dolche"
CleveRoids.Localized.Axe = "Äxte"
CleveRoids.Localized.Attack = "Angriff" CleveRoids.Localized.Attack = "Angriff"
CleveRoids.Localized.AutoShot = "Automatischer Schuss" CleveRoids.Localized.AutoShot = "Automatischer Schuss"
CleveRoids.Localized.Shoot = "Schießen" CleveRoids.Localized.Shoot = "Schießen"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "Wildtier", ["Beast"] = "Wildtier",
@@ -108,42 +59,11 @@ elseif CleveRoids.Locale == "deDE" then
["Stealth"] = "Verstohlenheit", ["Stealth"] = "Verstohlenheit",
["Prowl"] = "Schleichen", ["Prowl"] = "Schleichen",
["Shadowmeld"] = "Schattenmimik", ["Shadowmeld"] = "Schattenmimik",
["Revenge"] = "Rache",
["Overpower"] = "Überwältigen",
["Riposte"] = "Riposte",
["Surprise Attack"] = "Überraschungsangriff",
["Lacerate"] = "Zerfleischen",
["Baited Shot"] = "Köderschuss",
["Counterattack"] = "Gegenangriff",
["Arcane Surge"] = "Arkane Woge",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Verbrauchsmaterial",
["Reagent"] = "Reagens",
["Projectile"] = "Projektil",
["Trade Goods"] = "Handwerkswaren",
} }
elseif CleveRoids.Locale == "frFR" then elseif CleveRoids.Locale == "frFR" then
CleveRoids.Localized.Shield = "Boucliers"
CleveRoids.Localized.Bow = "Arcs"
CleveRoids.Localized.Crossbow = "Arbalètes"
CleveRoids.Localized.Gun = "Armes à feu"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack" CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot" CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot" CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "Bête", ["Beast"] = "Bête",
@@ -164,41 +84,11 @@ elseif CleveRoids.Locale == "frFR" then
["Stealth"] = "Camouflage", ["Stealth"] = "Camouflage",
["Prowl"] = "Rôder", ["Prowl"] = "Rôder",
["Shadowmeld"] = "Camouflage dans l'ombre", ["Shadowmeld"] = "Camouflage dans l'ombre",
["Revenge"] = "Vengeance",
["Overpower"] = "Fulgurance",
["Riposte"] = "Riposte",
["Surprise Attack"] = "Attaque surprise",
["Lacerate"] = "Lacérer",
["Baited Shot"] = "Tir appâté",
["Counterattack"] = "Contre-attaque",
["Arcane Surge"] = "Éruption d’arcanes",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Consommable",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Artisanat",
} }
elseif CleveRoids.Locale == "koKR" then elseif CleveRoids.Locale == "koKR" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack" CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot" CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot" CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "야수", ["Beast"] = "야수",
@@ -219,41 +109,11 @@ elseif CleveRoids.Locale == "koKR" then
["Stealth"] = "은신", ["Stealth"] = "은신",
["Prowl"] = "숨기", ["Prowl"] = "숨기",
["Shadowmeld"] = "그림자 숨기", ["Shadowmeld"] = "그림자 숨기",
["Revenge"] = "복수",
["Overpower"] = "제압",
["Riposte"] = "반격",
["Surprise Attack"] = "기습",
["Lacerate"] = "괴롭히다",
["Baited Shot"] = "베이티드 샷",
["Counterattack"] = "역습",
["Arcane Surge"] = "비전 쇄도",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "소모품",
["Reagent"] = "재료",
["Projectile"] = "발사체",
["Trade Goods"] = "거래 용품",
} }
elseif CleveRoids.Locale == "zhCN" then elseif CleveRoids.Locale == "zhCN" then
CleveRoids.Localized.Shield = "盾牌"
CleveRoids.Localized.Bow = "弓"
CleveRoids.Localized.Crossbow = "弩"
CleveRoids.Localized.Gun = "枪械"
CleveRoids.Localized.Thrown = "投掷武器"
CleveRoids.Localized.Wand = "魔杖"
CleveRoids.Localized.Sword = "剑"
CleveRoids.Localized.Staff = "法杖"
CleveRoids.Localized.Polearm = "长柄武器"
CleveRoids.Localized.Mace = "锤"
CleveRoids.Localized.FistWeapon = "拳套"
CleveRoids.Localized.Dagger = "匕首"
CleveRoids.Localized.Axe = "斧"
CleveRoids.Localized.Attack = "攻击" CleveRoids.Localized.Attack = "攻击"
CleveRoids.Localized.AutoShot = "自动射击" CleveRoids.Localized.AutoShot = "自动射击"
CleveRoids.Localized.Shoot = "射击" CleveRoids.Localized.Shoot = "射击"
CleveRoids.Localized.SpellRank = "%(等级 %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "野兽", ["Beast"] = "野兽",
@@ -274,41 +134,11 @@ elseif CleveRoids.Locale == "zhCN" then
["Stealth"] = "潜行", ["Stealth"] = "潜行",
["Prowl"] = "潜行", ["Prowl"] = "潜行",
["Shadowmeld"] = "影遁", ["Shadowmeld"] = "影遁",
["Revenge"] = "复仇",
["Overpower"] = "压制",
["Riposte"] = "还击",
["Surprise Attack"] = "偷袭",
["Lacerate"] = "划破",
["Baited Shot"] = "诱饵射击",
["Counterattack"] = "反击",
["Arcane Surge"] = "奥术涌动",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "消耗品",
["Reagent"] = "材料",
["Projectile"] = "弹药",
["Trade Goods"] = "商品",
} }
elseif CleveRoids.Locale == "zhTW" then elseif CleveRoids.Locale == "zhTW" then
CleveRoids.Localized.Shield = "盾牌"
CleveRoids.Localized.Bow = "長弓"
CleveRoids.Localized.Crossbow = "弩"
CleveRoids.Localized.Gun = "槍械"
CleveRoids.Localized.Thrown = "投擲武器"
CleveRoids.Localized.Wand = "魔杖"
CleveRoids.Localized.Sword = "劍"
CleveRoids.Localized.Staff = "法杖"
CleveRoids.Localized.Polearm = "長柄武器"
CleveRoids.Localized.Mace = "錘"
CleveRoids.Localized.FistWeapon = "拳套"
CleveRoids.Localized.Dagger = "匕首"
CleveRoids.Localized.Axe = "斧"
CleveRoids.Localized.Attack = "攻擊" CleveRoids.Localized.Attack = "攻擊"
CleveRoids.Localized.AutoShot = "自動射擊" CleveRoids.Localized.AutoShot = "自動射擊"
CleveRoids.Localized.Shoot = "射擊" CleveRoids.Localized.Shoot = "射擊"
CleveRoids.Localized.SpellRank = "%(等級 %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "野獸", ["Beast"] = "野獸",
@@ -329,41 +159,11 @@ elseif CleveRoids.Locale == "zhTW" then
["Stealth"] = "隱形", ["Stealth"] = "隱形",
["Prowl"] = "徘徊", ["Prowl"] = "徘徊",
["Shadowmeld"] = "影遁", ["Shadowmeld"] = "影遁",
["Revenge"] = "復仇",
["Overpower"] = "壓倒",
["Riposte"] = "還擊",
["Surprise Attack"] = "偷襲",
["Lacerate"] = "劃破",
["Baited Shot"] = "誘餌射擊",
["Counterattack"] = "反擊",
["Arcane Surge"] = "奧術湧動",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "消耗品",
["Reagent"] = "材料",
["Projectile"] = "彈藥",
["Trade Goods"] = "貿易貨物",
} }
elseif CleveRoids.Locale == "ruRU" then elseif CleveRoids.Locale == "ruRU" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack" CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot" CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot" CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "Животное", ["Beast"] = "Животное",
@@ -384,41 +184,11 @@ elseif CleveRoids.Locale == "ruRU" then
["Stealth"] = "Незаметность", ["Stealth"] = "Незаметность",
["Prowl"] = "Крадущийся зверь", ["Prowl"] = "Крадущийся зверь",
["Shadowmeld"] = "Слияние с тенью", ["Shadowmeld"] = "Слияние с тенью",
["Revenge"] = "Реванш",
["Overpower"] = "Превосходство",
["Riposte"] = "Ответный удар",
["Surprise Attack"] = "Внезапная атака",
["Lacerate"] = "Разрыв",
["Baited Shot"] = "Выстрел с наживкой",
["Counterattack"] = "Контратака",
["Arcane Surge"] = "Чародейский выброс",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Расходный материал",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Хозяйственные товары",
} }
elseif CleveRoids.Locale == "esES" then elseif CleveRoids.Locale == "esES" then
CleveRoids.Localized.Shield = "Shields"
CleveRoids.Localized.Bow = "Bows"
CleveRoids.Localized.Crossbow = "Crossbows"
CleveRoids.Localized.Gun = "Guns"
CleveRoids.Localized.Thrown = "Thrown"
CleveRoids.Localized.Wand = "Wands"
CleveRoids.Localized.Sword = "Swords"
CleveRoids.Localized.Staff = "Staves"
CleveRoids.Localized.Polearm = "Polearms"
CleveRoids.Localized.Mace = "Maces"
CleveRoids.Localized.FistWeapon = "Fist Weapons"
CleveRoids.Localized.Dagger = "Daggers"
CleveRoids.Localized.Axe = "Axes"
CleveRoids.Localized.Attack = "Attack" CleveRoids.Localized.Attack = "Attack"
CleveRoids.Localized.AutoShot = "Auto Shot" CleveRoids.Localized.AutoShot = "Auto Shot"
CleveRoids.Localized.Shoot = "Shoot" CleveRoids.Localized.Shoot = "Shoot"
CleveRoids.Localized.SpellRank = "%(Rank %d+%)"
CleveRoids.Localized.CreatureTypes = { CleveRoids.Localized.CreatureTypes = {
["Beast"] = "Bestia", ["Beast"] = "Bestia",
@@ -439,21 +209,6 @@ elseif CleveRoids.Locale == "esES" then
["Stealth"] = "Sigilo", ["Stealth"] = "Sigilo",
["Prowl"] = "Acechar", ["Prowl"] = "Acechar",
["Shadowmeld"] = "Fusión con las sombras", ["Shadowmeld"] = "Fusión con las sombras",
["Revenge"] = "Revancha",
["Overpower"] = "Abrumar",
["Riposte"] = "Estocada",
["Surprise Attack"] = "Ataque sorpresa",
["Lacerate"] = "Lacerar",
["Baited Shot"] = "Disparo con cebo",
["Counterattack"] = "Contraataque",
["Arcane Surge"] = "Oleada Arcana",
}
CleveRoids.Localized.ItemTypes = {
["Consumable"] = "Consumible",
["Reagent"] = "Reagent",
["Projectile"] = "Projectile",
["Trade Goods"] = "Objetos comerciables",
} }
end end
+59 -190
View File
@@ -1493,15 +1493,12 @@ function API.GetEquippedItems(unitToken)
local items = {} local items = {}
for slot = 0, 18 do for slot = 0, 18 do
local link = GetInventoryItemLink("player", slot + 1) local itemId = CleveRoids.ClassicAPI.GetInventoryItemID("player", slot + 1)
if link then if itemId then
local _, _, itemId = string.find(link, "item:(%d+)") items[slot] = {
if itemId then itemId = itemId,
items[slot] = { -- Other fields not available without native API
itemId = tonumber(itemId), }
-- Other fields not available without native API
}
end
end end
end end
@@ -1524,14 +1521,11 @@ function API.GetEquippedItem(unitToken, slot)
return nil return nil
end end
local link = GetInventoryItemLink("player", slot + 1) -- 1-indexed local itemId = CleveRoids.ClassicAPI.GetInventoryItemID("player", slot + 1) -- 1-indexed
if link then if itemId then
local _, _, itemId = string.find(link, "item:(%d+)") return {
if itemId then itemId = itemId,
return { }
itemId = tonumber(itemId),
}
end
end end
return nil return nil
@@ -1560,16 +1554,13 @@ function API.GetBagItems(bagIndex)
local bagContents = {} local bagContents = {}
local numSlots = GetContainerNumSlots(bagIndex) or 0 local numSlots = GetContainerNumSlots(bagIndex) or 0
for slot = 1, numSlots do for slot = 1, numSlots do
local link = GetContainerItemLink(bagIndex, slot) local itemId = CleveRoids.ClassicAPI.GetContainerItemID(bagIndex, slot)
if link then if itemId then
local _, _, itemId = string.find(link, "item:(%d+)")
local _, count = GetContainerItemInfo(bagIndex, slot) local _, count = GetContainerItemInfo(bagIndex, slot)
if itemId then bagContents[slot] = {
bagContents[slot] = { itemId = itemId,
itemId = tonumber(itemId), stackCount = count or 1,
stackCount = count or 1, }
}
end
end end
end end
return bagContents return bagContents
@@ -1582,16 +1573,13 @@ function API.GetBagItems(bagIndex)
if numSlots > 0 then if numSlots > 0 then
bags[bag] = {} bags[bag] = {}
for slot = 1, numSlots do for slot = 1, numSlots do
local link = GetContainerItemLink(bag, slot) local itemId = CleveRoids.ClassicAPI.GetContainerItemID(bag, slot)
if link then if itemId then
local _, _, itemId = string.find(link, "item:(%d+)")
local _, count = GetContainerItemInfo(bag, slot) local _, count = GetContainerItemInfo(bag, slot)
if itemId then bags[bag][slot] = {
bags[bag][slot] = { itemId = itemId,
itemId = tonumber(itemId), stackCount = count or 1,
stackCount = count or 1, }
}
end
end end
end end
end end
@@ -1609,16 +1597,13 @@ function API.GetBagItem(bagIndex, slot)
end end
-- Fallback: manual lookup -- Fallback: manual lookup
local link = GetContainerItemLink(bagIndex, slot) local itemId = CleveRoids.ClassicAPI.GetContainerItemID(bagIndex, slot)
if link then if itemId then
local _, _, itemId = string.find(link, "item:(%d+)")
local _, count = GetContainerItemInfo(bagIndex, slot) local _, count = GetContainerItemInfo(bagIndex, slot)
if itemId then return {
return { itemId = itemId,
itemId = tonumber(itemId), stackCount = count or 1,
stackCount = count or 1, }
}
end
end end
return nil return nil
@@ -1779,14 +1764,13 @@ function API.FindBagItem(itemIdOrName)
for bag = 0, 4 do for bag = 0, 4 do
local numSlots = GetContainerNumSlots(bag) or 0 local numSlots = GetContainerNumSlots(bag) or 0
for slot = 1, numSlots do for slot = 1, numSlots do
local link = GetContainerItemLink(bag, slot) if checkId then
if link then if CleveRoids.ClassicAPI.GetContainerItemID(bag, slot) == checkId then
if checkId then return bag, slot
local _, _, currentId = string.find(link, "item:(%d+)") end
if currentId and tonumber(currentId) == checkId then elseif checkName then
return bag, slot local link = GetContainerItemLink(bag, slot)
end if link then
elseif checkName then
local _, _, currentName = string.find(link, "|h%[(.-)%]|h") local _, _, currentName = string.find(link, "|h%[(.-)%]|h")
if currentName and string.lower(currentName) == checkName then if currentName and string.lower(currentName) == checkName then
return bag, slot return bag, slot
@@ -2103,26 +2087,28 @@ function API.GetTrinkets(copy)
for bag = 0, 4 do for bag = 0, 4 do
local numSlots = GetContainerNumSlots(bag) or 0 local numSlots = GetContainerNumSlots(bag) or 0
for slot = 1, numSlots do for slot = 1, numSlots do
local link = GetContainerItemLink(bag, slot) local numItemId = CleveRoids.ClassicAPI.GetContainerItemID(bag, slot)
if link then if numItemId then
local _, _, itemId = string.find(link, "item:(%d+)") local invType = API.GetItemInventoryType(numItemId)
if itemId then if invType == 12 then -- Trinket
local numItemId = tonumber(itemId) -- Only build the link string for actual trinkets, to read the name.
local invType = API.GetItemInventoryType(numItemId) local link = GetContainerItemLink(bag, slot)
if invType == 12 then -- Trinket local name
local _, _, name = string.find(link, "|h%[(.-)%]|h") if link then
local texture = GetContainerItemInfo(bag, slot) local _
local itemLevel = API.GetItemLevel(numItemId) _, _, name = string.find(link, "|h%[(.-)%]|h")
trinkets[index] = {
itemId = numItemId,
trinketName = name or "Unknown",
texture = texture,
itemLevel = itemLevel,
bagIndex = bag,
slotIndex = slot,
}
index = index + 1
end end
local texture = GetContainerItemInfo(bag, slot)
local itemLevel = API.GetItemLevel(numItemId)
trinkets[index] = {
itemId = numItemId,
trinketName = name or "Unknown",
texture = texture,
itemLevel = itemLevel,
bagIndex = bag,
slotIndex = slot,
}
index = index + 1
end end
end end
end end
@@ -2183,18 +2169,13 @@ function API.GetTrinketCooldown(slot)
end end
-- Get item ID from equipped slot -- Get item ID from equipped slot
local link = GetInventoryItemLink("player", equipSlot) local itemId = CleveRoids.ClassicAPI.GetInventoryItemID("player", equipSlot)
if not link then
return -1
end
local _, _, itemId = string.find(link, "item:(%d+)")
if not itemId then if not itemId then
return -1 return -1
end end
-- Get cooldown info -- Get cooldown info
return API.GetItemCooldownInfo(tonumber(itemId)) return API.GetItemCooldownInfo(itemId)
end end
-- Use an equipped trinket -- Use an equipped trinket
@@ -3550,117 +3531,5 @@ function API.GetUnitMaxPower(unitToken, powerType)
return UnitManaMax(unitToken) return UnitManaMax(unitToken)
end end
--------------------------------------------------------------------------------
-- RELIQUARY DBC FUNCTIONS (optional DLL)
--------------------------------------------------------------------------------
-- Safe Reliquary call wrapper — returns nil on missing DLL or lookup failure
local function RQ_SafeCall(func, ...)
if not func then return nil end
local ok, result = pcall(func, unpack(arg))
if ok then return result end
return nil
end
-- Get item set data from DBC by set ID
-- Returns: { name, itemId_1..17, setSpellId_1..8, setThreshold_1..8 } or nil
function API.GetItemSet(setId)
if not setId or not _G.RQ_GetItemSet then return nil end
return RQ_SafeCall(_G.RQ_GetItemSet, setId)
end
-- Get the set ID for an item (via Nampower's GetItemStatsField)
-- Returns: setId (number) or nil if item has no set
function API.GetItemSetId(itemId)
if not itemId then return nil end
local setId = API.GetItemField(itemId, "itemSet")
if setId and setId ~= 0 then return setId end
return nil
end
-- Get all item IDs belonging to a set (from Reliquary DBC)
-- Returns: { itemId1, itemId2, ... } or nil
function API.GetItemSetItems(setId)
local setData = API.GetItemSet(setId)
if not setData then return nil end
local items = {}
for i = 1, 17 do
local id = setData["itemId_" .. i]
if id then
id = tonumber(id)
if id and id ~= 0 then
table.insert(items, id)
end
end
end
if table.getn(items) > 0 then return items end
return nil
end
-- Get set bonus spell/threshold pairs from DBC
-- Returns: { { spellId = N, threshold = N }, ... } or nil
function API.GetItemSetBonuses(setId)
local setData = API.GetItemSet(setId)
if not setData then return nil end
local bonuses = {}
for i = 1, 8 do
local spellId = setData["setSpellId_" .. i]
local threshold = setData["setThreshold_" .. i]
if spellId and threshold then
spellId = tonumber(spellId)
threshold = tonumber(threshold)
if spellId and spellId ~= 0 and threshold and threshold > 0 then
table.insert(bonuses, { spellId = spellId, threshold = threshold })
end
end
end
if table.getn(bonuses) > 0 then return bonuses end
return nil
end
-- Get spell effect radius in yards from DBC
-- spellId: the spell to look up
-- effectIndex: 1, 2, or 3 (which effect slot, default 1)
-- Returns: radius (number) or nil
function API.GetSpellEffectRadius(spellId, effectIndex)
effectIndex = effectIndex or 1
if not spellId then return nil end
-- Get the radius index from the spell's effect via Nampower
local radiusField = "effectRadiusIndex"
local rec = API.GetSpellRecord(spellId)
if not rec then return nil end
-- effectRadiusIndex is an array field — access by effect index
local radiusIndex = nil
if rec.effectRadiusIndex then
if type(rec.effectRadiusIndex) == "table" then
radiusIndex = rec.effectRadiusIndex[effectIndex]
else
-- Single value (effect 1 only)
if effectIndex == 1 then
radiusIndex = rec.effectRadiusIndex
end
end
end
if not radiusIndex or radiusIndex == 0 then return nil end
-- Try Reliquary for the SpellRadius DBC lookup
if _G.RQ_GetSpellRadius then
local radiusData = RQ_SafeCall(_G.RQ_GetSpellRadius, radiusIndex)
if radiusData and radiusData.radius then
local radius = tonumber(radiusData.radius)
if radius and radius > 0 then return radius end
end
end
return nil
end
-- Expose API globally for other addons -- Expose API globally for other addons
_G.CleveRoidsNampowerAPI = API _G.CleveRoidsNampowerAPI = API
+50 -95
View File
@@ -6892,11 +6892,7 @@ CleveRoids.equipmentModifiers[9904] = { slot = 18, modifier = ripRakeIdolModifie
-- Function to get equipped item ID in a specific slot -- Function to get equipped item ID in a specific slot
function CleveRoids.GetEquippedItemID(slotID) function CleveRoids.GetEquippedItemID(slotID)
local itemLink = GetInventoryItemLink("player", slotID) return CleveRoids.ClassicAPI.GetInventoryItemID("player", slotID)
if not itemLink then return nil end
local _, _, itemID = string.find(itemLink, "item:(%d+)")
return tonumber(itemID)
end end
-- Apply equipment modifiers to a debuff duration -- Apply equipment modifiers to a debuff duration
@@ -7042,28 +7038,30 @@ end
-- Database of set bonus modifiers for debuff durations -- Database of set bonus modifiers for debuff durations
-- Structure: [spellID] = { items = {itemID1, itemID2, ...}, threshold = X, modifier = function(baseDuration) } -- Structure: [spellID] = { items = {itemID1, itemID2, ...}, threshold = X, modifier = function(baseDuration) }
-- When Reliquary is available, items can be omitted and setId used instead (auto-resolves from DBC) -- When a setId is given, items can be omitted and resolved from ItemSet.dbc
CleveRoids.setbonusModifiers = CleveRoids.setbonusModifiers or {} CleveRoids.setbonusModifiers = CleveRoids.setbonusModifiers or {}
-- Cache: setId -> { itemId1, itemId2, ... } (resolved from Reliquary or hardcoded) -- Cache: setId -> { itemId1, itemId2, ... } (resolved from ItemSet.dbc or hardcoded)
local setItemCache = {} local setItemCache = {}
-- Resolve set items: use Reliquary DBC if available, otherwise fall back to hardcoded list -- Resolve set items: use the ItemSet.dbc lookup when a setId is given, otherwise
-- fall back to the hardcoded list on the modifier.
local function ResolveSetItems(modifier) local function ResolveSetItems(modifier)
-- If items are already provided (hardcoded), use them directly -- If items are already provided (hardcoded), use them directly
if modifier.items and table.getn(modifier.items) > 0 then if modifier.items and table.getn(modifier.items) > 0 then
return modifier.items return modifier.items
end end
-- Try Reliquary DBC lookup by setId -- DBC lookup by setId via ClassicAPI
if modifier.setId and CleveRoids.NampowerAPI then if modifier.setId then
-- Check cache first -- Check cache first
if setItemCache[modifier.setId] then if setItemCache[modifier.setId] then
return setItemCache[modifier.setId] return setItemCache[modifier.setId]
end end
local items = CleveRoids.NampowerAPI.GetItemSetItems(modifier.setId) local info = CleveRoids.ClassicAPI.GetItemSetInfo(modifier.setId)
if items then local items = info and info.items
if items and table.getn(items) > 0 then
setItemCache[modifier.setId] = items setItemCache[modifier.setId] = items
return items return items
end end
@@ -7073,24 +7071,20 @@ local function ResolveSetItems(modifier)
end end
-- Function to count how many items from a set are currently equipped -- Function to count how many items from a set are currently equipped
-- Accepts either a direct items table or a modifier entry with setId for Reliquary lookup -- Accepts either a direct items table or a modifier entry with setId for DBC lookup
function CleveRoids.CountEquippedSetItems(items) function CleveRoids.CountEquippedSetItems(items)
if not items or type(items) ~= "table" then return 0 end if not items or type(items) ~= "table" then return 0 end
local count = 0 local count = 0
-- Check all equipment slots (1-19) -- Check all equipment slots (1-19)
for slot = 1, 19 do for slot = 1, 19 do
local itemLink = GetInventoryItemLink("player", slot) local itemID = CleveRoids.GetEquippedItemID(slot)
if itemLink then if itemID then
local _, _, itemID = string.find(itemLink, "item:(%d+)") -- Check if this item is in the set
if itemID then for _, setItemID in ipairs(items) do
itemID = tonumber(itemID) if itemID == setItemID then
-- Check if this item is in the set count = count + 1
for _, setItemID in ipairs(items) do break
if itemID == setItemID then
count = count + 1
break
end
end end
end end
end end
@@ -7099,40 +7093,19 @@ function CleveRoids.CountEquippedSetItems(items)
return count return count
end end
-- Count equipped set items by set ID (uses Nampower to check each slot's itemSet field) -- Count equipped set items by set ID, comparing each equipped slot's own set
-- Falls back to CountEquippedSetItems with Reliquary item list if GetItemStatsField unavailable -- membership (ClassicAPI GetItemSetIDByID) against the target set.
function CleveRoids.CountEquippedSetItemsBySetId(setId) function CleveRoids.CountEquippedSetItemsBySetId(setId)
if not setId then return 0 end if not setId then return 0 end
-- Fast path: use Nampower GetItemStatsField to check itemSet directly per slot local count = 0
if CleveRoids.NampowerAPI and CleveRoids.NampowerAPI.GetItemField then for slot = 1, 19 do
local count = 0 local itemID = CleveRoids.GetEquippedItemID(slot)
for slot = 1, 19 do if itemID and CleveRoids.ClassicAPI.GetItemSetIDByID(itemID) == setId then
local itemLink = GetInventoryItemLink("player", slot) count = count + 1
if itemLink then
local _, _, itemID = string.find(itemLink, "item:(%d+)")
if itemID then
local itemSetId = CleveRoids.NampowerAPI.GetItemSetId(tonumber(itemID))
if itemSetId == setId then
count = count + 1
end
end
end
end end
return count
end end
return count
-- Fallback: resolve set item list and count matches
local items = setItemCache[setId]
if not items and CleveRoids.NampowerAPI then
items = CleveRoids.NampowerAPI.GetItemSetItems(setId)
if items then setItemCache[setId] = items end
end
if items then
return CleveRoids.CountEquippedSetItems(items)
end
return 0
end end
-- Apply set bonus modifiers to a debuff duration -- Apply set bonus modifiers to a debuff duration
@@ -7183,7 +7156,7 @@ end
-- Helper function to register a set bonus modifier -- Helper function to register a set bonus modifier
-- Usage: CleveRoids.RegisterSetBonusModifier(spellID, itemsTable, threshold, modifierFunction) -- Usage: CleveRoids.RegisterSetBonusModifier(spellID, itemsTable, threshold, modifierFunction)
-- With Reliquary: CleveRoids.RegisterSetBonusModifier(spellID, nil, threshold, modifierFunction, setId) -- With a setId: CleveRoids.RegisterSetBonusModifier(spellID, nil, threshold, modifierFunction, setId)
function CleveRoids.RegisterSetBonusModifier(spellID, items, threshold, modifierFunc, setId) function CleveRoids.RegisterSetBonusModifier(spellID, items, threshold, modifierFunc, setId)
if not spellID or not threshold or not modifierFunc then if not spellID or not threshold or not modifierFunc then
return false return false
@@ -7202,17 +7175,17 @@ function CleveRoids.RegisterSetBonusModifier(spellID, items, threshold, modifier
return true return true
end end
-- Get info about an equipped item's set (combines Nampower + Reliquary) -- Get info about an equipped item's set (from ItemSet.dbc via ClassicAPI)
-- Returns: setName, setId, equippedCount, totalPieces, items or nil -- Returns: setName, setId, equippedCount, totalPieces, items or nil
function CleveRoids.GetEquippedItemSetInfo(itemId) function CleveRoids.GetEquippedItemSetInfo(itemId)
if not itemId or not CleveRoids.NampowerAPI then return nil end if not itemId then return nil end
local setId = CleveRoids.NampowerAPI.GetItemSetId(itemId) local setId = CleveRoids.ClassicAPI.GetItemSetIDByID(itemId)
if not setId then return nil end if not setId then return nil end
local setData = CleveRoids.NampowerAPI.GetItemSet(setId) local info = CleveRoids.ClassicAPI.GetItemSetInfo(setId)
local setName = setData and setData.name_enUS or nil local setName = info and info.name or nil
local items = CleveRoids.NampowerAPI.GetItemSetItems(setId) local items = info and info.items or nil
local totalPieces = items and table.getn(items) or 0 local totalPieces = items and table.getn(items) or 0
local equippedCount = CleveRoids.CountEquippedSetItemsBySetId(setId) local equippedCount = CleveRoids.CountEquippedSetItemsBySetId(setId)
@@ -7222,7 +7195,7 @@ end
-- Count equipped pieces of a named or ID-referenced item set -- Count equipped pieces of a named or ID-referenced item set
-- nameOrId: set name (string, e.g. "Judgement Battlegear") or set ID (number) -- nameOrId: set name (string, e.g. "Judgement Battlegear") or set ID (number)
-- Returns: equipped count (number), setId (number or nil) -- Returns: equipped count (number), setId (number or nil)
-- Name lookup requires Reliquary; ID lookup requires Nampower -- Both name and ID lookups resolve from ItemSet.dbc via ClassicAPI
function CleveRoids.GetEquippedSetPieceCount(nameOrId) function CleveRoids.GetEquippedSetPieceCount(nameOrId)
if not nameOrId then return 0, nil end if not nameOrId then return 0, nil end
@@ -7232,28 +7205,17 @@ function CleveRoids.GetEquippedSetPieceCount(nameOrId)
return CleveRoids.CountEquippedSetItemsBySetId(numericId), numericId return CleveRoids.CountEquippedSetItemsBySetId(numericId), numericId
end end
-- String: scan equipped items and match by set name from DBC -- String: scan equipped items and match by set name from ItemSet.dbc
if not CleveRoids.NampowerAPI or not CleveRoids.NampowerAPI.GetItemSetId then
return 0, nil
end
-- Scan equipped items to resolve set name → set ID, then count via fast path
local lowerName = string.lower(nameOrId) local lowerName = string.lower(nameOrId)
for slot = 1, 19 do for slot = 1, 19 do
local itemLink = GetInventoryItemLink("player", slot) local itemID = CleveRoids.GetEquippedItemID(slot)
if itemLink then if itemID then
local _, _, itemID = string.find(itemLink, "item:(%d+)") local setId = CleveRoids.ClassicAPI.GetItemSetIDByID(itemID)
if itemID then if setId then
local setId = CleveRoids.NampowerAPI.GetItemSetId(tonumber(itemID)) local info = CleveRoids.ClassicAPI.GetItemSetInfo(setId)
if setId then if info and info.name and string.lower(info.name) == lowerName then
local setData = CleveRoids.NampowerAPI.GetItemSet(setId) return CleveRoids.CountEquippedSetItemsBySetId(setId), setId
if setData then
local dbcName = setData.name_enUS
if dbcName and string.lower(dbcName) == lowerName then
return CleveRoids.CountEquippedSetItemsBySetId(setId), setId
end
end
end end
end end
end end
@@ -7262,18 +7224,9 @@ function CleveRoids.GetEquippedSetPieceCount(nameOrId)
return 0, nil return 0, nil
end end
-- Get spell effect radius in yards (Nampower + Reliquary)
-- spellId: the spell to look up
-- effectIndex: 1, 2, or 3 (which effect slot, default 1)
-- Returns: radius in yards or nil
function CleveRoids.GetSpellEffectRadius(spellId, effectIndex)
if not CleveRoids.NampowerAPI then return nil end
return CleveRoids.NampowerAPI.GetSpellEffectRadius(spellId, effectIndex)
end
-- DRUID set bonus modifiers -- DRUID set bonus modifiers
-- Dreamwalker Regalia (4/9): Increases Moonfire duration by 3 seconds and Insect Swarm by 2 seconds -- Dreamwalker Regalia (4/9): Increases Moonfire duration by 3 seconds and Insect Swarm by 2 seconds
-- setId 536 = Dreamwalker Regalia; hardcoded items as fallback when Reliquary unavailable -- setId 536 = Dreamwalker Regalia; hardcoded items as fallback when DBC lookup unavailable
local DREAMWALKER_SET_ID = 536 local DREAMWALKER_SET_ID = 536
local dreamwalkerItems = { 47372, 47373, 47374, 47375, 47376, 47377, 47378, 47379, 47380 } local dreamwalkerItems = { 47372, 47373, 47374, 47375, 47376, 47377, 47378, 47379, 47380 }
local dreamwalkerMoonfireModifier = function(base) return base + 3 end local dreamwalkerMoonfireModifier = function(base) return base + 3 end
@@ -7299,7 +7252,7 @@ CleveRoids.setbonusModifiers[24976] = { setId = DREAMWALKER_SET_ID, items = drea
CleveRoids.setbonusModifiers[24977] = { setId = DREAMWALKER_SET_ID, items = dreamwalkerItems, threshold = 4, modifier = dreamwalkerInsectSwarmModifier } -- Insect Swarm Rank 5 CleveRoids.setbonusModifiers[24977] = { setId = DREAMWALKER_SET_ID, items = dreamwalkerItems, threshold = 4, modifier = dreamwalkerInsectSwarmModifier } -- Insect Swarm Rank 5
-- Haruspex's Garb (3/5): Increases Faerie Fire duration by 5 seconds -- Haruspex's Garb (3/5): Increases Faerie Fire duration by 5 seconds
-- setId 474 = Haruspex's Garb; hardcoded items as fallback when Reliquary unavailable -- setId 474 = Haruspex's Garb; hardcoded items as fallback when DBC lookup unavailable
local HARUSPEX_SET_ID = 474 local HARUSPEX_SET_ID = 474
local haruspexItems = { 19613, 19955, 19840, 19839, 19838 } local haruspexItems = { 19613, 19955, 19840, 19839, 19838 }
local haruspexFaerieFireModifier = function(base) return base + 5 end local haruspexFaerieFireModifier = function(base) return base + 5 end
@@ -7810,7 +7763,7 @@ end
-- CC IMMUNITY TRACKING -- CC IMMUNITY TRACKING
-- Get CC type from a spell ID using the CCSpellMechanics table from Conditionals.lua -- Get CC type from a spell ID via DBC mechanic lookup (nampower, then ClassicAPI)
-- Returns: CC type name (e.g., "stun", "fear") or nil if not a CC spell -- Returns: CC type name (e.g., "stun", "fear") or nil if not a CC spell
-- EffectApplyAuraName → CC type mapping (fallback when mechanics are unset) -- EffectApplyAuraName → CC type mapping (fallback when mechanics are unset)
-- Uses vanilla 1.12.1 aura type enum values -- Uses vanilla 1.12.1 aura type enum values
@@ -7864,9 +7817,11 @@ local function GetSpellCCType(spellID)
end end
end end
-- Priority 2: Hardcoded table fallback (CCSpellMechanics in Conditionals.lua) -- Priority 2: ClassicAPI Spell.dbc reader (always present; covers every spell).
local mechanic = CleveRoids.CCSpellMechanics and CleveRoids.CCSpellMechanics[spellID] -- A subset of Priority 1's per-effect/aura checks, used when nampower's
if mechanic and MECHANIC_TO_CC_TYPE[mechanic] then -- GetSpellRecField is unavailable.
local mechanic = CleveRoids.ClassicAPI.GetSpellMechanicByID(spellID)
if mechanic and mechanic > 0 and MECHANIC_TO_CC_TYPE[mechanic] then
return MECHANIC_TO_CC_TYPE[mechanic] return MECHANIC_TO_CC_TYPE[mechanic]
end end