15 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
SuperCleveRoidMacros is a World of Warcraft 1.12.1 (Vanilla) addon that provides enhanced macro functionality with dynamic tooltips, conditional execution, and extended syntax. It requires three DLL mods: SuperWoW, Nampower, and UnitXP_SP3 - all are mandatory dependencies.
This addon is built for Turtle WoW (TWoW) private server and combines features from CleverMacro and Roid-Macros with significant extensions.
Critical Requirements
Required DLL Mods
The addon WILL NOT FUNCTION without all three DLL mods installed:
- SuperWoW (balakethelock) - Provides extended API functions like
SetAutoloot,SpellInfo(),UnitBuff/UnitDebuffwith spell IDs - Nampower - Provides
QueueSpellByName,IsSpellInRange,GetCurrentCastingInfo, and spell queueing - UnitXP_SP3 (konaka) - Provides
UnitXP()for distance/positioning checks
The addon checks for these on load in Core.lua:18-48 and will disable itself with error messages if any are missing.
Code Architecture
File Loading Order (SuperCleveRoidMacros.toc)
Files are loaded in this exact order, which is critical for initialization:
Localization.lua- Sets upCleveRoids.Localizedfor multi-language supportInit.lua- Initializes theCleveRoidsglobal table and environment flagsUtility.lua- Utility functions, string parsing, comparators, and the debuff tracking library (CleveRoids.libdebuff)Core.lua- Main addon logic, macro parsing, action evaluation, UI hooksConditionals.lua- Conditional keyword validation functions (CleveRoids.Keywords)Console.lua- Slash command handlersExtensionsManager.lua- Extension/plugin system for modular features- Compatibility layers for other addons (SuperMacro, pfUI, Bongos)
- Extension modules (MacroLengthWarn, Mouseover integrations, Tooltips)
Key Global Objects
CleveRoids - Main global namespace containing:
.playerClass- Player's class (set inConsole.lua).Spells,.Items,.Talents- Indexed lookups for spells/items/talents.Actions- Parsed macro data per action button.Sequences- Cast sequence state tracking.Keywords- Conditional validation function table (fromConditionals.lua).libdebuff- Debuff duration tracking system (SuperWoW-based).hasSuperwow,.hasNampower,.hasUnitXP- Feature detection flags.mouseoverUnit- Current mouseover unit (managed by Extensions)
CleveRoidMacros - SavedVariables configuration:
.realtime- 0 = event-based updates, 1 = continuous updates (default: 0).refresh- Update rate in Hz when realtime=1 (1-10, default: 5)
CleveRoids_LearnedDurations - SavedVariables for learned debuff durations (per-caster GUID)
CleveRoids_ImmunityData - SavedVariables for NPC immunity tracking (organized by damage school)
Core Systems
1. Conditional System (Conditionals.lua)
The CleveRoids.Keywords table maps conditional keywords to validation functions. Each function receives a conditionals table containing:
.target- The UnitID being evaluated (default: "target").help/.harm- Friendly/enemy flag.action- The spell/item name being cast- Additional conditional-specific values (e.g.,
.mod,.stance,.buff)
Multi-value conditionals (marked as "Multi" in README):
- Use
Or()helper - returns true if ANY value matches - Example:
[zone:Stormwind/Ironforge]→ true if in either zone
Negatable conditionals (marked as "Noable"):
- Use
And()helper - ALL must be false - Example:
[nozone:Stormwind/Ironforge]→ true only if in neither zone
Numeric comparisons (hp, power, cooldown, etc.):
- Use
CleveRoids.operatorsandCleveRoids.comparatorstables - Operators:
<,>,=,<=,>=,~=(and string aliases:lt,gt,eq, etc.) - Format in args table:
{operator = ">", amount = 50}
2. Debuff Timer System (Utility.lua:328-998)
The CleveRoids.libdebuff system provides accurate debuff tracking:
- Pre-configured durations for 329+ vanilla spells (see
lib.durations) - Auto-learning via
UNIT_CASTEVENT(cast start) andRAW_COMBATLOG(fade detection) - Per-caster GUID storage in
CleveRoids_LearnedDurations(handles talent variations) - GUID-based tracking (supports multiple mobs with same name)
- Fallback to static database for unknown spells
Key functions:
lib:GetDuration(spellID, casterGUID)- Returns learned or static durationlib:AddEffect(guid, unitName, spellID, duration, stacks, caster)- Track new debufflib:UnitDebuff(unit, id)- Returns: name, _, texture, stacks, dtype, duration, timeleft, caster
3. Immunity Tracking System (Utility.lua:1000-1380)
The immunity tracking system automatically learns and tracks NPC immunities from combat log messages:
- Auto-learning from combat log: "X's Spell fails. Y is immune."
- Stores immunities by damage school (fire, frost, nature, shadow, arcane, holy, physical) in
CleveRoids_ImmunityData - Supports both permanent immunities and buff-based immunities (e.g., boss immune during a shield phase)
- Automatic spell school detection via tooltip scanning and name pattern matching
Data Structure:
CleveRoids_ImmunityData = {
fire = {
["Ragnaros"] = true, -- Permanent immunity
["Vaelastrasz the Corrupt"] = { buff = "Burning Adrenaline" } -- Conditional immunity
},
frost = {
["Frozen Core"] = true
}
}
Key Functions:
CleveRoids.CheckImmunity(unitId, spellOrSchool)- Check immunity to spell name OR damage school- Example:
CheckImmunity("target", "Flame Shock")orCheckImmunity("target", "fire") - Automatically detects buff-based immunity by checking target's current buffs
- Example:
CleveRoids.ListImmunities(school)- List immunity data (all or specific school)CleveRoids.AddImmunity(npcName, school, buffName)- Manually add immunityCleveRoids.RemoveImmunity(npcName, school)- Remove immunity entryCleveRoids.ClearImmunities(school)- Clear immunity data
Combat Log Parsing:
- Listens to
RAW_COMBATLOGevent for immunity messages - Extracts spell name and target name from messages
- If target has exactly one buff when immunity occurs, assumes buff causes immunity
- Otherwise records as permanent immunity
Console Commands:
/cleveroid listimmune [school] # List all or specific school immunities
/cleveroid addimmune "<NPC>" <school> [buff] # Add manual immunity
/cleveroid removeimmune "<NPC>" <school> # Remove immunity
/cleveroid clearimmune [school] # Clear data
Conditional Usage:
[immune:fire]or[immune:Flame Shock]- Check if target is immune[noimmune:nature]or[noimmune:"Serpent Sting"]- Check if NOT immune- Can omit spell/school to check the action being cast:
[noimmune] Fireball
4. Macro Parsing and Execution
Macros are parsed in Core.lua into action lists. Each action has:
.cmd- Command (e.g., "/cast", "/use", "/castsequence").args- Arguments string.conditionals- Parsed conditional table.sequence- Cast sequence data (if/castsequence)
Evaluation flow:
CleveRoids.TestForActiveAction(actions)iterates action list- For each action,
CleveRoids.TestAction(cmd, args)evaluates conditionals - First passing action becomes
.activeand determines icon/tooltip #showtooltipat macro start enables dynamic icon/tooltip updates
5. Equipment Swapping System (Core.lua:57-227)
Implements queued equipment changes with cooldowns:
- Per-slot cooldown: 1.5s (
EQUIP_COOLDOWN) - Global cooldown: 0.5s (
EQUIP_GLOBAL_COOLDOWN) - Combat weapon swap protection (checks casting state, on-swing spells)
CleveRoids.QueueEquipItem(item, slotName)- Queue swapCleveRoids.ProcessEquipmentQueue()- Process queue (called from OnUpdate)
6. Extension System (ExtensionsManager.lua)
Modular plugin architecture for addon integrations:
CleveRoids.RegisterExtension(name)creates extension object- Extensions can register events, hook functions/methods
- Mouseover extensions set
CleveRoids.SetMouseoverFrom(source, unit)with priority system (pfUI > blizz > tooltip) - Compatibility extensions handle SuperMacro, pfUI MacroTweak, Bongos action bars
Common Development Tasks
Adding a New Conditional Keyword
- Add validation function to
Conditionals.lua:
CleveRoids.Keywords = {
-- Existing conditionals...
mynewconditional = function(conditionals)
-- Access parsed values from conditionals table
local checkValue = conditionals.mynewconditional
-- For multi-value support, use Or() helper:
return Or(checkValue, function(val)
return YourCheckFunction(val)
end)
end,
nomynewconditional = function(conditionals)
-- Negated version uses And() helper:
return And(conditionals.nomynewconditional, function(val)
return not YourCheckFunction(val)
end)
end,
}
- Update README.md with syntax, examples, and whether it's Multi/Noable
Adding Support for a New Spell Duration
- Add to static database in
Utility.lua:
lib.durations = lib.durations or {
-- Existing durations...
[12345] = 30, -- Spell Name (Rank X) - duration in seconds
}
- Or let players learn it manually:
/cleveroid learn 12345 30
The system will auto-learn durations as players cast spells if not in database.
Modifying Mouseover Behavior
Mouseover unit determination uses a priority system in Utility.lua:94-145:
- Priority levels: pfUI (3), blizzard (3), tooltip (1)
- Extensions call
CleveRoids.SetMouseoverFrom(source, unit)to set mouseover - Highest priority source wins
CleveRoids.ClearMouseoverFrom(source, unitIfMatch)to remove
To add new source:
- Create extension in
Extensions/Mouseover/YourAddon.lua - Hook the addon's frame OnEnter/OnLeave scripts
- Call
SetMouseoverFrom("youraddon", unitID)with appropriate priority
Testing Conditionals
Use /dump command to inspect values:
/script DEFAULT_CHAT_FRAME:AddMessage(tostring(CleveRoids.ValidateHp("target", "<=", 50)))
Check CleveRoids.Keywords table for function existence:
/script DEFAULT_CHAT_FRAME:AddMessage(tostring(CleveRoids.Keywords.myconditional ~= nil))
Important Implementation Details
String Parsing and Quotation Handling
- Spell/item names with spaces can use underscores OR quotes:
[buff:Mark_of_the_Wild]or[buff:"Mark of the Wild"] - The parser in
Core.luausesCleveRoids.splitStringIgnoringQuotes()to handle quoted strings - Rank syntax MUST include parentheses:
Faerie Fire (Feral)(Rank 4)(not justFaerie Fire (Feral))
Macro Icon/Tooltip Updates
- Icons update via
CleveRoids.QueueActionUpdate()which setsisActionUpdateQueued = true - OnUpdate handler processes queue and calls
ActionButton_Update()on affected buttons - If
realtime=0(default), updates only on events (ACTIONBAR_UPDATE, UNIT_AURA, etc.) - If
realtime=1, updates continuously atrefreshrate (CPU intensive)
Spell Cooldown Handling
CleveRoids.GetSpellCooldown(spellName, ignoreGCD)returns absolute expiry timeignoreGCD=truetreats 1.5s cooldowns as "not on cooldown" (GCD)- Item cooldowns are separate:
CleveRoids.GetItemCooldown(item)returns remaining seconds
Cast Sequence Reset Logic
Cast sequences reset on:
reset=X- X seconds of inactivityreset=target- Target changereset=combat- Leaving combatreset=mod- Modifier key press- Can combine:
reset=3/target/combat
State tracked in CleveRoids.Sequences by macro slot.
File Structure Patterns
Adding New Compatibility Layer
Create Compatibility/YourAddon.lua:
local _G = _G or getfenv(0)
local CleveRoids = _G.CleveRoids or {}
if not YourAddon then return end -- Check if addon exists
-- Your compatibility code here
-- Usually hooks or event handlers to prevent conflicts
_G["CleveRoids"] = CleveRoids
Add to .toc file in Compatibility section.
Adding New Extension
Create Extensions/YourExtension.lua:
local extension = CleveRoids.RegisterExtension("YourExtension")
extension.OnLoad = function()
-- Initialization code
extension.RegisterEvent("SOME_EVENT", "OnSomeEvent")
end
extension.OnSomeEvent = function()
-- Event handler using 'event', 'arg1', etc. globals
end
return extension
Add to .toc file in Extensions section.
Performance Considerations
- Avoid
realtime=1unless necessary - Event-based updates (realtime=0) are significantly more efficient - Debuff table cleanup - Runs on target change, throttled to 2s intervals (see
Utility.lua:948) - Spell/item indexing - Only rebuilt on SPELLS_CHANGED, LEARNED_SPELL_IN_TAB events
- Reactive spell detection - Requires abilities on action bars to detect usability (limitation may be removed with Nampower enhancements)
Console Commands
Defined in Console.lua:
# View/modify settings
/cleveroid # Show current settings
/cleveroid realtime 0|1 # Toggle realtime updates
/cleveroid refresh 1-10 # Set update rate (Hz)
# Debuff duration learning
/cleveroid learn <spellID> <dur> # Manually set duration (seconds)
/cleveroid forget <spellID|all> # Forget learned duration(s)
/cleveroid debug 0|1 # Toggle learning debug messages
Debugging Tips
-
Enable debug mode for debuff learning:
/cleveroid debug 1Shows learned durations in chat as debuffs fade.
-
Check for missing dependencies: Look for error messages on login mentioning SuperWoW/Nampower/UnitXP.
-
Macro syntax errors:
- Check for unmatched quotes or brackets
- Verify spell/item names are spelled correctly (case-sensitive)
- Use
#showtooltipto see which action is evaluating as active
-
Icon not updating:
- Ensure macro starts with
#showtooltip - Check if
realtime=0and conditional needs event trigger - Verify action bar addon compatibility (see Extensions)
- Ensure macro starts with
Localization
The Localization.lua file provides CleveRoids.Localized table with:
.Spells- Localized spell names (keyed by English name).CreatureTypes- Creature type translations.Dagger,.Sword,.Shield, etc. - Weapon type names
Always use CleveRoids.Localized.Spells["EnglishName"] for hardcoded spell references to support non-English clients.
Known Limitations
- Reactive abilities (Revenge, Overpower, etc.) must be on action bars for detection (workaround may be possible with Nampower)
- Aquatic Form detection uses reactive system (must be on non-stance action bar)
- Debuff time-left conditionals only work on player's own debuffs unless pfUI or internal libdebuff has data
- Macro names must be unique - no blank names, duplicates, or using spell names
- Parenthesis in spell names (e.g., "Faerie Fire (Feral)") MUST include rank: "Faerie Fire (Feral)(Rank X)"