From 9811d9c89425eef15e629f8ba6d6433287b341ec Mon Sep 17 00:00:00 2001 From: Jrc13245 Date: Sun, 22 Feb 2026 20:00:21 -0500 Subject: [PATCH] update for nampower 2_41_0 and update readme --- Conditionals.lua | 31 ++++++++++++++++++++++++++++++ Core.lua | 49 ++++++++++++++++++++++++++++++++++++------------ Init.lua | 3 +++ NampowerAPI.lua | 24 +++++++++++++++++++++++- README.md | 22 +++++++++++++++++++++- Utility.lua | 21 +++++++++++++++++++++ 6 files changed, 136 insertions(+), 14 deletions(-) diff --git a/Conditionals.lua b/Conditionals.lua index 9ab48a3..69bce17 100644 --- a/Conditionals.lua +++ b/Conditionals.lua @@ -5099,6 +5099,36 @@ CleveRoids.Keywords = { end, conditionals, "nomod") end, + -- [keydown:X] — true while key X is held (Nampower v2.41+ KEY_DOWN/KEY_UP events) + -- [keydown] with no argument — true if any non-meta key is currently held + keydown = function(conditionals) + if type(conditionals.keydown) ~= "table" then + for _, v in pairs(CleveRoids._keyState) do + if v then return true end + end + return false + end + return Multi(conditionals.keydown, function(keyname) + local code = CleveRoids.KEY_NAMES[string.lower(keyname)] + if not code then return false end + return CleveRoids._keyState[code] == true + end, conditionals, "keydown") + end, + + nokeydown = function(conditionals) + if type(conditionals.nokeydown) ~= "table" then + for _, v in pairs(CleveRoids._keyState) do + if v then return false end + end + return true + end + return NegatedMulti(conditionals.nokeydown, function(keyname) + local code = CleveRoids.KEY_NAMES[string.lower(keyname)] + if not code then return true end + return not (CleveRoids._keyState[code] == true) + end, conditionals, "nokeydown") + end, + target = function(conditionals) return CleveRoids.IsValidTarget(conditionals.target, conditionals.help) end, @@ -7874,6 +7904,7 @@ CleveRoids.STATIC_CONDITIONALS = { form = true, noform = true, stance = true, nostance = true, equipped = true, noequipped = true, mod = true, nomod = true, + keydown = true, nokeydown = true, swimming = true, noswimming = true, resting = true, noresting = true, } diff --git a/Core.lua b/Core.lua index 82a0dee..6d01ab0 100644 --- a/Core.lua +++ b/Core.lua @@ -4045,19 +4045,22 @@ function CleveRoids.OnUpdate(self) end -- PERFORMANCE: Check for modifier key state changes (no events for these in vanilla WoW) -- Only queue update if modifier state actually changed - avoids full TestForAllActiveActions - local altDown = IsAltKeyDown() and true or false - local shiftDown = IsShiftKeyDown() and true or false - local ctrlDown = IsControlKeyDown() and true or false + -- Nampower v2.41+ fires KEY_DOWN/KEY_UP for all keys including modifiers, so skip polling + if not CleveRoids.NampowerAPI.features.hasKeyEvents then + local altDown = IsAltKeyDown() and true or false + local shiftDown = IsShiftKeyDown() and true or false + local ctrlDown = IsControlKeyDown() and true or false - if altDown ~= CleveRoids._lastAltDown or - shiftDown ~= CleveRoids._lastShiftDown or - ctrlDown ~= CleveRoids._lastCtrlDown then - CleveRoids._lastAltDown = altDown - CleveRoids._lastShiftDown = shiftDown - CleveRoids._lastCtrlDown = ctrlDown - -- Modifier changed - queue update in event-driven mode, or just mark for realtime - if CleveRoidMacros.realtime == 0 then - CleveRoids.isActionUpdateQueued = true + if altDown ~= CleveRoids._lastAltDown or + shiftDown ~= CleveRoids._lastShiftDown or + ctrlDown ~= CleveRoids._lastCtrlDown then + CleveRoids._lastAltDown = altDown + CleveRoids._lastShiftDown = shiftDown + CleveRoids._lastCtrlDown = ctrlDown + -- Modifier changed - queue update in event-driven mode, or just mark for realtime + if CleveRoidMacros.realtime == 0 then + CleveRoids.isActionUpdateQueued = true + end end end @@ -4925,6 +4928,11 @@ if GetCurrentCastingInfo then CleveRoids.Frame:RegisterEvent("SPELL_CAST_EVENT") end +-- Nampower v2.41+: keyboard input events for [keydown:X] conditional +if CleveRoids.NampowerAPI.features.hasKeyEvents then + CleveRoids.Frame:RegisterEvent("KEY_DOWN") + CleveRoids.Frame:RegisterEvent("KEY_UP") +end -- NOTE: SuperMacro hook installation is handled by Compatibility/SuperMacro.lua -- which has the complete implementation including the INTERCEPT path for all commands @@ -5806,6 +5814,23 @@ function CleveRoids.Frame:SPELL_CAST_EVENT() end +-- Nampower v2.41+: KEY_DOWN/KEY_UP events +-- arg1=keyCode (int), arg2=metaKeyState (Shift=1,Ctrl=2,Alt=4), arg3=repeat, arg4=time +-- Meta key codes (0=Shift, 1=Ctrl, 2=Alt) are skipped — they are already tracked via IsXKeyDown() +function CleveRoids.Frame:KEY_DOWN() + local keyCode = arg1 + if keyCode == 0 or keyCode == 1 or keyCode == 2 then return end + CleveRoids._keyState[keyCode] = true + CleveRoids.isActionUpdateQueued = true +end + +function CleveRoids.Frame:KEY_UP() + local keyCode = arg1 + if keyCode == 0 or keyCode == 1 or keyCode == 2 then return end + CleveRoids._keyState[keyCode] = nil + CleveRoids.isActionUpdateQueued = true +end + CleveRoids.Hooks.SendChatMessage = SendChatMessage function SendChatMessage(msg, ...) -- Filter out #showtooltip lines diff --git a/Init.lua b/Init.lua index bf62857..b0471e1 100644 --- a/Init.lua +++ b/Init.lua @@ -53,6 +53,9 @@ CleveRoids.lastComboPointsTime = 0 -- Structure: { resistType = "full"|"partial", targetGUID = guid } CleveRoids.resistState = nil +-- KEY_DOWN/KEY_UP state table (populated when Nampower v2.41+ hasKeyEvents) +CleveRoids._keyState = {} + -- Holds information about the currently cast spell CleveRoids.CurrentSpell = { -- "channeled" or "cast" diff --git a/NampowerAPI.lua b/NampowerAPI.lua index 38b2786..543e419 100644 --- a/NampowerAPI.lua +++ b/NampowerAPI.lua @@ -143,7 +143,21 @@ - Fixed packed GUID parsing bug that caused target to appear as "0x000000000" for some player GUIDs. - Current version: v2.40.0 + Keyboard Events & Extended Unit Token Support (v2.41+): + - KEY_DOWN / KEY_UP events: fire when keyboard keys are pressed and released. + Any addon can register for these to react to key input without frame scripts. + - Internal unit token resolver extended: all Nampower functions that accept a + unit string (SetMouseoverUnit, UseItemIdOrName, CastSpellByName, etc.) now + support additional formats beyond standard tokens and GUIDs: + mark1..mark8 - resolve to the unit bearing that raid marker + owner - owner of (e.g. "targetowner" = target's owner) + target - target of (e.g. "mouseovertarget") + pet - pet of (e.g. "party1pet") + can be a standard token, a GUID string, or a mark token. + Suffix matching is case-insensitive. + Note: GetGUIDFromName is an internal C++ helper, NOT a new Lua global. + + Current version: v2.41.0 ]] local _G = _G or getfenv(0) @@ -334,6 +348,10 @@ API.VERSION_REQUIREMENTS = { ["SpellStartCorpseParam"] = { 2, 40, 0 }, -- arg9=corpseOwnerGuid added to SPELL_START events ["SpellGoCorpseParam"] = { 2, 40, 0 }, -- arg8=corpseOwnerGuid added to SPELL_GO events ["PackedGuidFix"] = { 2, 40, 0 }, -- Fix for packed GUID parsing (target showed as 0x000000000) + + -- v2.41+ - Keyboard events and extended unit token support + ["KeyEvents"] = { 2, 41, 0 }, -- KEY_DOWN / KEY_UP events (keyboard input events) + ["ExtendedUnitTokens"] = { 2, 41, 0 }, -- Internal unit token resolution now supports "owner"/"target"/"pet"/"mark" in all Nampower functions (SetMouseoverUnit, UseItemIdOrName, etc.) } -- Check if a specific feature is available @@ -508,6 +526,10 @@ local function InitializeFeatures() f.hasSpellGoCorpseParam = API.HasFeature("SpellGoCorpseParam") f.hasPackedGuidFix = API.HasFeature("PackedGuidFix") + -- v2.41+ Keyboard events and extended unit token support + f.hasKeyEvents = API.HasFeature("KeyEvents") + f.hasExtendedUnitTokens = API.HasFeature("ExtendedUnitTokens") + -- Runtime detection for enhanced spell functions (verify by testing) if f.hasEnhancedSpellFunctions and GetSpellTexture then local success, result = pcall(function() diff --git a/README.md b/README.md index 304d8f4..c8fb67a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Enhanced macro addon for World of Warcraft 1.12.1 (Vanilla/Turtle WoW) with dyna - **Conditionals** in `[]` brackets, space or comma separated - **Arguments** use colon: `[mod:alt]`, `[hp:>50]` - **Negation** with `no` prefix: `[nobuff]`, `[nomod:alt]` -- **Target** with `@`: `[@mouseover,help]`, `[@party1,hp:<50]` +- **Target** with `@`: `[@mouseover,help]`, `[@party1,hp:<50]`, `[@targetowner,help]` (v2.41+) - **Spell names** with spaces: `"Mark of the Wild"` or `Mark_of_the_Wild` ### Multi-Value Logic @@ -171,6 +171,7 @@ These always evaluate against the player. Cannot be redirected with `@unit`. | `known` | Spell/talent known (with rank) | ✅ | ✅ | `[known:Berserk]` `[known:Frostbolt>#2]` | | | | `lastswing` | Player melee swing type/timing | ✅ | ✅ | `[lastswing:dodge]` `[lastswing:<2]` | v2.24 | | | `mhimbue` | Main hand has temporary imbue | ✅ | ✅ | `[mhimbue:Instant_Poison<300]` `[mhimbue:>#5]` | | | +| `keydown` | Key is currently held down | ✅ | ✅ | `[keydown:f]` `[keydown:space/enter]` | v2.41 | | | `mod` | Modifier key pressed | ✅ | ✅ | `[mod:alt/ctrl]` | | | | `moving` | Moving / speed % | ✅ | ✅ | `[moving]` `[moving:>100&<200]` | | MonkeySpeed (speed %) | | `mybuff` | Player has buff (with time/stacks) | ✅ | ✅ | `[mybuff:Thorns<5]` `[nomybuff:MotW/GotW]` | | | @@ -259,6 +260,25 @@ These default to checking the current target. Most can be redirected with `@unit | `ttk` | Time to kill target (seconds) | ✅ | ✅ | `[ttk:<10]` | | TimeToKill | | `type` | Creature type | ✅ | ✅ | `[type:Undead/Beast]` | | | +### Extended Unit Tokens (Nampower v2.41+) + +With Nampower v2.41+, all `[@unit]` redirects support additional token formats beyond standard tokens: + +| Token format | Resolves to | Example | +|---|---|---| +| `mark1`–`mark8` | Unit bearing that raid marker | `[@mark1,harm]` | +| `owner` | Owner/summoner of `` | `[@targetowner,help]` — cast on target's owner | +| `target` | Target of `` | `[@mouseovertarget,hp:<30]` | +| `pet` | Pet of `` | `[@party1pet,exists]` | + +`` can be any standard token (`target`, `mouseover`, `party1`–`party4`, `raid1`–`raid40`…), a GUID string, or a mark token (`mark1`–`mark8`). Suffix matching is case-insensitive. + +```lua +/cast [@targetowner,help] Rejuvenation -- Heal the owner of your target (e.g. a pet) +/cast [@mark1target,harm] Polymorph -- Cast on whatever the skull-marked unit is targeting +/cast [@party1pet,exists] Mend Pet -- Heal party1's pet if it exists +``` + ### Multi-Unit Count Mode Range and position conditionals (`meleerange`, `behind`, `insight`, `inrange`, `outrange`) support counting enemies when given an operator + number. Requires UnitXP_SP3. Operators: `>`, `<`, `>=`, `<=`, `=`, `~=` diff --git a/Utility.lua b/Utility.lua index 65a03a6..af5dde8 100644 --- a/Utility.lua +++ b/Utility.lua @@ -587,6 +587,27 @@ CleveRoids.kmods = { nomod = function() return (not IsControlKeyDown() and not IsAltKeyDown() and not IsShiftKeyDown()) end, } +-- Key code lookup table for [keydown:X] conditional (Nampower v2.41+) +-- Maps lowercase name -> integer key code from the Nampower KEY_DOWN/KEY_UP enum +CleveRoids.KEY_NAMES = { + -- Printable ASCII + space=32, + ["0"]=48,["1"]=49,["2"]=50,["3"]=51,["4"]=52, + ["5"]=53,["6"]=54,["7"]=55,["8"]=56,["9"]=57, + a=65,b=66,c=67,d=68,e=69,f=70,g=71,h=72,i=73,j=74,k=75,l=76, + m=77,n=78,o=79,p=80,q=81,r=82,s=83,t=84,u=85,v=86,w=87,x=88,y=89,z=90, + -- Special + tilde=256, + -- Numpad + numpad0=257,numpad1=258,numpad2=259,numpad3=260,numpad4=261, + numpad5=262,numpad6=263,numpad7=264,numpad8=265,numpad9=266, + -- Control keys + escape=512,enter=513, + -- Function keys + f1=768,f2=769,f3=770,f4=771,f5=772,f6=773, + f7=774,f8=775,f9=776,f10=777,f11=778,f12=779, +} + CleveRoids.operators = { ["<"] = "lt", ["lt"] = "<",