Sku v43.9 - patch notes

Overview

New

Changes

Bugfixes

Quest menu: "Route" finds creatures with a hyphen in their name

Simple: In the quest menu (Quest start, Quest target, Delivery) a creature offers "Route", "Close route" and "Waypoint". "Route" said "list empty" whenever the creature's name contained a hyphen, a bracket or a similar character, even when the creature is well connected to the route network. On German clients that was 249 creatures, among them all three ape kinds in Un'Goro Crater. "Close route" and "Waypoint" were not affected.

Technically: SkuQuest/Options.lua, CreateRtWpSubmenu, "Route" branch: string.find(i, wpName) without the plain argument read the waypoint name as a Lua pattern. There "-" is a quantifier ("o-" = any number of o), so the name never found itself. Now string.find(i, wpName, 1, true) at both call sites. The route data in the crater was fine (checked: links, spawn indices and connection to the route network).

Close route: the ten nearest linked waypoints are really found

Simple: Most creatures are not linked to the route network themselves. For "Close route" Sku therefore looks for up to ten linked waypoints within 500 yards of the target and takes the best reachable one. That search often returned fewer than ten. The nearest waypoint was always among them, though, and the route network is connected almost everywhere. This most probably never affected anyone; the fix is there for correctness only. The bug could only have shown when the nearest waypoint lies on a detached piece of the network: then "list empty" or a small detour.

Technically: SkuNav:GetNearestWpsWithLinksToWp (SkuNav/Core.lua). The sorted insert had no append case: a candidate farther away than every entry was dropped although the list still had room, so the first hit of pairs() set the ceiling. The trim above N entries always removed the farthest one and stays. Checked offline against "the N nearest" (20000 random cases): old 9059 too short, new all correct. All five callers evaluate the whole list and take the best reachable entry, so more candidates can only give equally good or better routes.

Auras: basic auras get the full output list

Simple: Under "New aura", "Basic auras" every template had a "Sound" entry where you could pick exactly one sound and nothing else. That entry is now called "Output", followed by the number of outputs switched on, and it opens the same list a custom aura has: every sound and every data output, for example spell name or target unit. Each entry is a switch, Enter turns it on or off, and several may be on at once. What the template used to set (its sound, plus spell name and target unit for "Your buff on a group member expired") is already switched on when the form opens, and can now be switched off too.

Technically: SkuAuras/Options.lua. tBuildOutputsLevel takes an optional context (outputs, ownerLabel, tooltip); without it the list edits the aura builder's draft as before, with it the basic-aura form's list. The form (tBaseForm) holds a list outputs instead of a single sound value, seeded from defaultSound and defaultOutputs (formerly fixedOutputs, which were appended unconditionally on create). The summary and tBaseFormCommit read that list; with no output on it still says "No output set".

Auras: "Delete all auras" asks first

Simple: "Delete all auras" in the Auras menu had no level below it: one Enter or Right arrow and every aura of the character was gone. Now the entry leads to "Really delete?", like deleting a single aura. Only Enter there deletes, Left arrow backs out.

Technically: SkuAuras/Options.lua, MenuBuilder: the entry is now dynamic and its BuildChildren injects the single child "Really delete?". On entering, selectTarget points at the entry itself, so Enter on the child calls its OnAction. Before it was dynamic = false with no children, so OnPostSelect went straight to the OnAction branch.

Menu: paths are resolved instead of walked

Simple: Whenever Sku itself puts the menu at a certain place (a window opens, a quick key like Shift-F10, or a window changed and its menu is rebuilt), it used to walk the path there as if Enter were pressed on every level, announcing every stop on the way. During the quiet rebuild of a profession or trainer window after a craft or a learn you therefore heard the window name ("Trade skill", "Class Trainer"), and the cursor was restored by row number into a list that had just changed. Now the target path is resolved directly, without announcing the stops, and the cursor returns to the same entry: the same recipe (even with a new count), the same skill, the same button. Only when that entry is gone is the place the cursor landed announced.

Technically: SkuOptions:ResolveMenuPath and EnsureLevelBuilt (SkuZOptions/Core.lua) replace the loop in SlashFunc that called OnSelect(true) on every path segment. Levels on the way are only built (dynamic: RebuildNodeChildren, otherwise one BuildChildren when empty), never selected; only the destination gets its OnSelect as before (pre-build of an empty, non-dynamic level, never on isSkuToggle). The side effects of the walk are gone with it: actionOnEnter nodes along the path fired, every sibling before the match was pre-built. SlashFunc's aSilent parameter is effective now. The restore in SkuCore:CheckFrames makes one silent call instead of two speaking ones and sets the cursor directly: skuIdentity, then name, then the row at the old index (clamped to the new length). Window entries carry skuIdentity (copied by SkuIterateGossipList): recipes "recipe:Name (rank)", categories "cat:", trainer skills "skill:", otherwise "frame:<frame>" for every entry that is alone on its frame (SkuCore:PrepareWindowEntries at the end of the three builders). SkuCore:RefreshWindowMenuQuietly (LocalMenu.lua) is the shared quiet rebuild for TRADE_SKILL_UPDATE/CRAFT_UPDATE and the Train button; it speaks only when the identity (or the count-stripped name) is a different one afterwards. The bags keep their own path (tFindMenuNodeByPath, tBagAnnounceSuppress).

Profession windows: Enter on a recipe or "Create" announced the entry twice

Simple: After Enter on a recipe or a Create button the entry was spoken twice. Now once.

Technically: The classic click path in SkuIterateGossipList called a speaking CheckFrames after func and OnUpdate 0.35 s later, on top of the key handler's own announce. The third announce was usually caught by the duplicate guard (1 s), the second one came 0.9 s later and was not. Entries with quietClick (set by PrepareWindowEntries for every click button without containerFrameName) now run func plus RefreshWindowMenuQuietly; buttons with a secure /click keep the old path.

Mailbox: "Target" before "New mail"

Simple: On opening a mailbox, "Target" was announced first and only then "New mail". Now only "New mail".

Technically: Mail:MAIL_SHOW opened the path "Local, Mail" before the MailFrame was visible, but the mail entry under Local exists only while its frame is visible. The path found nothing, and the silent open announced the first root entry instead ("Target", the target menu); the bags pulled the menu into the mail a moment later via CheckFrames. The debug log showed "path walk found nothing ... short,lokal,post" on every mailbox since at least v43.6; it was only noticed once the intermediate announcements were gone. Now MAIL_SHOW opens one frame later (C_Timer.After(0)), only with a visible MailFrame and only if the cursor is not already in the mail branch.

Key bindings: second key for monitor, scan, turn and friends

Simple: Under "Sku key bindings" every key has a first and a second binding. For a number of keys the second one could be set and was announced as "Key 2", but did nothing. Affected were "Trigger monitor party continuous output", target distance, panic mode, minimap scan wide and narrow, group member range check, "Turn to unit" 1 to 6 and 180 degrees, "Scan continue", scan 1 to 8 and the resource notification. The second key now works everywhere. The monitor key's English name also loses the typo "continous".

Technically: SkuCore/Core.lua, OnHide script of SkuCoreControlOption1: the bindings owned by this frame were armed with SetOverrideBindingClick for .key only (SKU_KEY_TAXICANCEL was the lone exception), while the click dispatcher checks both fields through SkuKeyBindsMatchKey. The binding menus in SkuZOptions/Core.lua have always armed key2, which is why the second key worked for other actions. A local tArm(aConst) helper now binds every key SkuKeyBindsGetKeys returns; the twenty hand-written single lines are gone.

Monitor combat: the death announcement names the numpad key

Simple: Under Monitor, Combat, Friendly, "Announce deaths" announces a dead group member. The number in it is now always the key that targets that member. In a party those are Sku's default keys: numpad 1 = self, 2 to 5 = the four others. The fourth party member is therefore now "party 5, dead", no longer "party 4". The health monitor and the overview have always counted this way. In a raid the dial-targeting number is spoken: the single key up to 10 players, the two-digit sequence from 11 on. It used to say "party 2" for members of your own subgroup and "raid 17" (the raw raid slot) for everyone else, two numberings in one fight, neither matching the numpad. Raid slots 26 to 40 were not announced at all. "Count deaths up" is removed: in "number only" mode its "3, dead" could not be told from "party 3, dead", and the counter never went down on a resurrection.

Technically: SkuCore/aqCombat.lua, aqCombat_SKU_UNIT_DIED. New helper tDeathUnitToken(GUID) returns the spoken token and the real unit id separately, the UnitIsDeadOrGhost and pet checks need the raw slot. Party: token from aqCombatGroupGuidToUnitId, digit plus 1. Raid: all MAX_RAID_MEMBERS slots scanned by GUID (the 25 in tAllPartyRaidUnits were not enough), number read from the dial-targeting grid (SkuSecureTargetingFrame, unitNameSlotGG-SS, key = (GG-1)*5+SS; insecure code may read a secure frame's attributes), else tDTRaidRoster from aq.lua, else live (subgroup-1)*5+position. Grid and roster are rebuilt out of combat only, so they go stale together with the numpad. partyDeadCount with its counter, menu and locale key removed, the stored value is cleared at login.

Monitor combat: "Ignore dead party pets" stays on No

Simple: The setting could be set to "No" but was back on "Yes" after the next reload. Fixed.

Technically: aqCombatOnLogin set the value with "x or true"; a stored false is falsy in Lua and was replaced by true at every load. Now only when nil.

Monitor health: "Add Dead on 0 percent" off by default

Simple: The pitch style of the party and raid health monitor appends a "dead" clip to the tone of a member at 0 percent. That was on for party and raid and is now off, for existing characters as well. Switch it back on under Monitor, Party or Raid, Health if you want it. The combat monitor's death announcement (above) is thereby the only death message that runs on its own.

Technically: SkuCore/aq.lua, AqOnLogin: default false instead of true, one-time switch of existing characters via addDeadOn0PercentDefaultOff (same pattern as *DefaultOff in aqCombat).

Dial Targeting: raids only, one key up to 10 players

Simple: "Enabled" under Dial Targeting is now an On/Off toggle and only acts in a raid. The choices "Party" and "Party and Raid" are gone: in a party Sku's default keys numpad 1 to 5 reach everyone anyway, and the party mode laid a shifted numbering (0 = self, 1 to 4 = the others) over them and hid the default keys while it was active. A stored "Party" becomes Off, "Raid" and "Party and Raid" become On. In raids of up to 10 players one key per member is now always active (numpad 1 to 9, 0 = member 10, in subgroup order), from 11 players on the two-digit input. The option "Single key action in raids up to 10 players" is gone, that is the rule now.

Technically: SkuCore/DialTargeting.lua. enabled is mapped once at login to Off/On, singleKeyinRaid10 cleared. DialTargetingRosterUpdate and DialTargeting_EndableDisable only check UnitInRaid and enabled == On; the party branch (unitNameSlot01-0x = partyx) and the dead "party" branch in the secure snippet are removed. Raid mode: tNumCurMembers > 10 means two digits, else raid10. Three locale keys removed. All of it untested in game.

Group numbers: one count for every monitor

Simple: Every number Sku says for a group member should be the key that targets them. In a party that is numpad 1 for you and 2 to 5 for the others; in a raid the dial-targeting number, a single key 1 to 10 with up to 10 players and two digits from 11 on. The death announcement counts that way since this version. Now the raid health monitor and the raid debuff monitor, the threat warnings, "target of target" and "out of range" in the combat monitor, and the aura outputs "source unit" and "target unit" do too. The party health and debuff monitors keep the party count inside a raid, because whoever watches only their own subgroup there targets it with numpad 2 to 5.

The raid health monitor has pitch files for numbers 1 to 25 only, so members 26 to 40 were silent. They are spoken now, the number first, then health in steps of ten, with the voice from the new setting "Voice for members above 25" (Monitor, Raid, Health;

default Justin).

Technically: SkuCore/aq.lua: SkuCore.Monitor.RaidMemberNumbersByName() builds the name-to- number table by the dial rule (up to 10 members flat 1-10 in subgroup order, from 11 (subgroup-1)*5+position); tDTRaidRoster and the dial-targeting grid (DialTargeting.lua) are filled from it, tDTRaidRoster always used the two-digit formula before. SkuCore.Monitor.GroupMemberNumber(unitId) returns the key number for party/raid tokens. The continuous raid debuff output said string.sub(unitId, 5)+1. MonitorOutputRaidPercent2 speaks numbers above 25 via MonitorOutputPlayerStatus (raid.health2.voice, default 1) and returns the duration to the queue; the queue entries carry the absolute health for that. SkuCore/aqCombat.lua: tAllPartyRaidUnits and tUnitsToTestOnGameRaidTargets had raid1-25 hard-wired; they are now refilled in place from the real raid size on every roster event. tSpokenGroupUnit(unitId) applies the death-announcement mapping to every friendly announcement. "party5"/"partypet5" do not exist as words in the combat voices, SkuCoreAqCombatGetVoiceString splits them into "party", "pet", "5". SkuAuras/data.lua: tUnitIdToSpokenName says party N as N+1 and raid N as the dial number.

Raid subgroup keys: jump into a raid group with one key

Simple: Whoever only heals their own group in a raid needs a quick way into a group without the two-digit dial entry. Alt+Numpad 1 to 8 target the first member of raid subgroup 1 to 8 (the member numbered 1 in that group, the same order dial targeting and the monitors use). The target is announced like any target. If the group is empty, Sku says "Group N empty" and nothing happens; outside a raid "No raid". The eight keys have their own sub-menu "Raid subgroup keys" in the Sku key bindings, the second key works too. The feature can be switched off under Features. As with every targeting key: group changes during a fight are picked up after the fight, until then the key jumps to the previous first member.

Technically: New file SkuCore/subgroupTargeting.lua (submodule SubgroupTargeting, in the TOC after skuFocus.lua). Eight SecureActionButtons SkuSubgroupTarget1-8 with type1=macro, macrotext1="/tar <name>", bound via SetOverrideBindingClick WITHOUT a fifth argument (LeftButton, so type1/macrotext1 is read); the names come from GetRaidRosterInfo (first name per subgroup in roster order) on GROUP_ROSTER_UPDATE, GROUP_FORMED/JOINED/LEFT and PLAYER_ENTERING_WORLD out of combat, deferred to PLAYER_REGEN_ENABLED in combat. PreClick (insecure, runs in combat too) speaks the empty / no-raid line. Control frame SkuCoreSubgroupControl, script OnHide, arms both keys of every const via SkuOptions:SkuKeyBindsGetKeys. Consts

SKU_KEY_SUBGROUPTARGET1-8, default ALT-NUMPAD1-8 (SkuZOptions/SkuKeyBinds.lua), group "Raid Untergruppen Tasten" in SkuCore/Options.lua.