------------------------------------------------------------------------------------------------------- - Sku Anniversary Addon Release Notes (Deutsch) ------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.10 Ueberblick Neu Auren: neue Basis-Aura "Dein Ziel wechselt auf ein Gruppenmitglied". Wendet sich der Gegner, den du im Ziel hast, einem anderen Mitglied zu, gibt es einen Ton und das Mitglied wird mit seiner Tastennummer genannt, in Gruppe und Raid. Aenderungen Rollenerkennung: der Gesundheitsmonitor erkennt Tank, Heiler und Schaden jetzt auch fuer Raid-Mitglieder 26 bis 40 automatisch. Bisher nur bis Platz 25. Fokus: /focus1 bis /focus8 nehmen jetzt alle Raid-Plaetze an (raid1 bis raid40), bisher nur bis raid25. Auren: neue Einheiten-Werte "gruppen- oder raidmitglieder" und "... ohne dich". Sie gelten fuer den ganzen Raid; die bisherigen Gruppen-Werte erfassen im Raid nur die eigene Untergruppe. Fehlerbehebungen Monitor Kampf: die Bedrohungswarnungen loesten seit v43.9 einen Lua-Fehler aus (aqCombat.lua:380, UnitGUID) und blieben stumm, zum Beispiel wenn man in einer Gruppe Aggro zog. Behoben. Monitor Kampf: Bedrohungswarnungen wieder hoerbar Einfach: Wer in einer Gruppe Aggro zog oder kurz davor war, bekam seit v43.9 statt der Warnung einen Fehler. Die Warnungen "Bedrohung hoch" und "Bedrohung niedrig" kommen wieder. Sie nennen keinen Spieler, das haben sie nie getan; die Notizen zu v43.9 hatten das falsch beschrieben. Technisch: die vier Ausgaben der beiden Warnungen gaben unit1 = tAllPartyRaidUnits[x] mit, ohne dass es dort ein x gibt, also immer nil; ihre Vorlagen enthalten kein ${unit1}. v43.9 schickte den Wert durch tSpokenGroupUnit, und das rief UnitGUID(nil) auf. Das Argument ist entfernt, tSpokenGroupUnit gibt bei nil jetzt nil zurueck. Rollenerkennung: Raid-Plaetze 26 bis 40 Einfach: Der Gesundheitsmonitor im Raid spricht seit v43.9 auch die Mitglieder 26 bis 40. Ihre Rolle wurde aber nicht automatisch erkannt. Das geht jetzt. Technisch: RoleCheckerIsUnitGUIDInPartyOrRaid kannte nur raid1 bis raid25, die Grenze ist weg. RoleCheckerGetUnitRole stuerzte ab, wenn das gefragte Mitglied beim Aufraeumen der Rollendaten als nicht mehr in der Gruppe entfernt wurde, und las am Ende eine Variable ausserhalb ihres Gueltigkeitsbereichs. Beides behoben. Fokus: alle 40 Raid-Plaetze Einfach: "/focus3 raid30" speicherte bisher den Text "raid30" als Namen, die Fokustaste fand dann niemanden. Jetzt wird wie bei raid1 bis raid25 der Name des Mitglieds gespeichert. Technisch: tFocusUnitIds (skuFocus.lua) kannte raid, raidpet und ihre target-Ketten nur fuer 1 bis 25, jetzt bis MAX_RAID_MEMBERS. Auren: Basis-Aura "Dein Ziel wechselt auf ein Gruppenmitglied" Einfach: Fuer Tanks. Unter Neue Aura, Basis-Auren. Wechselt der Gegner, den du im Ziel hast, auf ein anderes Gruppen- oder Raidmitglied, gibt es einen Ton und Sku sagt, wer es ist: "party 3" in der Gruppe (die Numblock-Taste), die Dial-Nummer im Raid. Kommt er zu dir zurueck, bleibt es still. Unter "Wer" laesst sich einschraenken, wer beobachtet wird. Das ist die Aura aus dem alten Krieger-Schutz-Set, das man seit Langem nicht mehr laden kann, mit einer genaueren Bedingung. Technisch: Ereignis UNIT_TARGETCHANGE, Quelle enthaelt target und ist angreifbar, Ziel = der gewaehlte Wert (vorbelegt raidWoPlayer), Ausgabe Ton plus Zieleinheit. Das alte Set pruefte nur "Quelle ist kein Gruppenmitglied"; weil Sku die Ziele aller 40 Raid-Plaetze verfolgt, loeste dort auch ein Heiler aus einer anderen Untergruppe aus, der jemanden anwaehlte. Basis-Auren koennen jetzt einen anderen Wert als einen Zauber abfragen (valueLabel, emptyValueMessage, defaultValues). Auren: Werte fuer den ganzen Raid Einfach: Bei Quelle, Ziel und "Ziel deines Ziels" gibt es zwei neue Werte: "gruppen- oder raidmitglieder" (mit dir) und "gruppen- oder raidmitglieder ohne dich". In einer Gruppe verhalten sie sich wie die Gruppen-Werte, im Raid gelten sie fuer alle Mitglieder. Die alten Gruppen-Werte bleiben wie sie sind: im Raid nur die eigene Untergruppe. Technisch: tEvaluateRaidValue (data.lua) prueft die Einheitenmenge auf party1-4 und raid1-40. "Ohne dich" heisst: kein "player" in der Menge, weil GetBestUnitId fuer dich im Raid auch deinen raidN-Platz liefert. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.9 Ueberblick Neu Raid-Untergruppen-Tasten: Alt+Numblock 1 bis 8 nimmt das erste Mitglied der Raid-Gruppe 1 bis 8 ins Ziel. Bei leerer Gruppe heisst es "Gruppe N leer" und nichts passiert; ausserhalb eines Raids "Kein Schlachtzug". Eigenes Untermenue "Raid-Untergruppen Tasten" in der Sku-Tastenbelegung, abschaltbar unter Funktionen. Aenderungen Auren: Basis-Auren bieten unter "Ausgabe" jetzt dieselbe Ausgabeliste wie eigene Auren, also alle Toene und alle Datenausgaben (zum Beispiel Zaubername oder Zieleinheit), auch mehrere gleichzeitig. Bisher gab es dort nur einen einzelnen Ton. Berufs- und Lehrerfenster: nach Herstellen, Lernen oder Auswaehlen wird das Menue leise aufgefrischt, der Cursor bleibt auf demselben Eintrag, und nur ein wirklich anderer Eintrag wird angesagt. Monitor Kampf: "Tode ansagen" nennt in einer Gruppe jetzt die Numblock-Taste des Gestorbenen: "party 5, dead" heisst, Numblock 5 ist tot. Das aendert einen sehr alten Standard, bisher wurde das vierte Gruppenmitglied als "party 4" angesagt. Monitor Kampf: im Raid sagt "Tode ansagen" die Dial-Targeting-Nummer des Gestorbenen, also die Taste oder Ziffernfolge, die ihn anwaehlt. Bisher hiess es "party 2" fuer die eigene Untergruppe und "raid 17" fuer alle anderen. Raid-Plaetze 26 bis 40 werden jetzt auch angesagt. Monitor Kampf: "Tode hochzaehlen" ist entfernt. Monitor Gesundheit: "Tot bei 0 Prozent anhaengen" ist jetzt standardmaessig aus, fuer Gruppe und Raid, auch bei bestehenden Charakteren. Dial Targeting: nur noch im Raid. "Aktiviert" ist ein Ein/Aus-Schalter; in einer Gruppe bleiben Numblock 1 bis 5 die normalen Zieltasten (1 = selbst, 2 bis 5 = die anderen). Dial Targeting: in Raids bis 10 Spieler immer eine Taste pro Mitglied (0 = Mitglied 10), ab 11 Spielern zweistellig. Die Option "Nur ein Tastendruck in Raids bis 10 Spieler" ist weg, das ist jetzt die Regel. Monitor Gesundheit, Raid: die Nummern sind die Dial-Targeting-Nummern, in Raids bis 10 Spieler also 1 bis 10 in Untergruppenreihenfolge. Bisher immer zweistellig gezaehlt, in einem 10er-Raid mit jemandem in Gruppe 3 hiess Taste 7 darum "11". Monitor Gesundheit, Raid: Mitglieder mit Nummer 26 bis 40 werden jetzt gesprochen (Nummer, dann Prozent in Zehnern) mit der neuen Einstellung "Stimme fuer Mitglieder ab 26". Tonhoehen-Dateien gibt es nur bis 25, diese Mitglieder waren bisher stumm. Monitor Debuffs, Raid: die Nummern sind ebenfalls die Dial-Targeting-Nummern. Monitor Kampf: Bedrohungswarnungen, "Ziel des Ziels" und "ausser Reichweite" nennen Gruppenmitglieder wie die Todesansage, mit der Numblock-Taste in der Gruppe ("party 2" fuer das erste Mitglied) und der Dial-Nummer im Raid. Bisher der rohe Raid-Platz und "party 1" fuer Taste 2; Raid-Plaetze 26 bis 40 fehlten ganz. Auren: die Ausgaben "Quelleinheit" und "Zieleinheit" nennen Gruppenmitglieder ebenso mit der Tastennummer und Raid-Mitglieder mit der Dial-Nummer. Fehlerbehebungen Quest-Menue: "Route" unter einer Kreatur war immer leer, wenn ihr Name einen Bindestrich oder eine Klammer enthaelt (zum Beispiel "Un'Goro-Gorilla", "Goblin-Ingenieur"). Behoben. Nahe Route: die Suche nach verbundenen Wegpunkten in der Naehe eines Ziels lieferte oft weniger als die zehn naechsten. Hat sehr wahrscheinlich nie jemanden getroffen, reine Korrektheit. Auren: "Alle Auren loeschen" loeschte mit einem einzigen Tastendruck alle Auren, ohne nachzufragen. Jetzt kommt wie beim Loeschen einer einzelnen Aura zuerst "Wirklich loeschen?". Berufs- und Lehrerfenster: nach jedem Herstellen oder Lernen wurde der Fenstername angesagt, und der Cursor sprang manchmal auf einen anderen Eintrag. Behoben. Berufsfenster: Enter auf einem Rezept oder auf "Erstellen" sagte den Eintrag zweimal an. Behoben. Briefkasten: beim Oeffnen wurde zuerst "Ziel" angesagt, bevor "Neuer Brief" kam. Behoben. Tastenbelegung: die zweite Taste ("Sekundaere Taste neu belegen") war fuer eine Reihe von Tasten wirkungslos, darunter "Monitor Gruppe fortlaufende Ausgabe ausloesen", Zielentfernung, Panikmodus, Minimap-Scan, Reichweitenpruefung der Gruppe, "Zu Einheit drehen" und die Scan-Tasten. Behoben. Monitor Kampf: "Tote Gruppenbegleiter ignorieren" sprang nach jedem Neuladen auf "Ja" zurueck. Behoben. Monitor Debuffs, Raid: die fortlaufende Ausgabe sagte Raid-Platz plus eins, eine Nummer, die niemandem gehoerte. Behoben. Monitor Kampf: "party 5, dead" (viertes Gruppenmitglied, neu in dieser Version) piepte bei "Nur Nummern" aus, weil es kein Sprachwort "party5" gibt. Es wird jetzt "party" und "5" gesagt. Quest-Menue: "Route" findet Kreaturen mit Bindestrich im Namen Einfach: Im Quest-Menue (Annahme, Ziel, Abgabe) bietet eine Kreatur "Route", "Nahe Route" und "Wegpunkt". "Route" sagte "Liste leer", sobald der Name der Kreatur einen Bindestrich, eine Klammer oder ein aehnliches Zeichen enthielt, auch wenn die Kreatur gut an das Wegenetz angebunden ist. Im deutschen Client betraf das 249 Kreaturen, darunter alle drei Affenarten im Krater von Un'Goro. "Nahe Route" und "Wegpunkt" waren nicht betroffen. Technisch: SkuQuest/Options.lua, CreateRtWpSubmenu, Zweig "Route": string.find(i, wpName) ohne plain-Argument las den Wegpunktnamen als Lua-Muster. Dort ist "-" ein Quantor ("o-" = beliebig viele o), der Name fand sich also nie selbst. Jetzt string.find(i, wpName, 1, true) an beiden Stellen. Die Routendaten im Krater waren in Ordnung (geprueft: Links, Spawn-Indizes und Anbindung an das Wegenetz). Nahe Route: die zehn naechsten verbundenen Wegpunkte werden wirklich gefunden Einfach: Die meisten Kreaturen sind nicht selbst an das Wegenetz angebunden. Fuer "Nahe Route" sucht Sku darum bis zu zehn verbundene Wegpunkte im Umkreis von 500 Metern um das Ziel und nimmt den besten erreichbaren davon. Diese Suche lieferte oft weniger als zehn. Der naechste Wegpunkt war aber immer dabei, und das Wegenetz ist fast ueberall zusammenhaengend. Das hat sehr wahrscheinlich nie jemanden getroffen; die Korrektur ist nur der Korrektheit wegen da. Sichtbar geworden waere der Fehler nur, wenn der naechste Wegpunkt auf einem abgetrennten Stueck des Wegenetzes liegt: dann "Liste leer" oder ein kleiner Umweg. Technisch: SkuNav:GetNearestWpsWithLinksToWp (SkuNav/Core.lua). Das sortierte Einfuegen kannte keinen Anhaenge-Fall: ein Kandidat, der weiter weg war als alle Eintraege, fiel weg, obwohl die Liste noch Platz hatte. Der erste Treffer von pairs() setzte damit die Obergrenze. Das Kuerzen bei mehr als N Eintraegen entfernte schon immer den entferntesten und bleibt. Offline gegen "die N naechsten" geprueft (20000 Zufallsfaelle): alt 9059 zu kurz, neu alle richtig. Alle fuenf Aufrufer werten die ganze Liste aus und nehmen den besten erreichbaren Eintrag, mehr Kandidaten koennen also nur gleich gute oder bessere Routen ergeben. Auren: Basis-Auren haben die volle Ausgabeliste Einfach: Unter "Neue aura", "Basis-Auren" hatte jede Vorlage einen Eintrag "Ton", in dem man genau einen Ton auswaehlen konnte, sonst nichts. Dieser Eintrag heisst jetzt "Ausgabe", mit der Anzahl der eingeschalteten Ausgaben dahinter, und oeffnet dieselbe Liste wie bei einer eigenen Aura: alle Toene und alle Datenausgaben, zum Beispiel Zaubername oder Zieleinheit. Jeder Eintrag ist ein Schalter, Enter schaltet ihn ein oder aus, und mehrere duerfen gleichzeitig an sein. Was die Vorlage bisher vorgab (ihr Ton, bei "Dein Buff auf Gruppenmitglied ausgelaufen" zusaetzlich Zaubername und Zieleinheit), ist beim Oeffnen schon eingeschaltet und laesst sich jetzt auch abschalten. Technisch: SkuAuras/Options.lua. tBuildOutputsLevel nimmt einen optionalen Kontext (outputs, ownerLabel, tooltip); ohne ihn bearbeitet die Liste wie bisher den Entwurf des Aura-Baukastens, mit ihm die Liste des Basis-Formulars. Das Formular (tBaseForm) fuehrt statt eines einzelnen sound-Werts eine Liste outputs, vorbelegt aus defaultSound und defaultOutputs (vorher fixedOutputs, die beim Erstellen fest angehaengt wurden). Zusammenfassung und tBaseFormCommit lesen diese Liste; ist keine Ausgabe an, bleibt es bei "Keine Ausgabe festgelegt". Auren: "Alle Auren loeschen" fragt nach Einfach: "Alle Auren loeschen" im Auren-Menue hatte keine Unterebene: ein Enter oder Pfeil rechts, und alle Auren des Charakters waren weg. Jetzt fuehrt der Eintrag, wie beim Loeschen einer einzelnen Aura, auf "Wirklich loeschen?". Erst Enter dort loescht, Pfeil links bricht ab. Technisch: SkuAuras/Options.lua, MenuBuilder: der Eintrag ist jetzt dynamic und legt per BuildChildren den einen Kindeintrag "Wirklich loeschen?" an. Beim Betreten zeigt selectTarget auf den Eintrag selbst, Enter auf dem Kind ruft dessen OnAction. Vorher dynamic = false ohne Kinder, OnPostSelect lief also direkt in den OnAction-Zweig. Menue: Pfade werden aufgeloest statt durchlaufen Einfach: Immer wenn Sku das Menue selbst an eine bestimmte Stelle setzt (ein Fenster geht auf, eine Schnelltaste wie Umschalt-F10, oder ein Fenster hat sich geaendert und sein Menue wird neu aufgebaut), lief es bisher den Pfad dorthin ab, als wuerde auf jeder Ebene Enter gedrueckt, und sagte jede Zwischenstation an. Beim leisen Neuaufbau eines Berufs- oder Lehrerfensters nach Herstellen oder Lernen hoerte man darum den Fensternamen ("Beruf", "Lehrer"), und der Cursor wurde nach Zeilennummer zurueckgesetzt, in einer Liste, die sich gerade veraendert hatte. Jetzt wird der Zielpfad direkt aufgeloest, ohne Ansage der Zwischenstationen, und der Cursor kehrt zu demselben Eintrag zurueck: dasselbe Rezept (auch mit neuer Anzahl), dieselbe Faehigkeit, derselbe Knopf. Nur wenn dieser Eintrag weg ist, wird angesagt, wo der Cursor gelandet ist. Technisch: SkuOptions:ResolveMenuPath und EnsureLevelBuilt (SkuZOptions/Core.lua) ersetzen die Schleife in SlashFunc, die auf jedem Pfadsegment OnSelect(true) aufrief. Ebenen auf dem Weg werden nur gebaut (dynamic: RebuildNodeChildren, sonst einmal BuildChildren, wenn leer), nie selektiert; nur das Ziel bekommt sein OnSelect wie bisher (Vorbau bei leerer, nicht dynamischer Ebene, nie auf isSkuToggle). Damit entfallen die Nebenwirkungen des Durchlaufs: actionOnEnter-Knoten auf dem Weg wurden ausgeloest, alle Geschwister vor dem Treffer vorgebaut. Der aSilent-Parameter von SlashFunc wirkt jetzt. Die Wiederherstellung in SkuCore:CheckFrames macht einen stillen Aufruf statt zwei sprechender und setzt den Cursor direkt: skuIdentity, dann Name, dann die Zeile am alten Index (begrenzt auf die neue Laenge). Fenster-Eintraege tragen skuIdentity (SkuIterateGossipList kopiert es): Rezepte "recipe:Name (Rang)", Kategorien "cat:", Lehrer-Faehigkeiten "skill:", sonst "frame:" fuer jeden Eintrag, der allein auf seinem Frame steht (SkuCore:PrepareWindowEntries am Ende der drei Builder). SkuCore:RefreshWindowMenuQuietly (LocalMenu.lua) ist der gemeinsame leise Neuaufbau fuer TRADE_SKILL_UPDATE/CRAFT_UPDATE und den Lehrer-Knopf; er spricht nur, wenn Identitaet (oder der Name ohne Anzahl) hinterher eine andere ist. Die Taschen behalten ihren eigenen Pfad (tFindMenuNodeByPath, tBagAnnounceSuppress). Berufsfenster: Enter auf Rezept oder "Erstellen" sagte den Eintrag doppelt an Einfach: Nach Enter auf einem Rezept oder einem Erstellen-Knopf wurde der Eintrag zweimal gesprochen. Jetzt einmal. Technisch: Der klassische Klickpfad in SkuIterateGossipList rief nach func ein sprechendes CheckFrames und 0,35 s spaeter OnUpdate auf, zusaetzlich zur Ansage des Tastenhandlers. Die dritte Ansage fing meist die Dubletten-Sperre (1 s) ab, die zweite kam 0,9 s spaeter und nicht. Eintraege mit quietClick (gesetzt von PrepareWindowEntries fuer alle Klick-Knoepfe ohne containerFrameName) laufen jetzt ueber func plus RefreshWindowMenuQuietly; Knoepfe mit sicherem /click behalten den alten Pfad. Briefkasten: "Ziel" vor "Neuer Brief" Einfach: Beim Oeffnen eines Briefkastens wurde zuerst "Ziel" angesagt und dann erst "Neuer Brief". Jetzt nur noch "Neuer Brief". Technisch: Mail:MAIL_SHOW oeffnete den Pfad "Lokal, Post", bevor der MailFrame sichtbar war; der Post-Eintrag unter Lokal existiert aber nur bei sichtbarem Frame. Der Pfad fand nichts, und das stille Oeffnen sagte ersatzweise den ersten Wurzeleintrag an ("Ziel", das Zielmenue); die Taschen holten das Menue kurz darauf ueber CheckFrames in die Post. Das Debug-Log zeigte "path walk found nothing ... short,lokal,post" bei jedem Briefkasten seit mindestens v43.6; aufgefallen ist es erst, als die Zwischenansagen weg waren. Jetzt oeffnet MAIL_SHOW einen Frame spaeter (C_Timer.After(0)), nur bei sichtbarem MailFrame und nur, wenn der Cursor nicht schon in der Post steht. Tastenbelegung: zweite Taste fuer Monitor, Scan, Drehen und Co. Einfach: Unter "Sku Tastenbelegung" hat jede Taste eine erste und eine zweite Belegung. Fuer eine Reihe von Tasten liess sich die zweite zwar setzen und wurde auch als "Taste 2" angesagt, tat aber nichts. Betroffen waren "Monitor Gruppe fortlaufende Ausgabe ausloesen", Zielentfernung, Panikmodus, Minimap-Scan weit und eng, Reichweitenpruefung der Gruppenmitglieder, "Zu Einheit drehen" 1 bis 6 und 180 Grad, "Scan fortsetzen", Scan 1 bis 8 und die Ressourcen-Benachrichtigung. Jetzt wirkt die zweite Taste ueberall. Ausserdem heisst die Monitor-Taste jetzt richtig "fortlaufende" statt "forlaufende". Technisch: SkuCore/Core.lua, OnHide-Script von SkuCoreControlOption1: die Bindungen dieses Frames wurden mit SetOverrideBindingClick nur fuer .key gesetzt (einzige Ausnahme war SKU_KEY_TAXICANCEL), der Click-Dispatcher prueft per SkuKeyBindsMatchKey aber beide Felder. Die Tastenbelegungs-Menues in SkuZOptions/Core.lua setzen key2 seit jeher, daher funktionierte die zweite Taste bei anderen Aktionen. Ein lokaler tArm(aConst)-Helfer bindet jetzt jede Taste, die SkuKeyBindsGetKeys liefert; die zwanzig handgeschriebenen Einzelzeilen sind weg. Monitor Kampf: Todesansage nennt die Numblock-Taste Einfach: Unter Monitor, Kampf, Freundlich, "Tode ansagen" wird ein gestorbenes Gruppenmitglied angesagt. Die Nummer darin ist jetzt immer die Taste, die das Mitglied anwaehlt. In einer Gruppe sind das Skus Standardtasten: Numblock 1 = selbst, 2 bis 5 = die vier anderen. Das vierte Gruppenmitglied heisst darum jetzt "party 5, dead", nicht mehr "party 4". So zaehlen der Gesundheitsmonitor und die Uebersicht seit jeher. Im Raid wird die Dial-Targeting-Nummer angesagt: bis 10 Spieler die eine Taste, ab 11 die zweistellige Folge. Bisher hiess es dort "party 2" fuer Mitglieder der eigenen Untergruppe und "raid 17" (der rohe Raid-Platz) fuer alle anderen, zwei Zaehlungen in einem Kampf, keine davon passte zum Numblock. Raid-Plaetze 26 bis 40 wurden gar nicht angesagt. "Tode hochzaehlen" ist entfernt: im Modus "nur Nummer" war sein "3, dead" nicht von "party 3, dead" zu unterscheiden, und der Zaehler ging bei einer Wiederbelebung nie zurueck. Technisch: SkuCore/aqCombat.lua, aqCombat_SKU_UNIT_DIED. Neuer Helfer tDeathUnitToken(GUID) liefert gesprochenes Token und echte Unit-ID getrennt, die Pruefungen UnitIsDeadOrGhost und Begleiter brauchen den rohen Platz. Gruppe: Token aus aqCombatGroupGuidToUnitId, Ziffer plus 1. Raid: alle MAX_RAID_MEMBERS Plaetze per GUID durchsucht (die 25 in tAllPartyRaidUnits reichten nicht), Nummer aus dem Dial-Targeting-Raster gelesen (SkuSecureTargetingFrame, unitNameSlotGG-SS, Taste = (GG-1)*5+SS; Attribute eines Secure-Frames darf unsicherer Code lesen), sonst tDTRaidRoster aus aq.lua, sonst live (Untergruppe-1)*5+Position. Raster und Roster werden nur ausserhalb des Kampfes neu gebaut, veralten also gemeinsam mit dem Numblock. partyDeadCount samt Zaehler, Menue und Locale-Schluessel entfernt, der gespeicherte Wert wird beim Login geloescht. Monitor Kampf: "Tote Gruppenbegleiter ignorieren" bleibt auf Nein Einfach: Die Einstellung liess sich auf "Nein" stellen, stand nach dem naechsten Neuladen aber wieder auf "Ja". Behoben. Technisch: aqCombatOnLogin setzte den Wert mit "x or true"; ein gespeichertes false ist in Lua falsch und wurde so bei jedem Laden durch true ersetzt. Jetzt nur noch bei nil. Monitor Gesundheit: "Tot bei 0 Prozent anhaengen" standardmaessig aus Einfach: Der Tonhoehen-Stil des Gruppen- und Raid-Gesundheitsmonitors haengt an den Ton eines Mitglieds mit 0 Prozent einen "dead"-Clip an. Das war fuer Gruppe und Raid eingeschaltet und ist jetzt aus, auch bei bestehenden Charakteren. Wer es will, schaltet es unter Monitor, Gruppe beziehungsweise Raid, Gesundheit wieder ein. Die Todesansage des Kampfmonitors (oben) ist damit die einzige Todesmeldung, die von sich aus laeuft. Technisch: SkuCore/aq.lua, AqOnLogin: Vorgabe false statt true, einmalige Umstellung bestehender Charaktere ueber addDeadOn0PercentDefaultOff (Muster wie *DefaultOff in aqCombat). Dial Targeting: nur noch im Raid, eine Taste bis 10 Spieler Einfach: "Aktiviert" unter Dial Targeting ist jetzt ein Ein/Aus-Schalter und wirkt nur im Raid. Die Auswahl "Gruppe" und "Gruppe und Raid" ist weg: in einer Gruppe erreichen Skus Standardtasten Numblock 1 bis 5 ohnehin jeden, und der Gruppenmodus legte eine verschobene Zaehlung (0 = selbst, 1 bis 4 = die anderen) darueber und verdeckte die Standardtasten, solange er aktiv war. Gespeichertes "Gruppe" wird zu Aus, "Raid" und "Gruppe und Raid" zu Ein. In Raids bis 10 Spieler ist jetzt immer eine Taste pro Mitglied aktiv (Numblock 1 bis 9, 0 = Mitglied 10, Reihenfolge nach Untergruppen), ab 11 Spielern die zweistellige Eingabe. Die Option "Nur ein Tastendruck in Raids bis 10 Spieler" ist weg, das ist jetzt die Regel. Technisch: SkuCore/DialTargeting.lua. enabled wird beim Login einmalig auf Aus/Ein abgebildet, singleKeyinRaid10 geloescht. DialTargetingRosterUpdate und DialTargeting_EndableDisable pruefen nur noch UnitInRaid und enabled == Ein; der Gruppenzweig (unitNameSlot01-0x = partyx) und der tote "party"-Zweig im Secure-Snippet sind entfernt. Raid-Modus: tNumCurMembers > 10 heisst zweistellig, sonst raid10. Drei Locale-Schluessel entfernt. Alles ungetestet im Spiel. ------------------------------------------------------------------------------------------------------- Gruppennummern: eine Zaehlung fuer alle Monitore Einfach: Jede Nummer, die Sku fuer ein Gruppenmitglied sagt, soll die Taste sein, die es anwaehlt. In der Gruppe ist das Numblock 1 fuer dich und 2 bis 5 fuer die anderen; im Raid die Dial-Targeting-Nummer, also eine Taste 1 bis 10 bei bis zu 10 Spielern und zwei Ziffern ab 11. Die Todesansage zaehlt seit dieser Version so. Jetzt tun es auch der Gesundheitsmonitor und der Debuff-Monitor im Raid, die Bedrohungswarnungen, "Ziel des Ziels" und "ausser Reichweite" im Kampfmonitor sowie die Auren-Ausgaben "Quelleinheit" und "Zieleinheit". Der Gesundheits- und der Debuff-Monitor fuer die Gruppe laufen im Raid weiter mit der Gruppenzaehlung, denn wer im Raid nur seine Untergruppe im Blick hat, waehlt sie dort mit Numblock 2 bis 5 an. Der Gesundheitsmonitor im Raid hat Tonhoehen-Dateien nur fuer die Nummern 1 bis 25. Mitglieder 26 bis 40 waren darum stumm; sie werden jetzt gesprochen, erst die Nummer, dann die Gesundheit in Zehnerschritten, mit der Stimme aus der neuen Einstellung "Stimme fuer Mitglieder ab 26" (Monitor, Raid, Gesundheit; Standard Justin). Technisch: SkuCore/aq.lua: SkuCore.Monitor.RaidMemberNumbersByName() baut die Name-zu- Nummer-Tabelle nach der Dial-Regel (bis 10 Mitglieder flach 1-10 in Untergruppenreihenfolge, ab 11 (Untergruppe-1)*5+Position); tDTRaidRoster und das Dial-Targeting-Raster (DialTargeting.lua) werden daraus gefuellt, bisher rechnete tDTRaidRoster immer zweistellig. SkuCore.Monitor.GroupMemberNumber(unitId) liefert die Tastennummer fuer party-/raid-Tokens. Die fortlaufende Debuff-Ausgabe im Raid sagte string.sub(unitId, 5)+1. MonitorOutputRaidPercent2 spricht Nummern ueber 25 per MonitorOutputPlayerStatus (raid.health2.voice, Standard 1) und gibt die Dauer an die Warteschlange zurueck; die Warteschlangen-Eintraege tragen dafuer die absolute Gesundheit. SkuCore/aqCombat.lua: tAllPartyRaidUnits und tUnitsToTestOnGameRaidTargets enthielten raid1-25 fest; sie werden jetzt bei jedem Roster-Ereignis an Ort und Stelle aus der echten Raidgroesse neu gefuellt. tSpokenGroupUnit(unitId) nutzt die Todesansage-Zuordnung fuer alle freundlichen Ansagen. "party5"/"partypet5" gibt es in den Kampfstimmen nicht als Wort, SkuCoreAqCombatGetVoiceString zerlegt sie in "party", "pet", "5". SkuAuras/data.lua: tUnitIdToSpokenName sagt party N als N+1 und raid N als Dial-Nummer. Raid-Untergruppen-Tasten: mit einer Taste in eine Raid-Gruppe springen Einfach: Wer im Raid nur seine eigene Gruppe versorgt, braucht einen schnellen Einstieg in eine Gruppe, ohne die zweistellige Dial-Eingabe. Alt+Numblock 1 bis 8 nimmt das erste Mitglied der Raid-Gruppe 1 bis 8 ins Ziel (das Mitglied mit Nummer 1 in dieser Gruppe, dieselbe Reihenfolge wie Dial Targeting und die Monitore). Das Ziel wird wie jedes Ziel angesagt. Ist die Gruppe leer, sagt Sku "Gruppe N leer" und nichts passiert; ausserhalb eines Raids "Kein Schlachtzug". Die acht Tasten haben ein eigenes Untermenue "Raid-Untergruppen Tasten" in der Sku-Tastenbelegung, auch die zweite Taste funktioniert. Die Funktion laesst sich unter Funktionen abschalten. Wie bei allen Zieltasten gilt: Gruppenwechsel waehrend eines Kampfes werden erst nach dem Kampf uebernommen, bis dahin springt die Taste zum alten ersten Mitglied. Technisch: Neue Datei SkuCore/subgroupTargeting.lua (Untermodul SubgroupTargeting, in der TOC nach skuFocus.lua). Acht SecureActionButtons SkuSubgroupTarget1-8 mit type1=macro, macrotext1="/tar ", gebunden per SetOverrideBindingClick OHNE fuenftes Argument (LeftButton, damit type1/macrotext1 gelesen wird); die Namen werden aus GetRaidRosterInfo (erster Name je Untergruppe in Roster-Reihenfolge) bei GROUP_ROSTER_UPDATE, GROUP_FORMED/JOINED/LEFT und PLAYER_ENTERING_WORLD ausserhalb des Kampfes geschrieben, im Kampf auf PLAYER_REGEN_ENABLED verschoben. PreClick (unsicher, laeuft auch im Kampf) spricht die Leer-/Kein-Raid-Meldung. Kontroll-Frame SkuCoreSubgroupControl, Script OnHide, bewaffnet beide Tasten jeder Konstante ueber SkuOptions:SkuKeyBindsGetKeys. Konstanten SKU_KEY_SUBGROUPTARGET1-8, Standard ALT-NUMPAD1-8 (SkuZOptions/SkuKeyBinds.lua), Gruppe "Raid Untergruppen Tasten" in SkuCore/Options.lua. Aenderungen in Sku v43.8 Ueberblick Neu Spieleinstellungen: Kontrollkaestchen mit Regler oder Auswahlliste (zum Beispiel "Maximale Vordergrund-FPS"), Schaltflaechen, der Block "Grafikqualitaet" und die Farbenblindheits-Einstellungen sind jetzt bedienbar; bisher hiess es dort "nicht unterstuetzt". Spieleinstellungen: Zahlenwerte haben als ersten Eintrag "Wert eingeben" (Textfeld), Ziffern filtern die Werteliste, und die Werte tragen die Beschriftung des Spiels ("60 FPS", "150%"). Spieleinstellungen: Auswahllisten sagen "(empfohlen)" und "(nicht verfuegbar)" wie das Spiel, ausgegraute Eintraege "(deaktiviert)", und Untermenues von AddOn-Einstellungen werden angezeigt. Aenderungen Fehlermeldungen des Spiels (zum Beispiel "Ihr habt kein Ziel") werden beim Haemmern auf eine Taste nur noch einmal vorgelesen. Dieselbe Meldung wird erst wieder angesagt, wenn du die Taste etwa zweieinhalb Sekunden in Ruhe gelassen hast oder wenn dazwischen eine andere Fehlermeldung kam. Zum Beacon, Wegpunkt oder zur Einheit drehen: die Drehung landet jetzt auf jedem Rechner gleich genau und ist deutlich schneller. Bei 20 Bildern pro Sekunde dauerte eine halbe Drehung fast eine halbe Sekunde und jeder vierte Tastendruck ging verloren; jetzt eine Viertelsekunde, und kaum ein Druck geht verloren. Auf schnellen Rechnern treffen grosse Drehungen auf etwa ein Grad statt drei bis fuenf. Die Selbstkalibrierung aus v43.7 entfaellt. Fehlerbehebungen Sprachausgabe: dieselbe Zeile stellte sich seit v43.7 bei jedem Tastendruck erneut hinten an und wurde viele Male hintereinander vorgelesen, auch noch nach einer wichtigeren Ansage. Behoben. Menue: wer direkt nach "Menue geoeffnet" schon eine Taste drueckte (Ende, Pos1, Pfeil), bekam nach dem neuen Eintrag noch den ersten Hauptmenue-Eintrag ("Ziel Menue") nachgesprochen. Behoben. Sprachausgabe: dieselbe Zeile stellt sich nicht mehr hinter sich selbst an Einfach: Seit v43.7 konnte eine Meldung, die mehrfach kurz hintereinander ausgeloest wurde, sich beliebig oft in die Warteschlange stellen. Wer eine Taste haemmerte, die einen Fehler ausloest, hoerte "Ihr habt kein Ziel" danach zehn- oder zwanzigmal, und nach einer dazwischengehenden Zielansage kam die Meldung noch einmal. Jetzt gilt: wartet derselbe Text schon oder wird er gerade gesprochen, wird die neue Kopie verworfen. Menuezeilen und andere Ansagen, die du per Taste ausdruecklich noch einmal anforderst, sind nicht betroffen. Technisch: SkuVoice:OutputStringBTtts (Libs/SkuVoice-1.0). Die Pruefung "wird genau das gerade gesprochen" lief bisher bei der Uebergabe an den Client. Seit dem Client-Gate aus v43.7 erreicht eine Kopie die Uebergabe erst, wenn ihr Vorgaenger FINISHED ist - die Pruefung traf nie mehr (Log: Warteschlange 35 x dieselbe Zeile). Zeilen ohne queuereset werden darum jetzt beim EINREIHEN gegen mSkuVoiceQueueBTTS und mSkuVoiceQueueBTTS_Speaking geprueft; Log-Marke "BTTS ENQUEUE-DUP". Neues Harness-Szenario "errspam" (dev/rework-docs/voice-harness). Menue: erster Eintrag kam nach einem schnellen Tastendruck verspaetet doch noch Einfach: Beim Oeffnen des Menues sagt Sku "Menue geoeffnet" und danach den ersten Eintrag. Wer schon waehrend "Menue geoeffnet" eine Taste drueckte, hoerte den neuen Eintrag - und danach trotzdem noch "Ziel Menue", den ersten Eintrag, der gar nicht mehr dran war. Es hing nur davon ab, wie schnell man drueckte, nicht von der Taste oder dem Menue. Jetzt faellt der alte erste Eintrag weg, sobald ein anderer Menueeintrag angesagt wird. Technisch: Zwei Ursachen. (1) Die Regel "wartende Zeile ohne Reset hinter der neuen Ueberschreibzeile aufheben" aus v43.7 (gedacht fuer Chat, in den eine Warnung hineinschneidet) galt auch fuer Menuezeilen. Die Keep-Schleife in SkuVoice (queuereset-Scan, Libs/SkuVoice-1.0) verwirft jetzt eine wartende Zeile, deren Scope mit dem der neuen Ueberschreibzeile uebereinstimmt: ein Scope ist eine Position in einer Oberflaeche, nur seine juengste Zeile ist wahr. (2) Die beiden Zeilen beim Oeffnen ("Menu;open" und SkuOptions.Menu[1].name, SkuZOptions/Core.lua) riefen OutputStringBTtts direkt und OHNE den Scope "menu" auf, den VocalizeCurrentMenuName jeder anderen Menuezeile gibt - der Scope-Vergleich hatte also nichts zu vergleichen. Beide tragen jetzt "menu"; damit verwirft auch EndScope("menu") beide, wenn das Menue sofort wieder geschlossen wird. Log vorher: "BTTS queuereset kept 1 waiting line(s) behind the overwrite". Fehlermeldungen: nur ansagen, wenn sie neu erscheinen Einfach: Sku richtet sich jetzt nach der Regel, die das Spiel fuer Sehende anwendet. Dort steht eine Fehlermeldung etwa zweieinhalb Sekunden auf dem Bildschirm; kommt dieselbe Meldung in dieser Zeit noch einmal, blitzt sie nur kurz auf und bleibt laenger stehen, statt neu zu erscheinen. Entsprechend liest Sku eine Fehlermeldung vor, wenn sie erscheint, und schweigt, solange sie noch "auf dem Bildschirm steht". Jeder weitere Tastendruck verlaengert diese Zeit. Das Klickgeraeusch des Spiels sagt dir weiterhin bei jedem Druck, dass es noch nicht geht. Laesst du die Taste etwa zweieinhalb Sekunden in Ruhe und drueckst dann wieder, wird die Meldung erneut angesagt. Eine ANDERE Fehlermeldung wird immer sofort vorgelesen, und danach gilt auch die erste wieder als neu: Fehler A, Fehler B, Fehler A sind drei Ansagen. Betrifft nur vorgelesene Fehler, nicht die Ton- und Sprachhinweise. Technisch: UIErrors:OutputError (SkuCore/UIErrors.lua), TTS-Zweig. Gemerkt wird nur der ZULETZT gesprochene Fehler: tSpokenKey plus tSpokenShownUntil = GetTime() + 2.5 (displayDuration 2 + fadeDuration 0.5 aus UIErrorsFrame.xml). Jede Wiederholung setzt die Zeit neu, wie ResetMessageFadeByID; jeder andere Fehler, auch ein Ton- oder Sprachhinweis, ersetzt bzw. loescht tSpokenKey. Die erste Fassung fuehrte eine Zeitmarke PRO Text - dadurch blieb Fehler A stumm, obwohl Fehler B dazwischen lag. Bewusst eine Zeitmarke und kein Auslesen von UIErrorsFrame: Blizzard drosselt nur rund 20 Meldungstypen, bei den uebrigen kommt pro Druck eine neue Zeile dazu, und die Reihenfolge der beiden UI_ERROR_MESSAGE-Handler ist nicht festgelegt. Spieleinstellungen: alle Bedienelemente der Blizzard-Einstellungen Einfach: Im Menue Einstellungen, Spieleinstellungen waren viele Eintraege nur mit "(nicht unterstuetzt)" zu hoeren, zum Beispiel "Maximale Vordergrund-FPS". Jetzt sind sie bedienbar. Ein Kontrollkaestchen mit Regler wird zu zwei Eintraegen: dem Schalter und "... Wert". Zahlenwerte sind eine Werteliste mit den Beschriftungen des Spiels ("60 FPS", "150%"); Ziffern filtern die Liste, und der erste Eintrag "Wert eingeben" oeffnet das Textfeld. Auswahllisten markieren die Empfehlung mit "(empfohlen)" und Werte, die dieser Rechner nicht kann, mit "(nicht verfuegbar)". Schaltflaechen wie "Chatposition zuruecksetzen" fuehren ihre Aktion aus. Der Block "Grafikqualitaet" ist ein Untermenue mit "Schlachtzug und Schlachtfeld". Die Tastenbelegung verweist auf Skus eigenes Menue. Eine Einstellung, die vom Spiel gerade ausgegraut ist, sagt "(deaktiviert)". Ausserdem wurden Grafik-, Anzeige- und UI-Skalierungs-Einstellungen bisher nur vorgemerkt und nie angewendet - sie greifen jetzt sofort. Technisch: SkuCore/gameOptions.lua verzweigt jetzt nach dem Frame-Template des Initializers (Blizzard_SettingControls.lua) statt nach dem Werttyp: Checkbox, Slider, Dropdown, CheckboxSlider (cbSetting/sliderSetting), CheckboxDropdown, CheckboxWithButton, Button, AdvancedQualitySection (die Optionslisten sind dort Closures im Frame; Sku leitet sie aus einer Tabelle je CVar ab und fragt IsGraphicsSettingValueSupported), ColorblindSelector, Keybinding-Sektionen. setting:SetValue(v) ohne zweites Argument legt bei Settings mit CommitFlag.Apply nur einen pendingValue an, den erst der Apply-Knopf des Panels schreibt - Sku oeffnet das Panel nie, darum jetzt SetValue(v, true) plus RestartGx / UpdateWindow / SaveBindings je nach Commit-Flag. GetAllCategories liefert nur Top-Level-Kategorien, GetSubcategories wird rekursiv gelaufen. ShouldShow false = Zeile entfaellt, GetModifyPredicates false = Suffix "(deaktiviert)". Beschriftung der Zahlenwerte ueber options.formatters[Label.Right]; eine Tippeingabe wird linear durch den Formatter zurueckgerechnet (Prozent, Qualitaetsregler 1..10). Jeder Schreibzugriff loggt "gameOptions: set". Ein Offline-Harness gegen gefakte Setting-Objekte lief durch; im Spiel geprueft: FPS-Schalter und -Wert (Log: PROXY_FOREGROUND_FPS = 20, TurnCal fps 20). Drehen zum Beacon: bildgenau statt zeitgenau Einfach: Bisher drehte Sku die Kamera fuer eine berechnete Zeit und hielt sie dann an. Das Spiel bewegt die Kamera aber nur einmal je Bild, und ein Zeitgeber trifft die Bildgrenze nur ungefaehr - bei wenig Bildern pro Sekunde daneben. Auf einem langsamen Rechner (20 Bilder pro Sekunde, im Test per FPS-Begrenzung nachgestellt) dauerte darum jede Drehung ueber 15 Grad fast eine halbe Sekunde, kleine Drehungen blieben ein Drittel zu kurz, jeder vierte Tastendruck fiel in die Sperrzeit und ging verloren, und beritten kreiste man wieder um nahe Wegpunkte. Jetzt zaehlt Sku die Bilder und rechnet mit ihrer echten Dauer: die Drehgeschwindigkeit wird so gewaehlt, dass der Winkel in ganzen Bild-Schritten aufgeht, und wuerde der letzte Schritt ueber das Ziel hinausschiessen, wird er verkuerzt. Ergebnis bei 20 Bildern pro Sekunde: halbe Drehung in einer Viertelsekunde, alle Drehungen innerhalb von zwei Grad, kaum verlorene Druecke, kein Kreisen. Bei 80 bis 120 Bildern: grosse Drehungen mit etwa einem Grad Fehler statt drei bis fuenf, kleine unter einem halben Grad. Die Selbstkalibrierung aus v43.7 ist weg - sie lernte Werte, die auf jedem Rechner gleich sind. /skuturn zeigt nur noch, ob der schnelle Gang auf diesem Rechner funktioniert; /skuturn reset setzt diese Pruefung zurueck. Technisch: GameWorldObjects:TurnToWorldPosition (SkuCore/gameWorldObjects.lua). Gemessen an rund 400 Drehungen bei 20 und 77 bis 125 fps (Restfehler 0.5 ms): die Kamera schreitet einmal je Frame um Tempo mal ECHTE Framedauer; der Frame, in dessen OnUpdate der Stopp faellt, schreitet nicht mehr; die im OnUpdate gemessene Framedauer ist genau die des naechsten Schritts. Planer: n = ceil(Winkel / (1440 * f)) Schritte, v = Winkel / (n * f), CVar hoechstens 360, Rest als MoveView-Faktor. Stopp aus einem OnUpdate-Zaehler, der die echten Framedauern aufsummiert und stoppt, sobald die Summe die Bewegungszeit Winkel/v erreicht; wuerde der letzte Schritt ueberschiessen, wird cameraYawMoveSpeed fuer diesen einen Frame auf den Rest skaliert und im Folgeframe gestoppt - die CVar wirkt sofort (54 getrimmte Drehungen: Fehler 0.5 Grad statt der 5.3, die eine tote CVar ergeben haette). C_Timer war die Ursache der alten Streuung: er feuert nur an Framegrenzen und faellt bei 2 Prozent Frame-Streuung um einen ganzen Frame. Das "Nachgleiten" der Kamera aus v43.7 war dieser eine Leerframe, keine Traegheit. Die Kalibrierung (Massstab und Latenz je Gang, Store v4/v5) lernte 1.00 und einen Frame mit Streuung 0.01 und wurde entfernt; Store turnCal v6 haelt nur noch noGear2 (Faktor wirkt nicht: Median echtes/verlangtes Tempo unter 0.7 bei 6+ schnellen Drehungen). Sperrzeit nach dem Stopp 2 Frames bzw. 50 ms statt 3 bzw. 100. Log "TurnCal" je Druck mit n, m, mt, trim, dts (alle Framedauern), fest/fact/fmax, rest_land, lead_shift; Analyse-Skripte im Scratchpad-Muster an4.py. Lehren fuer WowVision: dev/rework-docs/TURN-TO-BEACON-LESSONS.md. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.7 Ueberblick Aenderungen Zum Beacon drehen (T), Zu Einheit drehen und Zum Ziel drehen: grosse Drehungen landen jetzt mit EINEM Druck. Bisher blieb jeder Druck bei etwa 88 Grad haengen, eine Kehrtwende brauchte immer zwei. Drehungen sind deutlich schneller: eine halbe Drehung dauert auf einem flotten Rechner gut eine Zehntelsekunde statt einer Viertelsekunde. Wer schon auf den Beacon ausgerichtet ist (innerhalb von 3 Grad), wird nicht mehr gedreht. Das beendet das Hin-und-her-Pendeln um den Beacon-Ping. Die Drehung misst sich selbst ein: Sku prueft nach jeder Drehung, wie weit du wirklich gedreht hast, und passt sich an deinen Rechner und deine Bildrate an. Die ersten paar Drehungen nach dem Update koennen ungenau sein. Tastaturecho mit einer echten Windows-Stimme (nicht die NVDA-Bruecke): die lange Pause nach jedem getippten Buchstaben ist weg, die Buchstaben folgen dicht aufeinander. Text in ein Eingabefeld einfuegen (Strg+V): Sku sagt jetzt einmal "Eingefuegt", statt den eingefuegten Text Buchstabe fuer Buchstabe vorzulesen. Fehlerbehebungen Schwimmen und Fliegen: Die Neigungssperre greift jetzt auch im Kampf. Wer kaempfend ins Wasser lief, tauchte bisher bei den ersten Drehungen ab. Gegenstaende aus einem Ausruestungsset: der Tooltip nannte die Ruestungsart (zum Beispiel "Stoff") zweimal. Jetzt nur noch einmal. Sprachausgabe mit einer echten Windows-Stimme (nicht die NVDA-Bruecke): Zeilen, die laengst ueberholt waren, kamen Sekunden bis Minuten spaeter doch noch - getippte Filterbuchstaben nach "Menue geschlossen", uebersprungene Listeneintraege nach dem Loslassen der Pfeiltaste, Gildenchat eine Minute zu spaet. Behoben. Menue: Oeffnete sich das Menue direkt in ein Fenster oder eine Liste (Tasche, Haendler, Umschalt+F10), kam nach dem Inhalt noch "Ziel Menue" hinterher. Behoben. Echte Windows-Stimme: sprach ein anderes Addon waehrend des Tippens, konnte ein Buchstabe nach "abgebrochen" nachkommen. Behoben. Drehen: schneller, genauer, selbst eingemessen Einfach: "Zum Beacon drehen" (T) und die beiden anderen Drehbefehle wurden anhand von Messungen im Spiel ueberarbeitet. Drei Dinge aendern sich spuerbar. Erstens: grosse Drehungen kommen mit einem Druck an. Bisher schaffte ein Druck hoechstens etwa 88 Grad, egal wie weit es gehen sollte - das war ein unbemerkter Fehler seit v43.2. Zweitens: die Drehung ist schneller, eine Kehrtwende dauert nur noch gut eine Zehntelsekunde. Drittens: bist du schon auf 3 Grad genau ausgerichtet, passiert bei einem weiteren Druck nichts mehr. Frueher drehte jeder Druck mindestens 5 Grad, darum pendelte man um den Beacon-Ping herum und kam nie zur Ruhe. Im Wasser spart das ausserdem unnoetige Tauchstupser. Sku lernt dabei deinen Rechner: nach jeder Drehung wird gemessen, wie weit der Charakter wirklich gedreht hat, und die naechste Drehung wird danach berechnet. Bei hoher Bildrate dreht Sku von selbst flotter, bei niedriger langsamer und dafuer genau. Nach dem Update sind die ersten paar Drehungen Lernschritte und duerfen danebenliegen. Sehr grosse Drehungen nahe 180 Grad landen auf etwa 5 Grad genau; ab und zu verfeinert ein zweiter Druck. Ein Druck waehrend einer laufenden Drehung wird wie bisher verworfen. Technisch: GameWorldObjects:TurnToWorldPosition (SkuCore/gameWorldObjects.lua). Gemessen 2026-09-21: cameraYawMoveSpeed wirkt nur bis 360 - Werte darueber drehen nicht schneller (376, 453 und 731 ergaben in 0.25 s alle ~88 Grad). Die Regel max(360, Winkel/0.25) aus v43.2 deckelte darum jeden Druck still bei ~88 Grad. Mehr Tempo kommt nur ueber das Argument von MoveViewLeftStart/MoveViewRightStart, das die CVar multipliziert (Technik aus WowVision). Zwei Gaenge: Gang 1 = CVar allein bis 360 Grad/s, Gang 2 = CVar 360 mal Faktor bis 1440 Grad/s. Modell je Gang: gedreht = k * Sollgeschwindigkeit * (Timerdauer + L); k ab der ersten Messung aus dem Median, ab 8 Messungen mit streuenden Dauern eine Ausgleichsgerade fuer k und L. Geschwindigkeit nach Bildrate: die Stopp-Streuung ist eine halbe Framedauer mal Tempo, erlaubt sind 3 Grad bzw. 6 Prozent des Winkels; nie langsamer als Winkel/0.25 s; gebremst, wenn der Timer kuerzer als 2 Frames waere. Multipliziert der Faktor auf einem Client nicht, legt Sku Gang 2 dauerhaft still. Messwerte accountweit in SkuOptions.db.global.SkuCore.turnCal. Die Sperre gegen Folgedruecke deckt jetzt auch die Nachmess-Wartezeit ab (ein Druck in dieser Luecke rechnete mit der alten Blickrichtung). Jede Drehung schreibt eine Zeile "TurnCal" ins Debug-Log. /skuturn zeigt den Stand, /skuturn reset verwirft die Messwerte, /skuturn legacy schaltet auf das alte Verhalten. Gebaut, getestet und wieder ausgebaut: eine Nachkorrektur im selben Druck - die Kamera hat Schwung und gleitet nach dem Stopp weiter, ein Befehl in dieses Gleiten kostete bis zu 35 Grad. Schwimmen und Fliegen: Neigungssperre greift auch im Kampf Einfach: Die automatische Neigungssperre, die dich beim Schwimmen und Fliegen waagerecht haelt, wartete bisher das Ende des Kampfes ab. Wer kaempfend ins Wasser ging, war solange ungeschuetzt, und jede Beacon-Drehung drueckte ihn tiefer. Die Sperre greift jetzt sofort. Auch die Taste Strg+Umschalt+N geht jetzt im Kampf. Technisch: Die InCombatLockdown-Pruefungen in SkuCore:TogglePitchLock und im Automatik- Tick (SkuCore/Core.lua) beruhten auf der ungeprueften Annahme, pitchlimit sei im Kampf geschuetzt. Es ist ein Konsolenbefehl und im Kampf setzbar (getestet 2026-09-21). Im Log desselben Tages lagen zwischen Schwimmbeginn und Sperre 6 Sekunden mit drei ungeschuetzten Drehungen. Tooltip von Set-Gegenstaenden: Ruestungsart wurde doppelt vorgelesen Einfach: Gehoert ein Gegenstand zu einem deiner gespeicherten Ausruestungssets, fuegt Sku im Tooltip die Zeile "Gehoert zu Set" ein. Bei genau diesen Gegenstaenden war danach die Ruestungsart zweimal zu hoeren, zum Beispiel "Seelengebunden, Stoff, Kopf, Stoff". Das erste "Stoff" war ein Rest und gehoerte dort nicht hin. Jetzt kommt es nur noch einmal, hinter dem Platz: "Seelengebunden, Kopf, Stoff". Bei Waffen betraf das genauso die Waffenart und das Tempo. Gegenstaende ohne Set waren nie betroffen. Technisch: tInsertSetLineAtTop (SkuCore/equipmentSets.lua) schiebt alle Tooltip-Zeilen ab Zeile 2 um eine nach unten. Die rechte Spalte wurde dabei nur geschrieben, wenn die Quellzeile eine hatte. Die Zeile, aus der "Kopf | Stoff" wegwanderte, bekam links "Seelengebunden" und behielt rechts ihr altes "Stoff". TooltipLines_helper liest jede FontString-Region einzeln, darum war der Rest hoerbar. Die rechte Spalte wird jetzt immer geschrieben: gesetzt und gezeigt, oder geleert und versteckt; ebenso in Zeile 2. Der Fehler steckte seit v42.00 im Code und fiel erst mit gespeicherten Sets auf. Sprachausgabe: ueberholte Zeilen kamen verspaetet doch noch (echte Windows-Stimmen) Einfach: Betrifft nur Spieler, die Sku ueber eine echte Windows-Stimme sprechen lassen, nicht ueber die NVDA-Bruecke. Dort konnte eine Zeile, die Sku laengst durch eine neuere ersetzt hatte, im Spiel haengen bleiben und viel spaeter doch noch gesprochen werden: Wer im Menue schnell einen Filter tippte, hoerte "g r" oder "g r e i f" erst nach "Menue geschlossen". Wer die Pfeiltaste hielt, hoerte nach dem letzten Eintrag noch zwei, drei uebersprungene. Und Chatzeilen, die waehrend des Blaetterns eintrafen, kamen bis zu 70 Sekunden zu spaet und ausser der Reihe. In einem eingeschickten Log waren das 24 von 524 Ansagen in einer halben Stunde. Das ist behoben: was Sku ersetzt oder abgebrochen hat, bleibt stumm. An den Regeln, was was unterbrechen darf, aendert sich nichts. Auch das Mischen bleibt: schiebt sich eine wichtige Ansage in eine Reihe wartender Zeilen (Chat, Statusmeldungen), spricht sie zuerst, danach geht die Reihe weiter, die aelteste Zeile zuerst. Nur was dabei aelter als 30 Sekunden geworden ist, wird verworfen. Technisch: Libs/SkuVoice-1.0. C_VoiceChat.StopSpeakingText beendet nur die Aeusserung, die gerade SPIELT. Eine uebergebene, aber noch nicht gestartete erreicht es nicht, und alles, was uebergeben wird, waehrend eine andere noch im Client ist, wird dort geparkt und startet erst beim naechsten natuerlichen PLAYBACK_FINISHED - egal wie viele Stopps dazwischen liegen. Neu: ein gemeinsames Tor (mClientGate) fuer ALLE Uebergaben. Sku uebergibt dem Client hoechstens EINE Aeusserung; die naechste Zeile wartet in Skus eigener Warteschlange auf FINISHED/FAILED mit passender ID, wo queuereset, EndScope und CancelBttsOutput sie noch erreichen. Weil die Zeilen jetzt bei Sku warten, musste die queuereset-Regel ausgesprochen werden, die bisher der Client nebenbei erledigte: eine wartende Overwrite-Zeile ist ueberholt und faellt weg (mSkuVoiceQueueBTTS_Overwrite); eine wartende Zeile ohne queuereset wird hinter die neue Overwrite-Zeile gestellt, solange sie juenger als tBttsKeptMaxAge (30 s) ist. Alle fuenf Stopp-Stellen laufen ueber BttsStop: hat die Aeusserung im Client noch nicht gestartet, wird der Stopp vorgemerkt und 0.1 s nach ihrem STARTED aus OnUpdate zugestellt - nie aus dem STARTED-Handler selbst: ein StopSpeakingText von dort legte im Test die gesamte Sprachausgabe des Clients bis zum Neustart lahm (das alte Kill-Fenster tat genau das). Das ersetzt das Kill-Fenster aus v43.5 (dieselbe Idee mit geschaetzter Zeitspanne, nur an zwei Stellen) und das eigene Tor der Tipp-Echo-Spur. Sicherungen: 0.5 s ohne STARTED gibt das Tor frei (und schickt einen vorgemerkten Stopp trotzdem), nach drei Uebergaben ohne jedes STARTED schaltet das Tor ab, bis wieder eines kommt. Auf der NVDA-Bruecke kommen STARTED und FINISHED im Uebergabe-Frame, das Tor ist dort nie geschlossen - Verhalten unveraendert. Geprueft mit einem Offline-Nachbau des Clients (dev/rework-docs/voice-harness): alter Stand 27-33 verspaetete Aeusserungen in 3 Minuten Zufallslast, neuer Stand 0; Bruecken-Modell alt und neu identisch. Im Log: "stop deferred (handover not started)", "deferred stop fires", "client gate ttl", "queuereset kept", "STALE-DROP". Folgefehler, im selben Zug behoben: die Taste "Audio Ausgabe beenden" (Strg+V) brach nur noch die gerade gesprochene Zeile ab, die wartenden liefen danach weiter - man musste je Zeile einmal druecken. Frueher lag der ganze Schwall schon im Client, und der eine Stopp traf alles; seit dem Tor warten die Zeilen bei Sku, und StopOutputEmptyQueue leerte diese Warteschlange nie. StopOutputEmptyQueue(true, true) ruft jetzt CancelBttsOutput: wartende Zeilen und wartende Tippzeichen weg, dann der Stopp. Die Aufrufer mit (true, nil) bleiben, wie sie sind - dort sollen wartende Chatzeilen ueberleben. Harness-Szenario "stopkey": alter Stand vier hoerbare Zeilen, neuer Stand eine (abgeschnitten). Menue: "Ziel Menue" wurde nach dem Inhalt nachgesprochen Einfach: Oeffnet sich das Menue nicht an der Wurzel, sondern gleich an einer bestimmten Stelle - beim Oeffnen einer Tasche, eines Haendlers oder Briefkastens, bei Umschalt+F9 und Umschalt+F10, bei den Schnellwahltasten -, dann war nach dem eigentlichen Inhalt noch "Ziel Menue" zu hoeren, der erste Eintrag der Menuewurzel. Also etwa "Tasche 1, Ziel Menue". Das ist behoben: du hoerst nur noch, wo du gelandet bist. "Menue geoeffnet" entfaellt bei diesen Oeffnungen; es wurde ohnehin sofort abgeschnitten, und der Oeffnen-Ton bleibt. Das normale Oeffnen des Menues ist unveraendert: "Menue geoeffnet", dann "Ziel Menue". Technisch: SkuOptions:SlashFunc (SkuZOptions/Core.lua) oeffnet ein geschlossenes Menue ueber den OnClick von OnSkuOptionsMain und laeuft danach den Pfad ab. Der Oeffnen-Zweig sprach "Menue geoeffnet" als Overwrite und stellte Menu[1].name als wartende Zeile dahinter. Die Ansage des Pfadlaufs setzte ein queuereset, und seit dem Client-Tor dieser Version behaelt queuereset wartende Zeilen ohne Overwrite hinter der neuen Zeile - gedacht fuer Chat, hier traf es den Wurzeleintrag (Log: "queuereset kept 1 waiting line(s)"). Behoben an der Quelle statt durch Unterdruecken: mit einem Pfad (mindestens zwei Felder) setzt SlashFunc SkuOptions.tOpeningForPathWalk um den Oeffnen-Aufruf, der Oeffnen-Zweig spricht dann nichts. Das Flag wird direkt nach dem Aufruf geloescht, auch bei einem Fehler (pcall, Fehler wird weitergereicht). Findet der Pfad nichts und das Menue steht an der Wurzel, holt SlashFunc die Ansage nach und schreibt "menu: path walk found nothing" ins Debug-Log. Zwischenstationen des Pfads waren schon vorher stumm. Tastaturecho mit einer echten Windows-Stimme: die lange Pause zwischen den Buchstaben ist weg Einfach: Wer Sku mit einer echten Windows-Stimme nutzt (nicht mit der NVDA-Bruecke), hoerte beim Tippen im Chat nach jedem Buchstaben eine Pause von einer halben bis ganzen Sekunde - etwa ein Buchstabe pro Sekunde, egal wie schnell die Stimme eingestellt war. Eine langsamere Stimme machte nur den Buchstaben laenger, die Pause blieb gleich. Diese Pause ist jetzt weg, die Buchstaben folgen dicht aufeinander. Es wird weiterhin jeder Buchstabe gesprochen, auch doppelte, und nach Escape kommt kein Buchstabe mehr nach. Dieselbe Pause steckte auch zwischen Zeilen, die hintereinander warten (Teile eines Questtexts, mehrere Chatzeilen); dort faellt sie kaum auf, ist aber ebenfalls verkuerzt. Auf der NVDA-Bruecke aendert sich nichts. Technisch: Der Client meldet VOICE_CHAT_TTS_PLAYBACK_FINISHED fest 0.5 bis 1 s NACH dem Ende des Tons (Bookmark "End") und startet vorher nichts Neues. Frueher uebergeben hilft nicht (v43.5e: die Aeusserung wird nur geparkt und ist dann nicht mehr abbrechbar). Was den Client sofort freigibt, ist ein Stopp. Neu in Libs/SkuVoice-1.0: kam fuer unsere Aeusserung erst "Start" und dann "End" und wartet etwas (Echo-Spur oder Queue), schickt OnUpdate nach tTailCutDelay (0.03 s) ein StopSpeakingText und uebergibt nach tTailCutHold (0.06 s). Nie aus dem Bookmark-Handler. Ein "End" vor "Start" (kommt bei der ersten Aeusserung nach einem Stopp vor) zaehlt nicht. Wartet nichts, endet die Zeile wie bisher von selbst. Der Schnitt setzt die Bruecken-Marke nicht, sperrt den "#queue > 1"-Bypass einmal und raeumt den Dubletten-Eintrag selbst ab (eine gestoppte Aeusserung meldet kein FINISHED). Gemessen im Nachbau: Buchstabentakt 1.15 s -> 0.73 s. Zum Probieren, nur fuer die Sitzung: /skudebug tts tail , /skudebug tts tail off. Im Log: "tail cut -> StopSpeakingText". Sprache anderer Addons brachte das Tastaturecho durcheinander Einfach: Sprach ein anderes Addon (oder ein /run-Befehl) ueber die Sprachausgabe des Spiels, waehrend du getippt hast, konnte danach ein Buchstabe nach "abgebrochen" nachkommen, also nach dem Schliessen des Chatfelds. Nur mit einer echten Windows-Stimme. Das ist behoben: solange fremde Sprache laeuft, wartet Sku mit seinen Buchstaben und Chatzeilen; schliesst du das Feld, werden die wartenden Buchstaben verworfen. Ansagen, die ohnehin alles unterbrechen (Menue, "abgebrochen", Prioritaetszeilen), unterbrechen auch die fremde Sprache wie bisher sofort. Technisch: Das Client-Tor kannte nur Skus eigene Uebergaben. Eine fremde Aeusserung (Mitschnitt: id 403, geparkt, 11 s spaeter unter dem ersten Buchstaben gestartet) liess den naechsten Buchstaben ohne STARTED stehen, die 0.5-s-TTL gab ihn auf, ein zweiter ging in den Client und uebernahm das STARTED des ersten. Neu (mForeign, tMaxSeenId, tClientGateFreedAt): ein STARTED, auf das niemand wartet, oder eines mit einer id unter der hoechsten vor unserer Uebergabe gesehenen, ist fremd - wird nie als unsere id uebernommen, und solange es laeuft, wird nichts uebergeben (Stille-Grenze 8 s; unsere eigenen Stopps beenden es). Auf der Bruecke sind alle ids 0, "aelter" ist deshalb echt-kleiner und greift dort nie. Im Frame, in dem eine unserer Aeusserungen FINISHED meldet, wird nichts uebergeben: eine geparkte fremde startet genau auf dieses FINISHED und muss zuerst gesehen werden. Harness-Szenario "foreign": alter Stand vier Buchstaben nach "abgebrochen", neuer Stand keiner. Im Log: "BTTS foreign utterance", "BTTS foreign cleared". Einfuegen in ein Eingabefeld: "Eingefuegt" statt Buchstabensalat Einfach: Wer mit Strg+V Text in die Chatzeile oder in ein Eingabefeld von Sku einfuegte, bekam den ganzen eingefuegten Text Buchstabe fuer Buchstabe vorgelesen. Jetzt sagt Sku einmal "Eingefuegt". Den Inhalt des Feldes liest du wie gewohnt mit Pfeil hoch oder Pfeil runter. Normales Tippen ist unveraendert, auch schnelles. Fuegst du nur ein oder zwei Zeichen ein, werden diese weiterhin als Zeichen gesprochen. Technisch: Ein Einfuegen liefert die Zwischenablage als einzelne OnChar-Aufrufe, alle im selben Frame. tSpeakTypedChar (SkuZOptions/Core.lua) zaehlt die Zeichen je Frame (GetTime() ist innerhalb eines Frames konstant): ab dem dritten gilt die Folge als Einfuegen - CancelEcho wirft die schon wartenden Zeichen weg (uebergeben ist im selben Frame noch keines, die Pumpe laeuft im OnUpdate), dann einmal SpeakEcho("Eingefuegt"), alle weiteren Zeichen des Frames werden ignoriert. Schwelle 3, weil zwei Anschlaege bei niedriger Bildrate in einen Frame fallen koennen. Gilt fuer AttachInputEcho (Chat) und das Sku-Eingabefeld. Im Log: "inputEcho paste erkannt". ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.6 Ueberblick Aenderungen Berufefenster: Die Rezeptliste zeigt jetzt den ganzen Beruf mit auf- und zuklappbaren Kategorien statt einer Bildlaufliste mit 8 Eintraegen. Berufefenster: Bild auf und Bild ab springen von Kategorie zu Kategorie. Berufefenster: Der Filter "Ressourcen vorhanden" ist ein normaler Schalter und fuehrt nicht mehr auf leere Seiten. Fehlerbehebungen Chat: "absender anfluestern" und "nachricht an kanal senden" im Zeilenmenue (Strg+Enter auf einer Chatzeile) taten auf manchen Rechnern gar nichts - die Chatzeile oeffnete sich nicht. Fluestern aus dem Zielmenue und aus dem Dungeonbrowser tat auf denselben Rechnern ebenfalls nichts. Tasten: Wer einmal v43 gestartet, dann wieder v42 benutzt und dort Umschalt+F9 bis F12 neu belegt hatte, stand in v43 ohne Taste fuer Wegpunktliste, Routenziele, Aktionsleisten und "Route beenden" da - die Tasten werden jetzt nachtraeglich uebernommen. Classic Era: Die Liste der nicht unterbrechbaren Zauber brach beim Laden mit einem Fehler ab; sie laedt jetzt auf jedem Client. Berufefenster: Im Rezept-Tooltip (Umschalt+Pfeil runter) fehlte bei manchen Materialien der Name, man hoerte nur Zahlen wie "0 2". Chat: "absender anfluestern" oeffnete keine Chatzeile Einfach: Wer im Chat mit Strg+Enter das Zeilenmenue oeffnete und dort "absender anfluestern" waehlte, bekam auf manchen Rechnern nichts: kein Ton, keine Chatzeile mit dem Namen des Absenders. Dasselbe galt fuer "nachricht an kanal senden" und "gegenstandslink an kanal senden". "Chatzeile kopieren" und "Absendername kopieren" gingen weiter, weil sie einen anderen Weg nehmen. Alle drei Eintraege oeffnen die Chatzeile jetzt wieder, und der Zielkanal wird wie gewohnt angesagt ("An Kai"). Technisch: SkuChat:SetEditboxToCustom rief den globalen ChatEdit_UpdateHeader auf und zeigte die Editbox erst DANACH. Dieser Name ist auf dem 2.5.6-Client keine echte Funktion mehr, sondern ein Alias aus Blizzard_DeprecatedChatInfo (Deprecated_ChatFrame.lua), und die ganze Datei steigt sofort aus, wenn die CVar loadDeprecationFallbacks aus ist. Dann ist der Name nil, der Aufruf wirft einen Fehler, und Show() und SetFocus() laufen nie. Neu: SkuChat:UpdateEditboxHeader ruft die echte Frame-Methode ChatFrame1EditBox:UpdateHeader() und nimmt den globalen Namen nur noch als Rueckfall. SkuChat_CanAddChannel liest Constants.ChatFrameConstants.MaxChatChannels statt des veralteten MAX_WOW_CHAT_CHANNELS. Fluestern aus dem Zielmenue und dem Dungeonbrowser tat nichts Einfach: "Fluestern" im Menue zum aktuellen Ziel und beim Gruppenleiter im Dungeonbrowser oeffnete auf denselben Rechnern keine Chatzeile - ohne jede Meldung. Beides geht wieder. Technisch: Beide Stellen riefen ChatFrame_OpenChat hinter einer "wenn vorhanden"-Pruefung. Auch das ist nur ein Alias aus Blizzard_DeprecatedChatInfo; fehlt er, passierte stillschweigend nichts. Jetzt wird ChatFrameUtil.OpenChat benutzt, der alte Name nur noch als Rueckfall (SkuMob/Options.lua, SkuCore/dungeonBrowser.lua). Tasten: Umschalt+F9 bis F12 fuehrten nach einem Wechsel v43 - v42 - v43 ins Leere Einfach: Betroffen war, wer v43 einmal gestartet hatte, danach zu v42 zurueckging und dort die Schnellzugriffe 1 bis 4 wieder auf Umschalt+F9 bis F12 legte. Beim naechsten Start von v43 hatten die festen Aktionen (Wegpunktliste, Routenziele, Aktionsleisten, Route oder Wegpunkt beenden) keine Taste mehr, und die vier Tasten riefen stattdessen alte Schnellzugriff-Pfade auf. Einer davon zeigte auf einen Menueeintrag, den es nicht mehr gibt: das Menue ging auf, der Cursor blieb auf "Ziel Menue" stehen - es sah genauso aus wie der fruehere Haenger "Wegpunkte werden noch geladen". Sku erkennt diesen Zustand jetzt beim Start und legt die vier Tasten von selbst auf die festen Aktionen um. Eigene Tasten auf den Schnellzugriffen bleiben unangetastet. Danke an Kai fuer die genaue Analyse (Issue 7). Technisch: tMigrateQuickKeys (SkuZOptions/SkuKeyBinds.lua) wertete allein das Vorhandensein von SKU_KEY_NAVWAYPOINTSQUICK als "schon migriert". v43 hatte den Eintrag beim ersten Start angelegt, v42 leerte ihn wieder, als es die Tasten fuer MENUQUICK1 bis 4 vergab - vorhanden, aber leer. Neu ist ein Rettungsdurchlauf: sind NAVWAYPOINTSQUICK, NAVROUTEDESTINATIONSQUICK und ACTIONBARSOPEN alle drei leer UND traegt mindestens ein MENUQUICK1 bis 4 eine der v42-Standardtasten SHIFT-F9 bis SHIFT-F12, laeuft die Uebernahme noch einmal - in diesem Durchlauf nur fuer die Plaetze, die eine solche Standardtaste tragen. Wer die neuen Tasten absichtlich geleert hat, behaelt so jede eigene Schnellzugriff-Taste. Der Durchlauf ist einmalig: danach sind die neuen Eintraege nicht mehr leer. Classic Era: Liste der nicht unterbrechbaren Zauber lud nicht Einfach: Auf Classic Era brach eine Datendatei von Sku beim Anmelden mit einem Lua-Fehler ab. Dadurch fehlte die Liste, mit der "Nur unterbrechbare Zauber ansagen" arbeitet. Die Datei laedt jetzt auf jedem Client vollstaendig. Auf TBC Anniversary aendert sich nichts. Technisch: SkuDB/uninterruptibleCasts.lua baut seine Namensschluessel mit GetSpellInfo(id) direkt im Tabellenkonstruktor. Die TBC-Zauber 29121 (Bogenschiessen) und 33808 (Schusswaffe abfeuern) kennt Era nicht, GetSpellInfo liefert nil, und "[nil] = true" wirft "table index is nil" - der Konstruktor bricht ab, SkuDB.uninterruptibleCasts.spells und .npcSpells bleiben nil. Die Datei benutzt jetzt einen lokalen Wrapper, der fuer eine unbekannte ID einen Platzhalter liefert, den kein Zaubername je treffen kann. Der Eintrag ist auf diesem Client wirkungslos, die Konstruktoren bleiben zeilengleich mit der Upstream-Quelle (ClassicCastbars), und dasselbe schuetzt die npcSpells-Zeilen, wo ein nil einen Verkettungsfehler ausgeloest haette. Berufefenster ueberarbeitet: Kategorien zum Auf- und Zuklappen statt 8 Eintraege pro Seite Einfach: Die Berufefenster (alle Herstellungsberufe, Verzauberkunst und die Tierausbildung) verhalten sich jetzt einheitlich. Bisher zeigte das Menue immer nur die 8 Zeilen, die das Blizzard-Fenster gerade anzeigt, dazu "Hoch blaettern" und "Runter blaettern". Jetzt steht der ganze Beruf in einer Liste: jede Kategorie als Ueberschrift, darunter ihre Rezepte. Enter auf einer Kategorie klappt sie zu oder auf, der neue Zustand wird angesagt, und Sku merkt ihn sich pro Charakter und Beruf. Bild ab und Bild auf springen zur naechsten bzw. vorigen Kategorie. "Ausgewaehlt" und die Herstellen-Knoepfe stehen weiter am Ende des Fensters. Gibt es zwei Kategorien mit demselben Namen (Schneiderei hat "Stoff" zweimal), heisst die zweite "Stoff 2". Der Filter "Ressourcen vorhanden" ist jetzt ein normaler Schalter: Enter schaltet um, der Cursor bleibt stehen. Mit Filter verschwinden Rezepte ohne Material und Kategorien, in denen nichts herstellbar ist. Man landet nicht mehr auf leeren Seiten ohne Ausweg, und in der Verzauberkunst gibt es keine Seiten mehr, auf denen nur die Ueberschriften uebrig sind. Die Liste aktualisiert sich nach dem Herstellen von selbst und spricht nur, wenn der Eintrag unter dem Cursor verschwunden ist. Technisch: Build_TradeSkillFrame und Build_CraftFrame (SkuCore/LocalMenu.lua) lesen die Liste aus GetTradeSkillInfo bzw. GetCraftInfo statt die Zeilen TradeSkillSkill1-8 und Craft1-8 abzulesen; ausgewaehlt wird ueber TradeSkillFrame_SetSelection bzw. CraftFrame_SetSelection. Blizzards TradeSkillOnlyShowMakeable wird nicht mehr benutzt: es setzt den Bildlauf nur zurueck, wenn der AUSWAHL-Index aus der verkuerzten Liste faellt - sonst stand der Offset hinter dem Listenende, alle 8 Zeilen und die Bildlaufleiste waren weg. Der Filter prueft jetzt in beiden Fenstern numAvailable; der alte Zwischenspeicher resFilterApplied (pro Beruf, obwohl Blizzards Schalter global ist) entfaellt. Neu: TRADE_SKILL_UPDATE und CRAFT_UPDATE bauen das Menue neu auf, entprellt und nur wenn sich die gezeigte Liste geaendert hat (SkuCore:RefreshProfessionMenu). Der Listen-Builder kennt zwei neue Felder: "toggle" (ein MakeToggleNode-Schalter in einem Fenster) und "isSectionHeader" (Sprungziel fuer Bild auf/ab). Der Filterzustand liegt jetzt unter dem Berufsnamen statt unter dem Fenstertitel; ein alter Wert wird uebernommen. Berufefenster: Rezept-Tooltip nannte manche Materialien ohne Namen Einfach: Im Tooltip eines Rezepts (Umschalt+Pfeil runter) stand bei einzelnen Materialien nur die Anzahl, etwa "0 2" statt "Bleiche 0 von 2". Betroffen waren Gegenstaende, die der Spielclient noch nie gesehen hat - meist reine Haendlerware wie Bleiche, Farbstoffe oder Flussmittel. Stoffe und Leder kennt der Client fast immer schon, deshalb sah es zufaellig aus. Jetzt sagt Sku an dieser Stelle "wird abgerufen" und holt den Namen im Hintergrund. Tooltip schliessen und noch einmal Umschalt+Pfeil runter druecken: dann steht der Name da. Das passiert pro Gegenstand nur einmal, danach kennt ihn der Client dauerhaft. Technisch: GetTradeSkillReagentInfo bzw. GetCraftReagentInfo liefern fuer einen Gegenstand, der nicht im Item-Cache liegt, keinen Namen, und der Reagenzien-Link traegt dann leere Klammern "[]". Der Rueckfall schrieb ein "?", das die Sprachausgabe nicht spricht. Dazu wurde der fertige Text in textFull des Menueknotens abgelegt und nie neu gebaut, der Fehler blieb also auch nach dem Nachladen. Neu (SkuZOptions/Core.lua, SHIFT-DOWN): fehlt der Name, wird die Item-ID aus dem Link gelesen und GetItemInfo(id) gerufen, was den Gegenstand zugleich beim Server anfordert. Ein unvollstaendiger Tooltip wird mit skuRecipeIncomplete markiert und beim naechsten Tastendruck neu gebaut. Jeder Fall schreibt eine Zeile "recipeTooltip" ins Debug-Log (Rezeptindex, Material, Link). ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.5-tools - Installer 5.2 und Anmelde-Tool 3.4, keine neue Addon-Version Ueberblick Neu Anmelde-Tool 3.4: Blizzards Sozialvertrag wird erkannt, zu Ende gescrollt und akzeptiert - bisher blieb ein neuer blinder Spieler davor haengen. Anmelde-Tool 3.4: die PvP-Warnung beim Erstellen eines Charakters auf einem PvP-Realm wird vorgelesen und mit Enter oder Escape beantwortet. Aenderungen Anmelde-Tool 3.4: Hardcore- und PvP-Warnungen werden bei jeder Bildschirmaufloesung und Fenstergroesse gefunden, nicht nur auf grossen Bildschirmen. Anmelde-Tool 3.4: jede Stimme wird vor der Uebernahme unhoerbar ausprobiert - eine kaputte Stimme kann das Tool nicht mehr stumm machen. Installer 5.2: das Log-Buendel enthaelt jetzt eine Liste aller Windows-Stimmen (voices.txt). Installer 5.2: Massnahmen gegen Fehlalarme von Windows Defender - die Installer-Datei nennt Produkt und Autor, und die mitgelieferte NVDA-Bruecken-Datei kommt ohne uebrig gebliebene Entwickler-Signatur. Fehlerbehebungen Anmelde-Tool 3.4: "Stimme auswaehlen" war auf manchen Rechnern leer, und die Ersteinrichtung kam dort nie weiter. Anmelde-Tool 3.4: Blizzards Sozialvertrag wird automatisch akzeptiert Einfach: Neue Accounts - und alle anderen, sobald Blizzard den Text aendert - bekommen auf der Charakterauswahl einen "Sozialvertrag" angezeigt. Das Fenster schluckt jede Taste, "Akzeptieren" ist gesperrt, bis der Text mit der Maus zu Ende gescrollt wurde, und "Ablehnen" beendet das Spiel. Das Tool blieb davor stumm und meldete hoechstens "Unbekannter Bildschirm". Jetzt sagt es "Blizzards Sozialvertrag ist offen. Er wird akzeptiert, bitte warten.", scrollt den Text zu Ende, drueckt Akzeptieren, prueft, ob das Fenster weg ist, und baut danach wie gewohnt die Charakterliste auf. Das gilt auch, wenn der Vertrag mitten in der Sitzung wieder auftaucht. Klappt es nicht, sagt das Tool, was eine sehende Person einmal tun muss, und versucht es nach einer Minute erneut. Ablehnen wird nie gedrueckt. Technisch: Der Dialog ist SocialContractFrame (Blizzard_GlueXML\SocialContract.xml/.lua) und wird vom SERVER ausgeloest (C_SocialContractGlue.GetShouldShowSocialContract -> SOCIAL_CONTRACT_STATUS_UPDATE); es gibt keine CVar und keine Einstellung dafuer, man kann ihn also weder hervorrufen noch vorab beantworten. Der alte Code konnte auf dem Anniversary-Client nicht greifen: die Helper-Pruefung verlangt das abgedunkelte gelbe Logo, das der BC-Glue nicht hat, und ihr dritter Messpunkt liegt mitten im Vertragstext - Pruefung falsch, Bildschirm "unknown", das Tool kam nie in den Login-Modus; der Klick-Teil war ein blinder Sweep aus 34 Klicks. Neu sind acht Sc*-Messpunkte in data.ini (aus dem XML abgeleitet: Rahmen 510x632, Buttons bei ui y 706..728, KEIN DefaultScaleFrame) sowie IsSocialContract, AcceptContract und HandleSocialContract in flows.ahk und zwei CheckMode-Zweige in menu.ahk - ohne neu gebauten Helper. Geprueft mit /validate, 0 Fehlalarmen auf allen Referenz-Screenshots und Treffern auf synthetischen Vertragsbildern in drei Aufloesungen. Am echten Dialog noch ungetestet, weil er sich nicht auf Bestellung erzeugen laesst; jeder Versuch schreibt seine Messwerte als "SocialContract:"-Zeilen nach log.txt. Anmelde-Tool 3.4: Hardcore- und PvP-Warnungen bei jeder Aufloesung, PvP-Erstellungswarnung neu Einfach: Die Hardcore-Warnung in der Realmliste, die Hardcore-Regeln beim Erstellen eines Charakters und die PvP-Warnungen sind Fenster, die Blizzard in echten Bildschirmpixeln gleich gross haelt. Ihre Lage haengt deshalb von der Aufloesung ab, und die festen Messpunkte des Tools stimmten nur auf grossen Bildschirmen (ab 1200 Pixel Hoehe). Auf einem ueblichen 1080p-Bildschirm oder im kleinen Fenster waere das Tool vor den Hardcore-Regeln stumm geblieben. Jetzt sucht es diese Fenster selbst und findet sie bei jeder Aufloesung. Neu dabei ist die PvP-Warnung beim Erstellen eines Charakters auf einem PvP-Realm: sie wird vorgelesen, Enter stimmt zu, Escape lehnt ab. Die PvP-Warnung in der Realmliste sieht genauso aus wie die Hardcore-Warnung und wurde deshalb schon bisher vorgelesen. Technisch: HardcorePopUpFrame (240 und 580 hoch) und RealmWarningPopUpFrame (240 und 360 hoch) erben von DefaultScaleFrame und werden per GetDefaultScale() skaliert - eine Client-Funktion ohne Lua-Quelltext. Im Spiel per /wdeval gemessen: 0,64 auf 2880x1800, wo 768/Hoehe 0,43 waere; es gibt also eine Untergrenze, und bei 1080p waeren es vermutlich 0,71. Statt den Faktor anzunehmen, findet ihn GlueDialogScan (flows.ahk): beide Buttons liegen in allen vier Formen auf einer Geraden aus der Bildschirmmitte, nur der Abstand haengt vom Faktor ab. Ein Bildausschnitt (neue Klasse ScreenGrab in ui.ahk, 1000 Pixel in 16 ms), dann Faktor 0,60..1,25 je Hoehe: rot an drei Spalten, nicht rot in der Luecke und knapp ausserhalb, schwarz am Hintergrundpunkt. Die festen Messpunkte bleiben die erste Pruefung, der Scan die zweite. Klicks (GlueDialogClick) und OCR-Textbereiche (GlueDialogBand) folgen dem gefundenen Faktor. Geprueft mit einer Python-Portierung auf 66 synthetischen Dialogen (6 Aufloesungen, 3 Hoehen, 4 Faktoren): Hoehe immer richtig, Faktor auf 0,012 genau, 0 Fehlalarme. An echten Dialogen noch ungetestet; jeder Fund steht als "GlueDialog:"-Zeile mit Faktor in log.txt. Anmelde-Tool 3.4: leere Stimmenauswahl behoben, die Ersteinrichtung bleibt nicht mehr haengen Einfach: Auf manchen Rechnern kann Windows die Liste der installierten Stimmen nicht liefern, obwohl die Sprachausgabe selbst funktioniert - etwa nach einer unsauber entfernten oder nur halb installierten Fremdstimme. Seit 3.3 stuerzt das Tool dabei nicht mehr ab, aber "Stimme auswaehlen" war dann leer: Pfeil rechts tat nichts, und weil die Ersteinrichtung erst nach der Stimmenwahl zur Sprache weitergeht, kam man nie hindurch. Jetzt liest das Tool die Stimmen in diesem Fall selbst aus der Windows-Registrierung. Findet es auch so keine, steht dort der Eintrag "Keine Stimmen gefunden, Eingabe druecken, um die Systemstimme zu behalten" - Eingabe behaelt die Stimme, mit der das Tool gerade spricht, und die Einrichtung geht weiter. Technisch: Im Log-Buendel des Nutzers stand viermal "GetVoices FAILED, voice list empty: (0x80045039)" und danach "SwitchToSetup". Nicht ein einzelnes Token war unlesbar (der Fall von 3.3), sondern schon sap.GetVoices() bzw. .Count wirft SPERR_NO_MORE_ITEMS, waehrend sap.Voice.GetDescription() funktioniert. Neu: RegistryVoiceTokens() in sapi.ahk baut je Schluessel unter Speech\Voices\Tokens (HKLM und HKCU) ein SAPI.SpObjectToken per SetId - nur im Fehlerfall. Gelistet wird nur, was einen Namen und eine CLSID hat, denn ein kaputter Eintrag wirft hier nicht, GetDescription() liefert einfach "". AddVoiceNodes() in menu.ahk ersetzt die drei gleichen Schleifen und haengt bei leerer Liste den Ersatz-Eintrag an. Geprueft mit einem Testgeruest, das die echte sapi.ahk laedt und GetVoices genau diesen Fehler werfen laesst: dieselben Stimmen wie auf dem normalen Weg, alle setzbar, zwei absichtlich kaputte Eintraege uebersprungen. Der eigentliche Fehler liess sich nicht nachstellen; auf dem Rechner des Nutzers noch ungetestet. Anmelde-Tool 3.4: eine kaputte Stimme kann das Tool nicht mehr stumm machen Einfach: Eine Stimme, deren Programm entfernt wurde, deren Eintrag aber in Windows zurueckblieb, steht weiter in der Stimmenliste. Waehlte man sie, nahm Windows die Wahl ohne Fehler an - und das Tool war danach stumm, aus dem Hauptmenue heraus sogar dauerhaft, weil die Wahl gespeichert wird. Jetzt probiert das Tool jede Stimme vor der Uebernahme unhoerbar aus. Funktioniert sie nicht, bleibt alles, wie es war, und das Tool sagt "Diese Stimme funktioniert nicht, bitte eine andere waehlen". Auch beim Start wird eine gespeicherte Stimme, die nicht mehr spricht, nicht mehr gesetzt; es bleibt dann die Windows-Standardstimme. Technisch: Gemessen mit einer Registrierung mit Namen und CLSID, aber ohne Engine: sap.Voice := token wird angenommen, erst Speak wirft 0x80040154 (Klasse nicht registriert). VoiceWorks() in sapi.ahk spricht deshalb auf einem eigenen SpVoice in einen SpMemoryStream, 16 bis 31 ms, die laufende Stimme wird nie angefasst. SetSapiVoiceByName und SetToolVoiceByName geben jetzt Erfolg zurueck, VoiceSelectAction und ApplyToolVoice werten ihn aus. SAPI2SR ist ausgenommen: die Bruecke reicht Text unabhaengig vom Ausgabestrom an den Screenreader weiter, die Probe waere hoerbar. Eine Stimme, die laedt, aber nur Stille erzeugt, erkennt die Probe nicht. Installer 5.2: das Log-Buendel listet alle Windows-Stimmen auf Einfach: "Logs sammeln" im Installer legt jetzt zusaetzlich die Datei voices.txt ins Buendel. Sie nennt jede in Windows registrierte Stimme und ob das Programm dahinter noch vorhanden ist. Bei Stimmenproblemen im Anmelde-Tool oder im Spiel laesst sich damit sofort sehen, welcher Eintrag kaputt ist. Kommt mit dem Installer 5.2. Technisch: LogCollector.WriteVoiceRegistrations liest Speech\Voices\Tokens, Speech\Voices\TokenEnums und Speech_OneCore\Voices\Tokens in der 64- und der 32-Bit-Registry-Sicht (das Anmelde-Tool ist 64 Bit und sieht reine 32-Bit-Stimmen nicht) sowie in HKCU, dazu DefaultTokenId. Je Eintrag: Name, CLSID, die InprocServer32-DLL samt Pruefung, ob sie registriert ist und auf der Platte liegt, VoicePath/LangDataPath und die Attribute. Installer 5.2: Massnahmen gegen Fehlalarme von Windows Defender Einfach: Einige Spieler haben gemeldet, dass Windows Defender den frisch heruntergeladenen Installer als gefaehrlich entfernt hat. Der Installer ist nicht gefaehrlich; unser eigener Defender-Scan mit aktuellen Signaturen findet nichts. Zwei Dinge, die die Datei verdaechtiger aussehen liessen als noetig, sind behoben: Die Dateieigenschaften sagen jetzt, was die Datei ist und von wem sie kommt (Produkt "Sku Installer", Firma "Sku", Autor JeanStiletto, Link zum Projekt) statt leer zu sein, und eine Datei der mitgelieferten NVDA-Bruecke traegt keine Signatur mehr, die vom PC des Entwicklers stammte und auf jedem anderen Rechner nichts bedeutete. Ehrlich zur Grenze: Der Installer ist weiterhin nicht mit einem gekauften Zertifikat signiert. Jeder neue Build faengt deshalb ohne Download-Reputation an, und Defender kann ihn in den ersten Tagen trotzdem zurueckhalten. Wenn das passiert: Windows-Sicherheit oeffnen, Schutzverlauf, den Eintrag waehlen und die Datei zulassen oder wiederherstellen - und uns bitte den Namen der Erkennung schicken. Technisch: SkuInstaller.exe war und ist nicht Authenticode-signiert; release.ps1 hat keinen Signierschritt, signiert werden nur die Bruecken-DLLs, auf dem Rechner des Nutzers, durch sku-nvda-voice-sign.ps1. Eine unsignierte Exe hat nur Cloud-Reputation je Hash, und die v43.5-Exe war bei den Meldungen einen Tag alt mit neun Downloads. Der lokale Scan (Engine 1.1.26080.3, Signaturen 1.459.278.0) ist sauber fuer Exe, Bruecken-Payload und das mitgelieferte AutoHotkey - das Urteil kommt also aus Cloud/ML oder Verhaltenserkennung, nicht aus einer statischen Signatur. Geaendert: Company, Product, AssemblyTitle, Description, Authors und Copyright in SkuInstaller.csproj (bisher stand ueberall "SkuInstaller", Copyright leer). Und x86\sapi2sr_engine.dll in payload\sapi2sr-payload.zip war aus dem Program-Files-Ordner des Entwicklers zurueckkopiert worden und trug noch die Wegwerf-Signatur dieses Rechners (ueberall sonst "signiert von nicht vertrauenswuerdiger Wurzel"); jetzt liegt die nackte DLL bei, 123320 -> 115712 Bytes. Der Authenticode-PE-Hash schliesst die Signatur aus, beide Pins im Signierskript passen weiter (5A76A572... x64, 1281E2B9... x86), das Signieren auf dem Nutzerrechner ist unveraendert. dev\rework-docs\nvda-voice-signing\ strip_payload_signature.py erledigt das Entfernen beim naechsten Payload-Update. Nicht geaendert, und weiterhin das, was eine Verhaltenserkennung sieht: Start mit Adminrechten, eingebettete Programme, regsvr32 /s, ein verstecktes PowerShell, das ein Codesignatur-Zertifikat in den Root-Speicher des Rechners legt, Selbstaustausch. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.5 Ueberblick Fehlerbehebungen Questdatenbank: das Oeffnen von "Alle" (ebenso "Start in Zone" und "Quests in der Naehe") liess das Spiel sekundenlang einfrieren. Chat: nach dem Oeffnen der Chatzeile mit "/" wurde der alte Kanal angesagt (etwa "An Kai"), obwohl erst der Befehl danach den Kanal festlegt. Sprachausgabe: einzelne Zeilen blieben ueber die NVDA/SAPI-Bruecke zufaellig stumm (etwa ein Ausruestungsteil in der Liste), waehrend die Nachbarn gesprochen wurden. Quest: "Raenes Saeuberung" (Eisenknauf, Eschental) hatte kein Questziel; es fuehrt jetzt zur Rostigen Truhe der Faulenden Bruehschleimer. Sprachausgabe: getippte Zeichen und abgebrochene Ansagen kamen verspaetet nach - Buchstaben einer laengst geschlossenen Chatzeile tauchten Sekunden spaeter in einem anderen Menue auf. Anmelde-Tool 3.3: eine beschaedigte Windows-Stimme auf dem Rechner liess das Tool gleich nach der Versionsansage mit einem Fehlerfenster (GetVoices, 0x80045039) abbrechen. Sprachausgabe: schnelles Blaettern durch lange Eintraege las ueber die NVDA/SAPI-Bruecke erst den vorigen Eintrag zu Ende, bevor der gewaehlte kam. Questdatenbank: das Oeffnen der Questlisten liess das Spiel einfrieren Einfach: Wer unter Quest > Questdatenbank die Liste "Alle" oeffnete, bekam seit v43.2 einen Haenger von mehreren Sekunden. Die Liste oeffnet jetzt wieder sofort; die Eintraege einer Quest (Annahme, Ziel, Abgabe ...) werden erst gebaut, wenn man die Quest betritt. Gleiches gilt fuer "Start in Zone" und "Quests in der Naehe". Technisch: "Alle" baute fuer jede der mehreren tausend Quests der Datenbank sofort das komplette Untermenue (CreateQuestSubmenu). Seit v43.2 loest dessen Ziel-Zweig fuer Quests mit einem Ausloese-Ort (triggerEnd) den naechsten Routen-Wegpunkt geometrisch auf (GetTriggerEndWps) - ein kompletter Scan des Wegpunkt-Caches eines Kontinents - und seit v43.3 fuer jede solche Quest statt nur fuer die ohne andere Ziele. Ein Oeffnen kostete so rund 170 Kontinent-Scans in einem einzigen Frame. Die Quest-Eintraege sind jetzt dynamische Knoten mit eigenem BuildChildren, wie in "Aktuelle Quests" schon immer. Chat: falsche Kanalansage nach dem Oeffnen mit dem Schraegstrich Einfach: Wer zuletzt jemandem gefluestert hatte und die Chatzeile mit "/" oeffnete, hoerte "An Kai" - und nach "/g " gleich darauf "Gilde". Die erste Ansage war falsch: solange die Zeile mit einem Schraegstrich beginnt, geht nichts an diesen Kanal, erst der Befehl entscheidet. Die Ansage schweigt jetzt, solange ein Befehl in der Zeile steht, und sagt den Kanal, sobald er feststeht ("/g " wird zu "Gilde") oder der Schraegstrich wieder geloescht wird. Ein bewusster Wechsel auf "Sagen" ("/s ") wird jetzt ebenfalls gesagt, wenn Sagen nicht ohnehin der Standardkanal war. Beim Zurueckholen einer gesendeten Zeile (Pfeil hoch) entfaellt der Kanal-Vorspann, wenn die Zeile ein Befehl ist. Technisch: Blizzard zeigt in der Kopfzeile immer das Attribut chatType, und das ist beim Oeffnen der sticky-Kanal der zuletzt gesendeten Nachricht (auch Fluestern ist sticky, samt tellTarget). Die Schraegstrich-Taste ruft ChatFrameUtil.OpenChat("/"): dieselbe Kopfzeile plus ein "/" im Feld, gesetzt erst im naechsten OnUpdate (editBox.setText), die UpdateHeader-Aufrufe des Oeffnens laufen also noch mit leerem Feld. Ein Text, der mit "/" beginnt, geht nie an den Kanal der Kopfzeile: erst wenn ParseText den Befehl aufloest ("/g " beim Leerzeichen, "/w Name " hinter dem Namen), setzt Blizzard chatType neu, SetText(Rest) und dann UpdateHeader. Sku prueft jetzt an allen Ansage-Stellen (UpdateHeader-Haken, Fokus, verzoegertes Sprechen) den effektiven Text inklusive des ausstehenden setText (SkuChat:EditboxTextIsCommand); eine neue OnTextChanged-Kante deckt das Loeschen des Schraegstrichs ab, fuer das Blizzard kein UpdateHeader ruft. Sprachausgabe: einzelne Zeilen blieben zufaellig stumm Einfach: Wer schnell durch eine Liste ging, hoerte hin und wieder eine einzelne Zeile nicht - etwa "Nagakampfhandschuhe" in der Ausruestung, waehrend die Nachbarn gesprochen wurden - und sie blieb auch beim mehrfachen Darueberfahren stumm. Das betraf die NVDA/SAPI-Bruecke und konnte ueberall in Sku passieren, meist nach einem /reload. Jede Zeile wird jetzt wieder zuverlaessig gesprochen. Technisch: Der WoW-Client speichert gerenderte Sprachausgabe pro Text und spielt sie bei einer Wiederholung ab, ohne die Stimme erneut aufzurufen - bei der Bruecke ist diese Wiederholung Stille. Sku haengt darum an jeden Text eine pro Text zaehlende Folge geschuetzter Leerzeichen (1..64), damit jede Wiederholung ein neuer Text ist. Der Zaehler lebte aber nur in Lua und begann bei jedem /reload von vorn, waehrend der Cache des Clients den Reload ueberlebt (die Utterance-IDs laufen ueber den Reload hinweg durch). Eine nach dem Reload erneut gesehene Zeile konnte so wieder in einen schon gerenderten Bereich fallen und blieb stumm, bis der Zaehler diesen Bereich verlassen hatte - im Protokoll sechs Anschlaege in Folge mit sauberem SpeakText + STARTED + FINISHED. Die Zaehler liegen jetzt in SkuOptionsDB.global (bttsCacheBust) und laufen ueber den Reload weiter; zudem ist der Raum pro Text 512 Varianten statt 64 (fuehrende geschuetzte Leerzeichen 1..8 tragen den hohen Teil des Zaehlers). Quest: "Raenes Saeuberung" (Eisenknauf) hatte kein Questziel Einfach: Die Quest 1027 "Raenes Saeuberung" im Eschental verlangt das letzte Teil von Dartols Rute, den Eisenknauf. Sku kannte dafuer keinen Ort, "Questziel" blieb leer. Jetzt fuehrt das Questziel in das Schleimgebiet suedoestlich von Raynewoods Zuflucht: Dort lassen die Faulenden Bruehschleimer beim Tod eine Rostige Truhe zurueck, in der der Knauf liegt. Technisch: Der Gegenstand 5519 (Iron Pommel) verweist in der Datenbank korrekt auf das Objekt 19021 (Rusty Chest), doch dessen Datensatz hatte keine Spawn-Koordinaten, weder in objects.lua noch in objects_fixes.lua - der Item-Zweig von GetResultingWps fand nichts. objects_fixes.lua (TBC und Era) traegt jetzt die 44 Truhenpositionen von Wowhead im Eschental nach (Zone 331, etwa 68-78 / 68-80); das ist dieselbe Flaeche wie die Spawns des Faulenden Bruehschleimers (3928), der die Truhe hinterlaesst. Sprachausgabe: getippte Zeichen und abgebrochene Ansagen kamen verspaetet nach Einfach: Wer eine laengere Nachricht tippte und die Chatzeile dann schloss, hoerte die Buchstaben danach weiter - Zeichen fuer Zeichen, waehrend man laengst in einem anderen Menue navigierte, in einem Mitschnitt fast eine Minute lang. Dasselbe galt fuer eine abgebrochene Ansage: nach "Abgebrochen" kam noch ein Rest der alten Zeile, etwa eine Entfernungsangabe aus dem gerade geschlossenen Wegpunktmenue. Was beim Schliessen oder Abbrechen noch aussteht, wird jetzt verworfen. Die Tastenansage bleibt dabei vollstaendig - es geht kein Buchstabe verloren. Technisch: Der Client nimmt jedes SpeakText ohne Begrenzung an, spielt aber nur eines nach dem anderen ab, und C_VoiceChat.StopSpeakingText bricht nur die gerade LAUFENDE Ausgabe ab - ein Leeren der Warteschlange wie SAPIs PurgeBeforeSpeak gibt es nicht. Alles bereits Uebergebene ist damit unwiderruflich. Die Tastenansage gab bisher pro Anschlag sofort eine Ausgabe ab, drei bis vier pro Sekunde, waehrend der Client etwa eine pro Sekunde schafft: eine getippte Zeile von 104 Zeichen parkte so rund 80 Ausgaben im Client, die danach einzeln nachliefen. Aus demselben Grund liefen CancelBttsOutput und EndScope ins Leere - sie leeren Skus eigene Warteschlange, in der die Zeichen nie lagen (85 von 93 EndScope-Aufrufen eines Mitschnitts verwarfen nichts). Die Zeichen warten jetzt in Sku, es geht immer nur eines an den Client, und das naechste erst bei dessen PLAYBACK_FINISHED - dem Moment, in dem der Client ueberhaupt wieder eine Ausgabe annimmt (jedes STARTED des Mitschnitts faellt mit einem FINISHED zusammen). Damit ist nie etwas uebergeben, das noch nicht laeuft, und ein Abbruch erreicht alles. Ein kurzes Abbruchfenster sichert den Rest ab: nach einem harten Abbruch wird nichts uebergeben und jede dennoch startende Ausgabe sofort gestoppt. Das entspricht dem Aufbau von NVDA, das die Warteschlange ebenfalls selbst haelt und der Stimme nur eine Ausgabe auf einmal gibt. Anmelde-Tool 3.3: Absturz beim Start durch eine beschaedigte Windows-Stimme Einfach: Nach einer frischen Installation sagte das Tool noch "Version 3.2" an und brach dann mit einem Fehlerfenster ab ("Error: (0x80045039) Specifically: GetVoices"). Schuld war nicht das Tool allein, sondern eine beschaedigte Stimme in Windows - etwa eine deinstallierte Stimme, die Reste hinterlassen hat. Das Tool ueberspringt eine solche Stimme jetzt, vermerkt sie in log.txt und startet normal; sie fehlt dann nur im Menue "Stimme auswaehlen". Technisch: 0x80045039 ist SPERR_NO_MORE_ITEMS: SAPI meldet N Stimmen, eine davon laesst sich aber nicht lesen (kaputter Eintrag unter HKLM\SOFTWARE\Microsoft\Speech\Voices\ Tokens). Das Tool starb beim Aufbau des Stimmen-Menues an der for-Schleife ueber sap.GetVoices(). GetVoices() und SetSapiVoiceByName() lesen jetzt ueber die neue Funktion ReadableVoiceTokens() jede Stimme einzeln per Item(i) in einem eigenen try; eine unlesbare wird uebersprungen und geloggt, scheitert schon die Liste, bleibt sie leer. SapiInit() liest die Standardstimme ebenfalls geschuetzt. Am Rechner mit kaputter Stimme noch ungetestet. Sprachausgabe: schnelles Blaettern las ueber die NVDA-Bruecke den vorigen langen Eintrag zu Ende Einfach: Mit der NVDA/SAPI-Bruecke als Stimme las Sku beim schnellen Blaettern durch eine Liste mit langen Eintraegen (Wegpunktliste, Questtexte, Chatverlauf) erst den vorigen Eintrag ganz zu Ende und dann den, auf dem der Cursor stand. Jetzt wird der alte Eintrag nach einem kurzen Moment abgebrochen und der gewaehlte gelesen, wie bei einer Windows-Stimme. Laengere Texte, die in mehreren Teilen kommen, werden weiter vollstaendig gelesen, und das Tipp-Echo bleibt unveraendert. Die Behebung braucht die neue NVDA-Bruecke aus dem Sku-Installer 5.1: ueber den Installer aktualisieren (nicht nur das Addon-Zip) und WoW danach komplett neu starten. Technisch: StopSpeakingText des Spiels stoppt nur die eigene Wiedergabe des Clients. Auf der Bruecke steht der Text dann schon in NVDAs Warteschlange, und SAPI reicht "purge before speak" nie an eine Engine weiter - nichts auf dem Weg konnte NVDA unterbrechen. Bei der Engine kommt nur die Ausgabe selbst an, Markup eingeschlossen. Deshalb reist die Absicht jetzt darin mit, wie bei Prisms speak(text, interrupt): jeder Stopp setzt ein Flag, und die naechste Zeile traegt . Die mit dem Installer ausgelieferte Engine (SAPI2SR mit Skus Patch C) ruft bei diesem Bookmark nvdaController_cancelSpeech und reicht dann den Text weiter. Zeilen ohne Stopp davor tragen keine Marke und reihen sich weiter ein. Echte SAPI-Stimmen verschlucken das Bookmark lautlos; eine aeltere Engine ueberspringt es. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.4 Ueberblick Neu Pawn: unter Addons > Pawn stehen Pawns Tooltip-Schalter, und Sku-Tooltips nennen die Verbesserung in Prozent, den Unterschied je Attribut und fehlende Attribute. Von Yennesta. Neue Taste "damage meter oeffnen" springt direkt zu den Details-Berichten; die Tastenbelegung hat eine eigene Gruppe "Addons". Aenderungen Chat: beim Absenden oder Abbrechen wird ein noch laufendes Tastatur-Echo sicher beendet, die Ansage der gesendeten Nachricht aber nie angeschnitten. Ansagen eines Menues oder Fensters enden mit dem Fenster: was beim Schliessen noch wartet, wird verworfen, was gerade laeuft, gestoppt. Fehlerbehebungen Mac: Pfeil-, Funktions- und Bild-Tasten kamen doppelt an - leere Taschen- und Leistenplaetze wurden uebersprungen, der Tooltip-Leser sprang bei jedem Umschalt+Pfeil runter an den Anfang. Schlachtzug-Lebensmonitor: eine von Hand zugewiesene Rolle landete beim falschen Spieler, und ohne Rollenerkennung blieb der Monitor stumm. Haendler: der Rueckkauf-Reiter las und kaufte den Gegenstand mit derselben Nummer aus dem normalen Angebot. Ausruestungsvergleich in Tooltips fehlte manchmal - der Scan-Tooltip hatte seinen Besitzer verloren. Tooltip-Leser: am Ende eines Textes, etwa in der Freundesliste, wechselte Umschalt+Pfeil runter zwischen Stille und der letzten Zeile. Per Taste angeforderte Ansagen (Zielleben, Entfernung, Ziel ...) blieben beim zweiten Druck innerhalb einer Sekunde stumm. Mac: Pfeil- und Funktionstasten kamen doppelt an Einfach: Auf dem Mac wurden beim schnellen Blaettern leere Taschen- und Aktionsleistenplaetze uebersprungen, und der Tooltip-Leser fing bei jedem Umschalt+Pfeil runter wieder von vorn an. Beides ist behoben; Windows war nie betroffen. Technisch: Der Mac-Client reicht fuer Tasten ohne Zeichen - Pfeile, F-Tasten, Bild auf und ab, Pos1, Ende, Einfuegen, Entfernen - die Platzhalterzeichen des Betriebssystems aus dem privaten Unicode-Bereich (U+F700 aufwaerts) an OnChar durch; Windows loest fuer diese Tasten kein OnChar aus. Jeder Pfeildruck erreichte das Menue deshalb zweimal: als gebundene Taste und als Phantomzeichen, das ungeprueft in die Tastenauswertung weitergereicht wurde. Dort zaehlte der Doppeltipp-Zaehler zwei Anschlaege je Druck (jeder Eintrag "Leer" uebersprungen), und die Regel "jede andere Taste schliesst den Leser" schloss den Tooltip-Leser nach jedem Umschalt+Pfeil runter. Das Menue reicht aus OnChar jetzt nur noch Zeichen weiter, die die Buchstabensuche kennt (Positivliste), die beiden Tastatur-Echo-Hooks verwerfen den ganzen privaten Bereich U+E000 bis U+F8FF, und ein Doppeltipp verlangt jetzt dieselbe Taste zweimal. Verworfene Zeichen landen mit ihren Bytes im Debug-Ring, damit ein Tester das Phantom auf seinem Client belegen kann. Ursache erkannt und zuerst abgefangen von Yennesta (PR 19). Schlachtzug-Lebensmonitor: Rollen beim richtigen Spieler Einfach: Wer im Schlachtzug einem Spieler von Hand eine Rolle zuwies, traf oft einen anderen, sobald die Gruppenreihenfolge von der Beitrittsreihenfolge abwich. Und ohne automatische Rollenerkennung blieb der Monitor fuer diesen Spieler ganz stumm. Technisch: Das Zuweisungsmenue zaehlt die Mitglieder in hoerbarer, nach Gruppen sortierter Nummer und speicherte die Rolle unter dieser Nummer; die Lebensauswertung las sie ueber den echten raidN-Index. Das Menue behaelt seine Nummerierung und merkt sich je Eintrag den echten Index, unter dem gespeichert und gelesen wird. Ohne Rolle (SkuAuras aus, oder keine erkannt) blieb die Rollen-ID nil, und UNIT_HEALTH griff damit in die Filtertabelle - Abbruch der ganzen Auswertung. Die Rollenaufloesung ist jetzt eine Funktion: Zuweisung, dann SkuAuras, sonst der Korb "Keine Rolle". Von Yennesta. Haendler: Rueckkauf kauft wieder das Verkaufte zurueck Einfach: Im Rueckkauf-Reiter nannte Sku den falschen Gegenstand und kaufte beim Bestaetigen das Angebot des Haendlers mit derselben Nummer statt des verkauften Stuecks. Technisch: Der Rueckkauf-Reiter benutzt dieselben Schaltflaechen und Nummern wie das normale Angebot. Sku las sie mit SetMerchantItem und kaufte mit BuyMerchantItem, beides bezogen auf das Angebot. Bei aktivem Rueckkauf-Reiter laeuft die Abfrage jetzt ueber SetBuybackItem und der Kauf ueber BuybackItem; ein Rueckkauf ist ein einzelner Stapel, daher gibt es dort kein Mengenuntermenue. Von Yennesta. Pawn: Verbesserung und Wertunterschiede im Tooltip Einfach: Ist Pawn installiert, nennt der Sku-Tooltip eines Gegenstands direkt unter dem Namen die Verbesserung in Prozent samt Skala, haengt an jede Attributzeile den Unterschied zum angelegten Gegenstand an (gesprochen "plus" oder "minus", Schaden pro Sekunde mit einer Nachkommastelle) und listet Attribute, die der angelegte Gegenstand hat und der neue nicht. Unter Addons > Pawn stehen die Schalter "Pawn in Sku-Tooltips" sowie Pawns eigene Tooltip-Einstellungen; ohne Pawn steht dort nur der Hinweis, dass es fehlt. Von Yennesta. Technisch: Neue Datei SkuCore/pawnIntegration.lua; alle Pawn-Aufrufe sind abgesichert und der Tooltip-Durchlauf laeuft in pcall, ohne Pawn wird nichts angehaengt. Gegenueber dem Beitrag: der Schalter ist eine Vorgabe im SkuCore-Einstellungsschema (an), der Zeilenabgleich ist unabhaengig von Gross- und Kleinschreibung (auf englischen Clients heisst die Statistik "Damage Per Second", die Tooltip-Zeile "damage per second" - die DPS-Differenz fiel dort stumm weg), und ein Fehler im Durchlauf steht im Debug-Ring. Taste "damage meter oeffnen" und Tastengruppe "Addons" Einfach: Eine neue, standardmaessig unbelegte Taste springt direkt zu Addons > Damage Meter > Berichte. In den Tastenbelegungen gibt es jetzt die Gruppe "Addons" mit den Tasten fuer AtlasLoot und das Damage Meter. Technisch: Gebunden und ausgewertet wie die Dungeon-Browser-Taste; der Menuepfad laeuft ueber Knoten-IDs (Addons, DamageMeter, Reports) und damit in jeder Sprache. Die Berichtseintraege liefern ihren Text erst beim Lesen (Funktion statt Tabelle, wie die Auktionshaus-Eintraege): frische Details-Daten, keine Kosten fuer ungelesene Kaempfe, und es funktioniert auch, wenn der Cursor per Taste auf einem Eintrag landet, ohne OnEnter zu durchlaufen. Taste und IDs von Yennesta. Ausruestungsvergleich fehlte manchmal Einfach: Bei Umschalt+Pfeil runter auf einem Gegenstand fehlte gelegentlich der Abschnitt "aktuell angelegter Gegenstand", scheinbar zufaellig. Er ist jetzt immer da. Technisch: Sku liest Tooltips ueber einen gemeinsamen, unsichtbaren GameTooltip. Ein GameTooltip fuellt seine Zeilen nur, solange er einen Besitzer hat, und verliert ihn von selbst: ein Aufruf ohne Inhalt (leerer Leisten-, Taschen- oder Ausruestungsplatz, noch nicht geladener Gegenstand) blendet ihn aus und loescht den Besitzer. Danach lieferte jede Abfrage still nichts, bis ein anderer Weg zufaellig SetOwner rief. Drei Stellen hatten das bereits fuer sich behoben, was den Fehler zufaellig wirken liess. Alle 18 Abfragestellen setzen den Besitzer jetzt vor jedem Lesen ueber eine Hilfsfunktion neu. Tooltip-Leser: das Ende eines Textes Einfach: In der Freundesliste (und ueberall sonst) blieb der Leser mit Umschalt+Pfeil runter nicht auf der letzten Zeile stehen, sondern wechselte zwischen Stille und der letzten Zeile - wie eine Endlosschleife. Er liest die letzte Zeile jetzt bei jedem Druck. Technisch: Am Textende reicht der Leser dieselbe Zeile erneut an die Sprachebene. Deren Dublettensperre aus v43.2 verwirft eine innerhalb einer Sekunde identische Zeile, sofern sie nicht als tastenausgeloest markiert ist - und der Leser markierte nie. Jede Zeile des Lesers, auch Links, traegt die Markierung jetzt. Per Taste angeforderte Ansagen bleiben nicht mehr stumm Einfach: Zielleben, Entfernung, Ziel-Ansage, Wuerfelinfo, Zum Beacon drehen, Wegpunkt-Tasten und aehnliche: ein zweiter Druck innerhalb einer Sekunde mit derselben Antwort blieb stumm. Jetzt kommt die Antwort bei jedem Druck. Technisch: Dieselbe Dublettensperre; markiert hatte bisher nur die Tastenauswertung des Menues. Statt jede Ansage einzeln zu markieren, merken sich die drei Tastenverteiler (Hauptfenster, SkuCore-Steuerrahmen, SkuNav) den Frame ihres Aufrufs, und die Sprachebene wertet jede Uebergabe innerhalb von 0,1 Sekunden danach als tastenausgeloest. Der Nachschlag eines Menue-Neuaufbaus kommt aus einem Timer und spaeteren Frames und faellt nicht in dieses Fenster; die Tastenauswertung des Menues markiert weiter ausdruecklich. Sprachbereiche: Ansagen enden mit ihrem Fenster Einfach: Zwei Faelle mit langsamen SAPI-Stimmen: Nach Absenden oder Abbrechen im Chat las die Stimme eine mit Pfeil hoch geholte Zeile zu Ende, und nach dreimal Lernen beim Lehrer und Escape kam der Lehrer noch dreimal. Beides ist vorbei: das Chat-Echo wird beim Schliessen abgebrochen - die Ansage der gesendeten Nachricht aber nie -, und was ein Menue oder Fenster beim Schliessen noch zu sagen hatte, wird verworfen oder gestoppt. Ansagen aus Kampf, Chat oder Navigation sind davon nicht betroffen. Technisch: Ein Tastendruck allein bricht weiterhin nichts ab (Regel aus v43.2), und auf der Screenreader-Bruecke ist das Ende einer Aeusserung nicht feststellbar, weil FINISHED im Uebergabe-Frame kommt - die Buchfuehrung "spricht gerade etwas" ist dort immer leer, weshalb selbst der Stop beim Menue-Schliessen als ueberfluessig unterdrueckt wurde. Bekannt ist aber genau, was zuletzt uebergeben wurde und fuer wen. Eine Zeile kann jetzt einen Bereich tragen ("menu" fuer Menueansagen, "echo" fuer die Tippspur), und SkuVoice:EndScope verwirft beim Ende des Bereichs dessen wartende Zeilen und stoppt die Stimme nur, wenn die laufende Aeusserung dazugehoert. Gerufen wird das beim Menue-Schliessen und im Hide-Hook jedes beobachteten Fensters, also auch bei Escape im Spiel. Der weiche Stop des Chatfelds fragt statt der Ein-Sekunden-Regel jetzt SkuVoice:IsEchoInFlight: Echo wird abgebrochen, egal wie lange es laeuft; wurde seither etwas anderes uebergeben - vor allem die Antwort des Servers auf die gesendete Nachricht -, wird nichts gestoppt. Yennesta hatte in PR 19 den unbedingten Abbruch vorgeschlagen; das hier ist die gezielte Fassung davon. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.3 Ueberblick Neu Das Installationsprogramm gibt es jetzt auch fuer den Mac - installieren, aktualisieren und Selbst-Update wie unter Windows. Danke an Yennesta. Installationsprogramm 5.0: sieben bewaehrte Zusatz-Addons wie Questie und Deadly Boss Mods lassen sich mitinstallieren und werden aktuell gehalten - Windows und Mac, Anniversary und Classic Era. Mac: Installationsprogramm und Anmelde-Tool sprechen Deutsch, Englisch und Franzoesisch; das Anmelde-Tool erkennt auch franzoesische Clients. Aenderungen Zu Einheit drehen und Zum Ziel drehen drehen jetzt wie Zum Beacon drehen: kuerzester Weg, hoechstens eine Viertelsekunde. Fehlerbehebungen Sprachausgabe: einzelne Ansagen blieben stumm, obwohl der Ton kam - vor allem bei kurzen Zeilen, die man immer wieder hoert. Interagieren-Taste: nach einem Kill schnappt sie manchmal ein weit entferntes Vieh ins Ziel und laeuft hin statt zu pluendern - Sku warnt jetzt mit einem Ton. Mac: die Sprachausgabe las an jeder Zeile technisches Steuer-Markup mit vor. Stallmeister: das Menue zeigte und tauschte die falschen Begleiter-Plaetze, und die Tausch-Ansage meldete zu frueh einen Fehlschlag. Chat: ein Kampfprotokoll-Tab blieb komplett stumm. Dial Targeting war auf dem Anniversary-Client komplett tot - funktioniert wieder, getestet im 25er-Schlachtzug. Franzoesisch: vier Chat-Einstellungstexte sprachen noch Englisch. Franzoesisch: vier Chat-Texte sprachen noch Englisch Einfach: Auf einem franzoesischen Client waren die Einstellung der Pfeiltasten in der Chateingabe, die Kanal-Ansage samt Erlaeuterung und die Meldung fuer einen unbekannten Slash-Befehl noch auf Englisch zu hoeren. Sie sind jetzt uebersetzt. Technisch: Die vier Texte aus v43.1 fehlten im Uebersetzungsspeicher, aus dem die franzoesische Sprachdatei erzeugt wird. Beim Beheben fiel auf, dass 29 fuer v43.2 von Hand in die erzeugte Datei geschriebene Texte ebenfalls nur dort standen - der naechste Erzeugungslauf haette sie stillschweigend auf Englisch zurueckgesetzt. Alle sind jetzt in den Speicher uebernommen, und das Erzeugungswerkzeug schreibt die Datei nur noch auf ausdrueckliches Kommando statt bei jedem unbekannten Argument. Sprachausgabe: wiederholte Ansagen bleiben nicht mehr stumm Einfach: Beim Navigieren in Menues und Tooltips kam ab und zu nur der Ton, die Ansage selbst blieb aus. Betroffen waren vor allem die kurzen Zeilen, die man den ganzen Abend wieder und wieder hoert - "menue geschlossen", "annehmen", "buffs" oder ein einzelner getippter Buchstabe. Technisch: Der Client merkt sich erzeugte Sprachausgabe zum Text und spielt sie bei einer Wiederholung aus dem Zwischenspeicher ab, ohne die Stimme erneut aufzurufen. Ueber eine Bruecke zum Screenreader ist diese Wiederholung stumm. Sku haengt deshalb an jede Zeile eine unhoerbare Kennung an, damit jeder Aufruf neu erzeugt wird - bisher aus einem Zaehler, der alle 64 Ansagen von vorn begann. Eine Zeile, die genau 64 Ansagen spaeter noch einmal kam, war damit zeichengleich und landete wieder im Zwischenspeicher. Der Zaehler laeuft jetzt pro Text statt fuer alle Ansagen gemeinsam; eine neu gesehene Zeile bekommt ihren Startwert weiterhin aus dem gemeinsamen Zaehler, damit auch das Leeren der Tabelle (ab 512 verschiedenen Zeilen) keine Zeile auf ihren eigenen ersten Wert zurueckwirft. Nachgerechnet an einer Aufzeichnung von 1307 Ansagen: vorher 27 zeichengleiche Wiederholungen, mit einem Zaehler pro Text ohne diesen Startwert 80 - also schlechter -, in der ausgelieferten Fassung 0. Mac: die Sprachausgabe liest kein Steuer-Markup mehr vor Einfach: Auf dem Mac sprach die Stimme zu den Zeilen hoerbar Steuerzeichen mit, die nur fuer die Technik gedacht sind. Sie sind dort jetzt weg. Technisch: Fuer den Handschlag mit dem Screenreader haengt Sku eine -Markierung an jede Zeile; der Mac-Client filtert solches Markup nicht aus der Sprachausgabe und las es woertlich vor. Auf dem Mac wird die Markierung jetzt weggelassen; die unhoerbaren Zeichen gegen den Wiederholungs-Zwischenspeicher bleiben, damit auch dort jede Wiederholung neu erzeugt wird. Idee von Yennesta. Zu Einheit drehen: schneller und praeziser Einfach: "Zu Einheit drehen" und "Zum Ziel drehen" drehen jetzt genauso wie "Zum Beacon drehen": auf kuerzestem Weg, in hoechstens einer Viertelsekunde, statt bis zu anderthalb Sekunden lang rechts herum zu suchen. Technisch: Der fuer v43.2 gebaute und ausgiebig getestete Drehkern (Richtungs-Schnapp, Tempodeckel, Vorhalten in Bewegung, Geradestellen mit der Neigungssperre) ist von der Wegpunkt-Aufloesung getrennt worden, so dass ihn jetzt auch die Einheiten-Drehung aufruft, sobald der Client Koordinaten zur Einheit liefert. Die bisherige Suche ueber Namensplaketten bleibt als Rueckfall fuer Instanzen, wo es keine Koordinaten gibt. Die Aufloesung des Ziels zu einer Einheit folgt einer Idee von Yennesta. Stallmeister: der Begleiter-Tausch trifft wieder die richtigen Plaetze Einfach: Im Stallmeister-Menue des Jaegers waren die Plaetze verschoben - angezeigt und getauscht wurde der falsche Begleiter. Ausserdem meldete der Tausch bei langsamer Verbindung faelschlich "Begleiter konnte nicht gewechselt werden", obwohl er geklappt hatte. Beides ist behoben, und die Ansage nennt jetzt den Namen des neuen Begleiters. Technisch: Blizzards Stallfenster nutzt die Aktionsindizes 1 bis 3 (aktiver Begleiter plus zwei Stallplaetze); Sku fragte einen zu niedrig ab. Fix von Yennesta. Die Erfolgs-Ansage entscheidet ausserdem nicht mehr auf dem ersten Stall-Ereignis (das schon beim Aufnehmen feuert), sondern wartet, bis der Name des aktiven Begleiters passt oder zwei Sekunden vergangen sind - und sie ist jetzt in allen drei Sprachen uebersetzt. Neu: das Installationsprogramm gibt es auch fuer den Mac Einfach: Sku laesst sich auf macOS jetzt genauso bequem installieren und aktuell halten wie unter Windows: ein Installationsprogramm mit Sprachausgabe, Selbst-Update und denselben Komponenten. Die Download-Seite bietet einen eigenen Link je Plattform. Beigesteuert von Yennesta - vielen Dank! Technisch: Der Mac-Zweig haengt am selben Veroeffentlichungs-Ablauf wie Windows: die Versionserkennung folgt der releases/latest-Weiterleitung von GitHub, statt eine Webseite zu lesen, und die Dateien samt ihren sha256-Pruefsummen werden beim Veroeffentlichen lokal geprueft und an dieselbe Veroeffentlichung angehaengt. Interagieren-Taste: Warnton, wenn sie das falsche Ziel schnappt Einfach: Direkt nachdem etwas stirbt, nimmt die Interagieren-Taste (Standard G) manchmal statt der Leiche vor dir ein ganz anderes, angreifbares Vieh ins Ziel - auch eines weit entfernt - und laeuft per Autolauf dorthin, statt zu pluendern. Sku spielt jetzt in genau diesem Moment einen Warnton, damit du den Fehlgriff sofort hoerst und den Autolauf von Hand abbrechen kannst. Technisch: Die Taste ruft Blizzards InteractUnit("anyinteract") mit lockerer Zielwahl auf; verschwindet die gerade gepluenderte Leiche unter dem Tastendruck, greift der Client lose auf die naechste angreifbare Einheit in Tab-Reichweite ueber, macht sie zum Hartziel und laeuft hin. Die Taste selbst laesst sich nicht ersetzen (InteractUnit ist geschuetzt), und auch das Ziel laesst sich aus einem Addon nicht zuruecksetzen (ClearTarget ist ebenfalls geschuetzt, im Kampf wie ausserhalb). Bleibt die Erkennung: unmittelbar nach dem Verlassen einer Leiche ein lebendes, angreifbares, NICHT mit dir im Kampf stehendes neues Ziel - dann der Warnton. Ein bewusst per Taste (Alt+H / Strg+H) gewaehltes Ziel loest ihn nicht aus. Installationsprogramm 5.0: bewaehrte Zusatz-Addons mitinstallieren Einfach: Auf der Komponenten-Seite lassen sich jetzt sieben bewaehrte Addons ankreuzen - Questie, Deadly Boss Mods, AtlasLoot, Details, GTFO, BugSack samt BugGrabber und Pawn. Was angekreuzt ist, installiert das Installationsprogramm mit und haelt es bei jedem Lauf aktuell - unter Windows und auf dem Mac, fuer Anniversary und Classic Era, jeweils mit dem zum Client passenden Stand. Ab Werk ist alles an ausser Pawn. Technisch: Beide Plattformen lesen denselben Katalog. Addons mit GitHub-Veroeffentlichungen kommen direkt von dort (aufgeloest ueber die releases/latest-Weiterleitung, ohne API-Schluessel und ohne Ratenbegrenzung); der Rest ist mit sha256-Pruefsumme auf gepruefte CurseForge-Dateien festgenagelt. Deadly Boss Mods ist ein Eintrag aus vier Paketen, und BugSack und BugGrabber sind bewusst ein gemeinsames Haekchen. Jeder Client bekommt den zu ihm passenden Build - Pawn fuer Classic Era etwa kommt aus dem Classic-Paket. Mac: Installationsprogramm und Anmelde-Tool in drei Sprachen Einfach: Beide sprechen jetzt Deutsch, Englisch und Franzoesisch. Die Sprache laesst sich im jeweiligen Menue umstellen und folgt sonst der Systemsprache. Das Anmelde-Tool erkennt ausserdem franzoesische Clients und liest Stufenzeilen woertlich vor - ein deutscher Client sagt also wieder "Stufe 36" statt "Level 36". Technisch: App, Installations-Skript und Anmelde-Tool teilen sich eine Sprachwahl (gespeicherte Einstellung vor Systemsprache vor Englisch); gespeicherte Werte wie die Sprachpaket-Namen bleiben intern deutsch, damit bestehende Einstellungen weitergelten. Die Bildschirmerkennung des Anmelde-Tools ist von der Oberflaechensprache unabhaengig. Chat: das Kampfprotokoll bekommt wieder Ereignisse Einfach: Ein Chat-Tab "Kampfprotokoll" blieb komplett stumm. Er fuellt sich wieder. Danke an den Tester aus der Community fuer die Meldung samt Loesung. Technisch: Der Tab hatte das Ereignis COMBAT_LOG_EVENT abonniert, das auf diesem Client nicht so feuert, wie der Code es erwartet; jetzt abonniert er COMBAT_LOG_EVENT_UNFILTERED - dasselbe Ereignis, das die anderen Sku-Module laengst nutzen. Dial Targeting funktioniert wieder Einfach: Die Zielwahl ueber den Ziffernblock (Eintrag "Dial Targeting" im Sku-Menue) war auf dem Anniversary-Client komplett tot - kein Tastendruck kam an. Sie funktioniert wieder, getestet im 25er-Schlachtzug. Obendrein: in einer normalen Gruppe (ausserhalb des Schlachtzugs) hatte sie noch nie jemanden gefunden, die Mitglieder 30 bis 40 waren nicht waehlbar, und eine halb eingegebene Nummer konnte die naechste Eingabe verderben - alles behoben. Technisch: Der moderne Client stellt Tastatur-Klicks nur noch zu, wenn der Knopf sie per RegisterForClicks angemeldet hat - das fehlte, und damit war das ganze Feature stumm. Die Aktion feuert jetzt ausserdem unabhaengig von der Klick-Einstellung des Nutzers genau einmal pro Tastendruck. Die Gruppen-Belegung kommt aus party1 bis party4 statt aus der nur im Schlachtzug gefuellten Abfrage, das Tor fuer die erste Ziffer laesst auch die Untergruppen 6 bis 8 durch, und die belegte Tastenmatrix steht bei jeder Aenderung im Debug-Log. Hinweis: die Nummern entsprechen dem Schlachtzugs-Abschnitt der Uebersichtsseite; der Gruppen-Abschnitt dort zaehlt dich selbst immer als 1 und verschiebt dadurch die uebrigen - das ist Absicht und kein Fehler der Zielwahl. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.2 Ueberblick Neu Quests lassen sich im Questmenue verfolgen und wieder abwaehlen - neuer Eintrag "Quest verfolgen" ganz unten in jedem Questmenue, abschaltbar. Neue Liste "Quests in der Naehe" im Questmenue: das ganze Questlog in einer Liste, sortiert danach, wie weit das Naechste weg ist - mit Entfernung und Himmelsrichtung. Ab Werk aus. Neuer Tastenbefehl "Naechstes Questziel ins Ziel nehmen" (Alt+H): nimmt eine Kreatur ins Ziel, die zu einem offenen Questziel gehoert - auch eine, die einen benoetigten Gegenstand nur fallen laesst. Der Tastenbefehl "Naechster Gegner im Kampf" (jetzt ab Werk auf Strg+H) findet deutlich oefter etwas: er ist nicht mehr auf den Blickkegel angewiesen. Neuer Tastenbefehl "Vollstaendigen Tooltip des Ziels ausgeben" (Strg+Umschalt+V): liest den kompletten Tooltip des aktuellen Ziels vor, inklusive dessen, was die Jaegerfaehigkeit Tierkunde offenlegt. Taschenmenue: neuer Eintrag "alle bank" direkt hinter "alle taschen", solange die Bank offen ist - alles in der Bank in einer flachen Liste, genau wie "alle taschen" fuer die Taschen. Strg+Eingabe holt einen Gegenstand von dort in die Taschen, wie bisher schon in den einzelnen Bankfaechern. Chat: die Eingabezeile spricht jetzt wie jedes andere Sku-Eingabefeld - jedes getippte Zeichen, das Zeichen oder Wort unter dem Cursor, und mit Pfeil hoch die zuletzt gesendeten Nachrichten zum erneuten Senden oder Aendern. Chat: der Zielkanal wird angesagt, sobald er nicht "Sagen" ist - beim Oeffnen und bei jedem Wechsel; abschaltbar in den Chat-Einstellungen ("Kanal der Chateingabe ansagen"), ab Werk an. Chat: ein unbekannter Slash-Befehl wird angesagt, statt still verworfen zu werden. Schwimmen und Fliegen: Sku haelt dich waagerecht. Die neue Neigungssperre beendet das schleichende Abtauchen bei den automatischen Drehungen, und nach einem Anflug auf einen NPC oder einem Druck auf Steigen/Sinken wirst du aktiv wieder gerade ausgerichtet. Ab Werk an; abschaltbar unter Einstellungen -> Allgemein. Neuer Tastenbefehl "Neigungssperre beim Schwimmen und Fliegen umschalten" (Strg+Umschalt+N): sperrt und loest die Neigung manuell - aus- und wieder einschalten richtet dich jederzeit neu waagerecht aus. Experimentell: Sammelrouten fuer Erze, Kraeuter, Gaswolken und Truhen - Sku fuehrt dich Vorkommen fuer Vorkommen durch die Zone, immer das naechstgelegene zuerst. Unter Einstellungen -> Scan -> ressourcen scan -> Sammelrouten. Neu und im Spiel erst in Ansaetzen erprobt; Rueckmeldungen sind ausdruecklich erwuenscht. Neues Menue "Namensplaketten" unter Einstellungen -> Visuelle Hilfen: Groesse der Plaketten, Hervorhebung des Ziels, Klassenfarben und Abschwaechung der uebrigen Plaketten - Einstellungen, die das Spiel beherrscht, in seinem eigenen Optionsfenster aber nirgends anbietet. Das Lesefenster fuer Questtexte, Tooltips, Chatverlauf und Wiki ist einstellbar geworden: Schriftgroesse, Schriftart, Farbkombination, Deckkraft und Umriss unter Einstellungen -> Visuelle Hilfen -> Textfenster. Aenderungen Zum Beacon drehen (T): die Drehung sitzt jetzt deutlich genauer. Vorher lief sie so schnell, dass allein das framegenaue Stoppen je nach Bildrate 20 Grad und mehr Ueberdreh kosten konnte; jetzt richtet sich das Tempo nach der Drehgroesse, und keine Drehung dauert laenger als eine Viertelsekunde. Zum Beacon drehen: in Bewegung wird vorgehalten - gezielt wird dorthin, wo der Wegpunkt am Ende der Drehung liegen wird. Das beendet das Im-Kreis-Laufen um nahe Wegpunkte, das vor allem beritten und im Flug auftrat. Zum Beacon drehen: ein Druck waehrend einer laufenden Drehung wird verworfen, statt die Drehung mittendrin abzubrechen - gewohntes Mehrfachdruecken verfeinert weiter wie bisher. Navigation: unter "Direkter Wegpunkt" steht "Aktuelle Karte Entfernung" jetzt an erster Stelle und "Letzte" dahinter. Questdatenbank: "Start in Zone" zeigt die nach Entfernung sortierte Liste direkt an - die Zwischenebene "Nach Entfernung" ist weg. Questdatenbank: "Start in Zone" nennt zu jeder Quest jetzt auch die Himmelsrichtung, nicht nur die Entfernung. Questdatenbank: auf den aktuellen Questie-Datenstand gebracht - 33 Quests ohne Ziel haben jetzt eines, fuenf fehlende ergaenzt, dazu rund 2000 kleinere Korrekturen an Namen, Stufen, Questgebern und Vorquests. Taschen: nach einem Rechtsklick auf einen Gegenstand bleibt der Cursor auf diesem Gegenstand stehen, statt an den Anfang der Liste zu springen. Taschen: Aktionen mit Zauberzeit (Verzauberung, Angelkoeder, Waffenoel, Ruestungsset, Entzaubern) melden den Gegenstand nach dem Zauber noch einmal und lassen den Cursor darauf stehen. Taschen: ein Bestaetigungsdialog wie "Bestehende Verzauberung ersetzen?" kostet nicht mehr die Position - nach "Ja" wie nach "Nein" landet man wieder auf dem Gegenstand. Chat: "Link zu Chat hinzufuegen" fuegt den Gegenstand an der Cursorposition ein, statt die Zeile zu ersetzen, und laesst den Cursor davor stehen - davor passt jetzt noch ein Kanal wie "/p ". Chat: ein Gegenstandslink zaehlt beim Lesen als ein einziges Zeichen - Pfeil links und rechts springen ueber den ganzen Link und sagen den Namen. Chat: "Link zu Chat hinzufuegen" schliesst die Taschen nicht mehr. Chat: die Pfeiltasten bewegen in der Chateingabe den Textcursor; abschaltbar unter Chateinstellungen. Auren: eine Waffenverzauberung (Angelkoeder, Gift, Oel) laesst sich jetzt wie ein Zauber ansprechen - Ereignis "Waffenverzauberung abgelaufen" zusammen mit "Zauber name". Auren: neue Bedingung und neue Ausgabe "Waffenverzauberung Hand" (Haupthand oder Nebenhand). Menue: das Schliessen eines Fensters baut die Menuedaten nur noch einmal statt bis zu sechsmal neu auf. Menue: der Tippfilter ignoriert Akzente - auf einem franzoesischen Client findet "general" jetzt "Fournitures generales", und "oe" findet einen Eintrag, der mit "Oe" beginnt. Auf einer franzoesischen AZERTY-Tastatur tippt die Taste ù jetzt auch in den Filter. Franzoesisch: die Wegpunktkommentare gibt es jetzt auf Franzoesisch - 207 Texte auf 546 Wegpunkten, aus dem deutschen Original uebersetzt. Installationsprogramm: ein WoW an einem ungewoehnlichen Ort muss nur einmal gezeigt werden - das Installationsprogramm merkt sich, wo jeder Client liegt, und findet ihn bei jedem spaeteren Update von selbst wieder. Das Lesefenster startet ab Werk serifenlos in 18 Punkt statt in Playfair Display in 12 - die bisherige Voreinstellung war die kleinste und duennste Textflaeche des ganzen Addons. Auch der Lesebalken laesst sich jetzt in Schriftart und Farbkombination einstellen, mit eigenen Werten getrennt vom Textfenster. Auktionshaus: "Level absteigend" sortiert jetzt die ganze Trefferliste und nicht mehr nur die erste Seite; bei gleicher Stufe entscheidet der Preis je Stueck. Auktionshaus: "Stufe" ist ueberall die Stufenanforderung des Gegenstands - und wird nur noch dort vorgelesen, wo sie die Eintraege wirklich unterscheidet. Fehlerbehebungen Menue: waehrend man ging, war das geoeffnete Menue wie tot - jede Taste ausser Escape wurde verschluckt, bis man stehen blieb. Escape schloss das Menue nicht, wenn man direkt auf einem Questobjekt stand - das Questfenster ging endlos wieder auf. Menue: Enter auf einem Ein/Aus-Eintrag in einer gefilterten Liste sagte den ersten Eintrag der Liste an statt des umgeschalteten Zustands. Menue: eine Zeile, die man per Tastendruck erneut anfordert, wird wieder vorgelesen statt verschluckt. Menue: der Tippfilter fasste das Getippte als Suchmuster auf - eine Eingabe wie "50%" oder "(lang" fand nichts oder brach ab. Tastatur-Echo: getippte Zeichen kommen sofort; verschluckte und verspaetete Buchstaben sind weg. Sprachausgabe: Ansagen blieben beim Navigieren immer wieder fuer eine Weile still - am zuverlaessigsten bei einem einzelnen Treffer nach dem Filtern. Sprachausgabe: Gegenstandslinks wurden als Folge von Farbcodes vorgelesen statt als Name - ueberall in Sku, nicht nur im Chat. Zum Beacon drehen: nach schnell hintereinander ausgeloesten Drehungen konnte die Drehgeschwindigkeit der Kamera-Tasten dauerhaft vervierfacht haengenbleiben. Das Loeschen eines eigenen Wegpunkts entfernte die falsche interne Kennung, und "/skucheck wp" meldete vier Fehler bei den Schnellwegpunkten, die keine waren. Questmenue: bei Quests mit gemischten Zielen ("toete X und sammle Y") zeigte "Ziel" nur die erste Zielart - jetzt stehen Gegner, Fundorte und Erkundungspunkt nebeneinander. Questmenue: bei 174 Quests, deren Ziel ein ORT ist, stand der Ort zwar in den Daten, aber "Questziel" meldete trotzdem nur "Leer" - gesucht wurde ein Wegpunkt unter einem Namen, den nie jemand vergibt. Jetzt wird aus den Koordinaten der naechstgelegene Routenwegpunkt berechnet. Bei 77 WEITEREN Quests fehlten die Zieldaten dagegen ganz - fuer sie sind Objekte, Kreaturen und 26 Ortskoordinaten neu eingetragen, ein Teil davon aus Webquellen: Rueckmeldungen, ob sie stimmen, sind willkommen. Questmenue: rund 300 Quests, deren Questgeber, Ziel oder Abgabe in einem Dungeon liegt, zeigten leere Eintraege - jetzt fuehren sie zum Dungeoneingang. Dreizehn Sprich-mit-Quests (u.a. die alten Priester-Zauberquests) standen ohne Abgabepunkt in den Daten - jetzt fuehrt die Abgabe zu dem NPC, den der Questtext nennt. Questdatenbank: direkt nach einem /reload konnten Quests inaktiver Weltereignisse (etwa Sonnenwendquests) in "Start in Zone" auftauchen. Questdatenbank: die Liste "Start in Zone, Nach Entfernung" brach nach der ersten Quest ab. Taschen: der Tippfilter blieb nach dem Benutzen eines Gegenstands haengen und liess sich nur noch durch Schliessen der Taschen loswerden. Nach einer Aktion mit Zauberzeit wurde direkt nach dem richtigen Gegenstand noch ein falscher angesagt. Die Taschenliste fuer den Kampf konnte veralten, wenn man ein Questfenster schloss, waehrend die Taschen offen waren. Taschenmenue: mit einem Taschen-Ersatz-Addon wie Bagnon, das Blizzards Bankfenster versteckt, verschwanden saemtliche Bankfaecher aus dem Menue. Auren: der Satt-Buff war in der Zauberauswahl doppelt vorhanden - beide Eintraege klangen gleich, nur einer konnte je ausloesen. Auren: Eintraege, die es nur als Waffenverzauberung gibt (etwa "Angelfertigkeit +75"), sind in den Auswahllisten jetzt als solche gekennzeichnet. Auren: "Waffenverzauberung Haupthand enthaelt X" zusammen mit "Waffenverzauberung abgelaufen" konnte nie ausloesen - /skucheck auras meldet diese Kombination jetzt. Auren: das Ende einer Waffenverzauberung wird auf den Frame genau erkannt statt bis zu eine viertel Sekunde spaeter. Aktionsleisten: Umschalt+Ab las im Zuweisungsmenue den Zauber-Tooltip nicht mehr vor. Dungeonbrowser: das Annehmen einer Gruppeneinladung fuehrt nicht mehr von selbst in den Dungeonbrowser. Franzoesisch: die Wegpunktkommentare blieben seit v42.11 vollstaendig stumm - auch die Warnungen wie "Vorsicht, Abgrund" oder "hier auf den Zeppelin warten". Franzoesisch: 22 der 94 Ressourcennamen des Minikartenscanners waren falsch, diese Vorkommen wurden nie angesagt. Franzoesisch: in der Hoehle der Nebel blieb die Wegpunktliste leer. Die Plaketten-Farben waren nach jedem Login und jedem Neuladen tot: der Schalter stand auf an, gefaerbt wurde aber nichts, bis man ihn von Hand zweimal umlegte. Der Lesebalken blieb im Kampf unsichtbar - also genau dann, wenn er am dringendsten gebraucht wird. Der Lesebalken zeigte nur den Namen eines Menueeintrags, nicht den vorgelesenen Wert dahinter - Schalterzustaende und Anzahlen waren hoerbar, aber nicht lesbar. Ein geschlossenes Fenster konnte spaeter noch einmal angesagt werden - typisch der Lehrer, nachdem man laengst sein Berufsfenster geoeffnet hatte. Das Menue ging gelegentlich von selbst auf der obersten Ebene auf, statt dort, wo man hinwollte. Waren zwei Fenster gleichzeitig offen, wurde das Schliessen des zweiten nicht bemerkt. Nach dem Schliessen eines Fensters konnten dessen Eintraege unter "Lokal" stehenbleiben. Lehrer: lernte man mehrere Zauber schnell hintereinander und schloss das Fenster gleich danach, sprach es noch weiter. Auktionshaus: "Nur benutzbare" versteckte in der Komplettscan-Liste ausgerechnet das Hochstufige, nach dem man sucht. Auktionshaus: die Komplettscan-Liste filterte nach Stufe und Qualitaet, obwohl gar kein Filter gesetzt war - Handelswaren, Materialien und alles Graue fehlten. Auktionshaus: eine Kategorie ohne Unterkategorien zeigte ausser "Alle" keinen einzigen Gegenstand. Auktionshaus: ein abgebrochener Kauf konnte die naechste Suche entfuehren und ungefragt einen Kauf scharf schalten. Auktionshaus: eine Suche, die der Waechter abbricht, sagt das jetzt - vorher sah die halbe Liste wie ein fertiges Ergebnis aus. Schwimmen und Fliegen: die Neigungssperre beendet das ungewollte Abtauchen Einfach: Beim Schwimmen oder Fliegen zog jede automatische Drehung zum Funkfeuer ein kleines Stueck nach unten - ueber eine Strecke summierte sich das, bis man unbemerkt unter Wasser oder am Boden war. Jetzt sperrt Sku die Neigung, sobald du schwimmst oder fliegst: du bewegst dich exakt waagerecht, und Leertaste und X tragen dich weiterhin nach oben und unten. Wenn dich doch etwas schief stellt - etwa der automatische Anflug beim Interagieren mit einem NPC -, richtet Sku dich aktiv wieder gerade: beim Oeffnen des NPC-Fensters, kurz nach jeder Drehung und immer, wenn du Steigen oder Sinken drueckst. Ab Werk an; wer beim Schwimmen mit der Maus per Neigung tauchen will (Restsehvermoegen), schaltet es unter Einstellungen -> Allgemein ab. Dazu der neue Tastenbefehl "Neigungssperre" (Strg+Umschalt+N) zum manuellen Sperren und Loesen. Technisch: Drei Bausteine. Erstens deckelt die Konsolenvariable pitchlimit 0 die Bewegungsneigung des Charakters (die Technik der Addons LevelFlight und FlightHUD) - dauerhaft gesetzt statt um jeden Dreh-Impuls herum, denn genau dieses Umschalt-Rennen hat fruehere Versuche scheitern lassen. pitchlimit ist beschreibbar, aber nicht lesbar; bei jedem Login wird deshalb blind der Standard 88 wiederhergestellt, damit nie eine Sperre haengenbleibt. Zweitens haelt die Sperre nur, was da ist: engine-gesteuerte Bewegung wie der Interagieren-Anflug neigt den Charakter trotzdem, und danach gibt es keine Tastatur-Eingabe, die die Neigung wieder anhebt. Das aktive Geradestellen benutzt genau den Transfer, der urspruenglich den Fehler verursachte: ResetView/SetView schnappt die Kamera auf die bekannte fast-waagerechte Voreinstellung, ein Mouselook-Impuls uebertraegt sie auf den Charakter, und die Sperre deckelt den kleinen Rest auf null. Ausloeser sind das NPC-Fenster, jede Drehung (um 0,5 s verzoegert, weil die Engine die Gierung erst einen Frame spaeter anwendet - ein sofortiger zweiter Impuls wuerde die Drehung aufheben) und per hooksecurefunc die Steig-/Sinkfunktionen JumpOrAscendStart, AscendStop, SitStandOrDescendStart und DescendStop - unabhaengig davon, auf welchen Tasten sie liegen. Drittens ein Neigungsmesser fuers Log: gemessene Horizontalgeschwindigkeit geteilt durch GetUnitSpeed ist der Kosinus der Bahnneigung - der einzige Messweg, den dieser Client hergibt (GetUnitPitch wurde mit Patch 7.1 entfernt und fehlt auch hier). Er misst die Bahn, nicht die Koerperneigung, und dient nur der Diagnose. Der Cursor bleibt in der Tasche auf dem Gegenstand Einfach: Wer in der Taschenliste einen Gegenstand rechts anklickte - benutzen, anlegen, an einen Haendler verkaufen, eine Verzauberung anwenden -, stand danach schlagartig auf dem ersten Eintrag der ganzen Liste. Bei Gegenstaenden, die sofort verschwinden, fiel das kaum auf, weil die Liste sich ohnehin neu sortiert; bei allem anderen war es einfach ein Verlust der Position. Jetzt bleibt der Cursor auf dem Gegenstand, auf dem man gearbeitet hat, und wenn der Gegenstand die Tasche verlaesst, landet man an seinem Platz - also auf dem, was nachgerueckt ist. Technisch: Ursache war nie ein Verrutschen von Indizes, sondern die dritte Zeile des Rechtsklick-Makros, "/script SkuCore:CheckFrames()". Sie stammte aus der Zeit vor der ereignisgesteuerten Bestaetigung und lief BEIM TASTENDRUCK - also bevor die Aktion ueberhaupt etwas veraendert hatte, bei einer Aktion mit Zauberzeit sogar Sekunden davor. Sie baute damit veraltete Daten neu auf und kostete dabei die Position. Entfernt; die Auffrischung gehoert allein der von BAG_UPDATE getriebenen Bestaetigung, die erst aufbaut, wenn die Taschen wirklich ruhig sind, und den Cursor dann ueber Taschen-Fach und Gegenstands-ID wieder anheftet. Zusaetzlich merkt sich CheckFrames beim Neuaufbau nicht mehr nur die Zeilennummer, sondern auch den Namen des Eintrags, und sucht ihn in der neu gebauten Liste - die Zeilennummer allein stimmt naemlich nicht mehr, sobald die Liste zwischendurch eine andere Form hatte. Verzauberungen, Koeder und Oele: die Liste aktualisiert sich nach dem Zauber Einfach: Eine Verzauberung, ein Angelkoeder, ein Waffenoel, ein Ruestungsset oder das Entzaubern veraendern die Taschen erst, wenn der Zauber fertig ist - oft fuenf Sekunden nach dem Klick. Bis dahin hatte Sku laengst aufgegeben: die Liste blieb veraltet, und der Cursor stand irgendwo. Jetzt wartet Sku den Zauber ab, meldet danach den Gegenstand einmal und laesst den Cursor darauf stehen. Wer waehrenddessen selbst weiterblaettert, behaelt seine eigene Position - dann mischt sich Sku nicht mehr ein. Technisch: Das beim Rechtsklick geoeffnete Bestaetigungsfenster lief nach 2,5 Sekunden ab. UNIT_SPELLCAST_START/-CHANNEL_START schieben seine Frist jetzt bis zum Ende des Zaubers und behalten dabei den beim Klick gemerkten Anker, sodass das Wiederanheften danach genau den behandelten Gegenstand trifft. Bewusst ohne Zauberliste: dass das Fenster offen ist, ist bereits der Beleg, dass der Zauber zu dieser Aktion gehoert. Zwei harte Sperren, beide an einem echten Fall gelernt: der Zauber muss innerhalb einer Sekunde auf den Klick folgen ("/use" startet ihn im selben Frame), und die Verlaengerung greift nur ein einziges Mal. Ohne sie schob das 22 Sekunden lange Angeln die Frist immer weiter vor sich her, und das Fenster starb nie. Der Bestaetigungsdialog kostet nicht mehr die Position Einfach: Wer eine Verzauberung auf einen bereits verzauberten Gegenstand anwendet, bekommt von Blizzard die Rueckfrage "Bestehende Verzauberung ersetzen?". Nach "Ja" oder "Nein" stand man anschliessend ganz oben in der Taschenhierarchie, also auf "Tasche 1" statt auf dem Gegenstand. Jetzt fuehrt beide Antworten wieder zum Gegenstand zurueck, und er wird einmal angesagt. Technisch: Der Dialog ist ein modales Fenster zwischen dem Klick und seiner Wirkung und zerstoerte die Position gleich zweifach: die 2,5-Sekunden-Frist lief waehrend des Dialogs ab, und Sku verankert das Menue IM Dialog, sodass beim Schliessen nichts mehr da war, wohin zurueckgekehrt werden konnte - der allgemeine Einstieg nahm dann das einzige offene Fenster und landete oben in der Taschenliste. SkuBagPostActionPopupGate haelt das Fenster offen, solange der Dialog steht (bis 30 Sekunden), und stoesst beim Schliessen die Bestaetigung an. Genau die ist das richtige Werkzeug, weil sie beide Antworten abdeckt: "Nein" erzeugt weder Zauber noch Taschenaenderung, es gaebe also sonst gar nichts, was den Cursor zuruecklegen koennte. Solange der Dialog steht, haelt sich die Bestaetigung komplett zurueck - sonst risse eine unbeteiligte Taschenaenderung (einsammelnde Beute, ein abgeschlossener Handel) den Cursor mitten aus dem Dialog heraus. Der Tippfilter in der Taschenliste loest sich wieder Einfach: Wer in der Taschenliste einen Namen tippt, filtert die Liste auf die Treffer. Dieser Filter loeste sich bisher nicht mehr, sobald man den gefilterten Gegenstand benutzt hatte: auch Pfeil links und wieder rechts brachten die volle Liste nicht zurueck, nur das Schliessen der Taschen half. Jetzt raeumt jede dieser Tasten den Filter wieder ab, so wie man es gewohnt ist. Passt auf den Filter gar nichts, bleibt die Liste weiterhin leer und die Pfeiltasten wiederholen nur den getippten Filter - genau daran hoert man, dass es keinen Treffer gibt. Technisch: SkuOptions:ClearFilter vergass nur den getippten Text; die von ApplyFilter eingesetzte gefilterte Kinderliste blieb im Baum stehen, bis irgendetwas sie vollstaendig ersetzte - und eine aus Spielfenstern gebaute Ebene wie die Taschen kann sich nicht an Ort und Stelle auffrischen, sie braucht einen kompletten Neuaufbau. Jahrelang verdeckt vom erzwungenen CheckFrames im Makro (siehe oben), fiel es sofort auf, sobald eine Aktion die Taschen gar nicht veraendert. ClearFilter stellt die Liste jetzt wirklich wieder her, samt Vor- und Rueckwaertsverkettung, und zwar an dem Knoten, den sie gefiltert hat, nicht am gerade aktuellen. Escape schloss das Menue nicht, wenn man direkt auf einem Questobjekt stand Einfach: Wer mit ungefaehr null Metern Abstand vor einem Questobjekt stand und das Menue mit Escape schloss, bekam das Questfenster sofort wieder aufgezogen - und das endlos. Das Menue liess sich in dieser Lage praktisch nicht mehr schliessen. Jetzt werden erst die offenen Spielfenster geschlossen und danach das Menue selbst. Technisch: Das Menue versteckte sich zuerst und arbeitete danach die offenen Interaktionsfenster ab. Der Quest-Rahmen wurde dadurch geschlossen, waehrend das Spiel den Gegenstand in Reichweite weiter meldete, und zog sich sofort wieder auf. Die Reihenfolge ist jetzt umgekehrt und durch einen Zaehler abgesichert, den "/skucheck menu" ausliest: eine Verletzung dieser Reihenfolge faellt damit auf, ohne dass jemand zufaellig genau auf diesem Fleck stehen muss. Weniger doppelte Neuaufbauten beim Fensterschliessen Einfach: Ein einziges Escape loeste bisher bis zu sechs komplette Neuaufbauten der Menuedaten aus, weil mehrere Fenster gleichzeitig zugehen und Blizzards Questfenster allein schon vier Unterbereiche versteckt. Das kostete spuerbar Zeit. Jetzt laeuft pro Bild genau ein Neuaufbau. Ausserdem konnte die fuer den Kampf vorgehaltene Taschenliste veralten, wenn ein Questfenster geschlossen wurde, waehrend die Taschen offen waren - ein Fehler, der erst spaeter im Kampf aufgefallen waere. Technisch: Die Hide-Pfade laufen ueber SkuCore:CheckFramesCoalesced, dessen Sperre einmal pro Bild oeffnet; der eigentliche Durchlauf ist ohnehin um 0,01 s verzoegert und liest den Endzustand, sieht also genau das, was der letzte Aufruf der Serie gesehen haette. Die OnShow-Seite bleibt bewusst aussen vor. Die Buchhaltung in GENERIC_OnClose hat eine eigene Sperre bekommen: sie hing vorher am Rueckgabewert derselben geteilten Sperre, und da die Quest-Unterbereiche zuerst feuern, verbrauchten diese sie und die Buchhaltung - unter anderem das Auffrischen der Kampf-Taschenliste - fiel aus. Sprachausgabe: Ansagen bleiben nicht mehr stumm Einfach: Beim Navigieren blieb die Sprachausgabe immer wieder fuer eine Weile still - ein Pfeiltastendruck las den Eintrag einfach nicht vor, obwohl es ruhig war und nichts anderes lief. Besonders zuverlaessig passierte das, wenn man eine Liste auf einen einzigen Treffer filterte und dann schnell zwischen dem Filter und diesem Treffer hin und her ging: nach ein paar Wechseln blieb der Treffer dauerhaft stumm, auch wenn man eine Sekunde wartete. Beides ist behoben. Technisch: Zwei voneinander unabhaengige Ursachen, beide unterhalb der Warteschlange - Sku selbst hatte jede Ansage sauber abgeschickt, in einem Mitschnitt ueber 95 Minuten kam auf jeden Tastendruck genau ein SpeakText mit STARTED. Erstens wurde dieselbe Zeile bis zu viermal innerhalb einer Sekunde erneut ausgegeben, weil eine ueberfluessige Fensterpruefung den Menueeintrag noch einmal ansagt; 95 von 1512 Ausgaben waren solche Wiederholungen. Jede bringt ihr eigenes "queuereset" mit, also ein StopSpeakingText, und das erreicht den Screenreader wirklich - die Zeile wurde also mitten im Wort abgeschnitten und neu begonnen, und wenn dabei die Neuausgabe verlorenging, blieb nichts uebrig. Die vorhandene Dopplungssperre konnte das nicht auffangen: sie haengt an VOICE_CHAT_TTS_PLAYBACK_FINISHED, und ueber die Screenreader-Bruecke kommen STARTED und FINISHED noch im selben Bild zurueck - dort ist die Sperre also immer leer und kann gar nicht greifen. Neu ist eine zeitbasierte Sperre, die eine unmittelbar folgende identische Zeile innerhalb einer Sekunde verwirft, und zwar samt ihrem queuereset; nur den Text zu verwerfen wuerde die laufende Ansage trotzdem abschneiden und nichts an ihre Stelle setzen. Verglichen wird ausschliesslich mit der direkt davor ausgegebenen Zeile, ein echtes erneutes Vorlesen kann sie also nicht schlucken, und sie greift nur, wenn die erste Ausgabe wirklich zu spielen begonnen hatte. Zweitens war der Cache-Brecher wirkungslos geworden. Der Client legt erzeugte Sprachdaten nach Text ab und spielt sie bei einer Wiederholung ab, ohne die Stimme erneut aufzurufen - ueber eine Bruecke ist dieses Abspielen still. Dagegen wurde bisher ein wechselndes angehaengt, aber der Client entfernt Auszeichnungen und schluesselt nur ueber den gesprochenen Text: im Mitschnitt trug jede einzelne Ausgabe ihre eigene Markierung und der Treffer verstummte trotzdem. Der urspruengliche Brecher hatte echte Zeichen variiert und funktionierte; der Wechsel auf eine Markierung sollte die Betonung schonen und hat dabei genau den Fehler wieder hereingeholt, gegen den er geschrieben war. Angehaengt wird jetzt wieder echter Text: eine wechselnde Folge von 1 bis 64 geschuetzten Leerzeichen hinter dem letzten Wort, wo sie weder hoerbar ist noch die Betonung faerben kann. Satt: nur noch ein Eintrag in der Zauberauswahl Einfach: Wer eine Aura auf den Satt-Buff bauen wollte, fand in der Zauberauswahl zwei Eintraege, die beide "Satt" gesprochen wurden. Nur einer davon konnte je ausloesen, der andere war eine Karteileiche - welchen man erwischte, war reine Glueckssache und nicht hoerbar. Es gibt jetzt nur noch einen Eintrag, und der ist der richtige. Eine bereits gespeicherte Aura, die auf den falschen zeigte, wird beim naechsten Anmelden einmalig umgehaengt und funktioniert danach. Technisch: Auren werden seit v43.0 ueber die englische Identitaet eines Zaubers gefuehrt, damit dieselbe Aura in jeder Sprache passt. In der mitgelieferten Zauberdatenbank tragen zehn Zeilen den englischen Namen jedoch in ANFUEHRUNGSZEICHEN - 44097 bis 44106 sowie 69559 und 65365 fuehren den Namen einschliesslich zweier Anfuehrungszeichen, wo die anderen 65 Zeilen ihn ohne fuehren. Damit entstand eine zweite Identitaet hinter demselben deutschen Namen, und die Menue-Unterscheidung haengt in so einem Fall die englische Identitaet an: der eine Eintrag hiess "Satt (Well Fed)", der andere genauso, nur mit zwei zusaetzlichen Anfuehrungszeichen um Well Fed herum. Anfuehrungszeichen spricht die Sprachausgabe nicht mit, also klangen beide Eintraege identisch. "Satt" ist der einzige der 26.650 deutschen Namen im Datenbestand, dessen zwei Identitaeten sich in nichts als diesen Zeichen unterscheiden. Der Name wird jetzt beim Bilden der Identitaet entklammert, und zwar auf BEIDEN Seiten - in der Werteliste und bei jeder Aufloesung eines laufenden Ereignisses -, denn nur eine Seite zu aendern wuerde einen gespeicherten Wert erzeugen, den kein Ereignis mehr trifft. Entklammert wird ausschliesslich, was an BEIDEN Enden ein Anfuehrungszeichen traegt; die 17 uebrigen Zeilen mit Anfuehrungszeichen mitten im Namen (etwa "Goblinbummkiste" oder das Parfuem "TRIUMPH") behalten sie, weil sie dort zum Namen gehoeren. Eine einmalige Wanderung haengt gespeicherte Auren um. Waffenverzauberungen sind in der Zauberauswahl erkennbar Einfach: Ein Angelkoeder, ein Schaerfstein oder ein Waffenoel sind keine Buffs, sondern eine Verzauberung auf der Waffe. Sie tauchen in keiner Bufliste des Spiels auf und loesen kein Aura-Ereignis aus - eine Aura auf "Ereignis = Aura verloren und Zauber name = Angelfertigkeit +75" konnte deshalb nie ausloesen, obwohl der Eintrag in der Auswahl steht und voellig normal klingt. Solche Eintraege tragen jetzt in allen Auswahllisten den Zusatz "(Waffenverzauberung)", damit hoerbar ist, worum es sich handelt. Wer darauf reagieren will, nimmt entweder das Ereignis "Waffenverzauberung abgelaufen" oder die Bedingung "Deine Waffenverzauberung Haupthand". In der Ansage einer ausgeloesten Aura wird der Zusatz nicht mitgelesen. Technisch: Die Werteliste des Attributs "Zauber name" ist die komplette Zauberdatenbank, also auch Zeilen, die den Spieler nur als temporaere Waffenverzauberung erreichen - der Koeder ist Zauber 8084 hinter Verzauberungs-ID 265. Die betroffenen Identitaeten werden jetzt beim Aufbau der Listen ermittelt (jede Zauber-ID der Identitaet wird von der Verzauberungsdatenbank referenziert) und bekommen den Zusatz. Bewusst GEKENNZEICHNET statt entfernt: es sind 395 Identitaeten, und sie sind nicht alle wirkungslos - "Feurige Waffe", "Scharfrichter" und "Unheilige Staerke" sind Prozeduren von Verzauberungen, die sehr wohl unter genau diesem Namen im Kampfprotokoll erscheinen. Sie zu entfernen haette funktionierenden Auren ihre einzige Benennungsmoeglichkeit genommen. Der Zusatz nutzt denselben Mechanismus wie die englische Unterscheidung, faellt also in der Sprachausgabe einer ausgeloesten Aura wieder weg. Waffenverzauberungen werden angesprochen wie Zauber Einfach: Fuer einen Schadenszauber ueber Zeit schreibt man "Ereignis gleich aura verloren" und "Zauber name gleich " - das Ereignis sagt selbst, worum es geht. Bei einer Waffenverzauberung ging das nicht: den Angelkoeder konnte man nur ueber "Deine Waffenverzauberung Haupthand" benennen, und das ist eine Zustandsfrage, keine Ereignisfrage. In der Fassung "enthaelt" konnte so eine Aura sogar NIE ausloesen - wenn das Ereignis kommt, ist die Verzauberung bereits weg, also enthaelt die Liste sie nicht mehr. Nur die verdrehte Fassung "enthaelt nicht" funktionierte. Jetzt traegt das Ereignis den Namen der Verzauberung selbst, und die Aura wird genau wie bei einem Zauber geschrieben: "Ereignis gleich Waffenverzauberung abgelaufen" und "Zauber name gleich Angelfertigkeit +75". "enthaelt nicht" funktioniert weiter. Technisch: Die beiden erzeugten Ereignisse WEAPON_ENCHANT_REMOVED und WEAPON_ENCHANT_UPDATE legten den Namen der HAND in Feld 13 - und Feld 13 ist das Zauber-name-Feld. Eine Bedingung auf "Zauber name" verglich also gegen "Haupthand", und eine Ausgabe "Zauber name" sagte "Haupthand" statt der Verzauberung. Dort steht jetzt die Verzauberung: Feld 12 bekommt ihre Zauber-ID, Feld 13 ihren Namen, beides ueber dieselben Resolver, aus denen auch die Auswahlliste gebaut wird - der gespeicherte Wert ist derselbe wie bei der Waffenverzauberungs-Bedingung. Beim Entfernen wird die Verzauberung gemeldet, die DA WAR; das ist die Identitaet, die gemeint ist. Bestehende Auren koennen dadurch nicht verstummen: "Haupthand", "Nebenhand", "Main Hand" und "Off hand" kommen in allen 49.117 Zeilen der Zauberdatenbank kein einziges Mal als Zaubername vor, eine Bedingung auf "Zauber name" konnte bei diesem Ereignis also ohnehin nie zutreffen. Die Hand ist nicht verloren, sie zieht in ein eigenes Feld mit eigener Bedingung und eigener Ausgabe um ("Waffenverzauberung Hand"), gespeichert als sprachneutrale Kennung, damit eine geteilte Aura in jeder Sprache dieselbe Hand meint. NICHT gemacht wurde der naheliegende andere Weg - die Zustandsliste beim Entfernen mit der auslaufenden Verzauberung zu fuellen: die Liste ist geteilt, sie wuerde in diesem Durchlauf JEDE andere Aura anluegen, ein "enthaelt nicht"-Gatter wieder scharf schalten und damit doppelte Ansagen erzeugen, und sie wuerde der Restdauer widersprechen, die beim Entfernen bewusst auf 0 gesetzt wird. Zusaetzlich meldet /skucheck auras die Kombination "Entfernt-Ereignis plus enthaelt" jetzt als Aura, die nie ausloesen kann. Nebenbei behoben: aenderte sich nur die Nebenhand, wurde das Ereignis trotzdem als "Haupthand" gemeldet. Das Ende einer Waffenverzauberung wird sofort erkannt Einfach: Dass ein Angelkoeder oder ein Gift ausgelaufen ist, meldet das Spiel nicht - Sku sieht alle 0,25 Sekunden nach. Die Ansage kam deshalb bis zu eine viertel Sekunde zu spaet. Jetzt kommt sie im Moment des Ablaufs. Technisch: Wie lange eine Verzauberung noch haelt, steht in dem Moment fest, in dem man sie sieht - GetWeaponEnchantInfo liefert die Restzeit in Millisekunden. Der Ticker merkt sich daraus den naechsten Ablaufzeitpunkt, und der Frame-Treiber vergleicht eine Zahl pro Frame und ruft dann genau den normalen Spieler-Ticker auf. Das ist dieselbe Bauart wie der in v43.0 eingefuehrte Dauer-Terminplaner und kostet kein zusaetzliches Abfragen. Doppelte Ansagen sind ausgeschlossen, weil der Ticker nur meldet, wenn sich sein gemerkter Stand wirklich geaendert hat. Bewusst NICHT gemacht: den Ticker auf jeden Frame zu stellen - das waere fuenfzehnmal so viel Abfragerei fuer denselben Gewinn. Umschalten in einer gefilterten Liste sagt wieder den neuen Zustand an Einfach: Grenzt man eine Liste per Tippfilter ein und drueckt dann Enter auf einem Ein/Aus-Eintrag, wird der Filter entfernt - das ist so gewollt. Der Eintrag wurde auch richtig umgeschaltet, nur zu hoeren war das nicht: der Cursor sprang dabei an den Anfang der Liste, und angesagt wurde der erste Eintrag statt des neuen Zustands. In den Auren-Ausgaben spielte zusaetzlich die Hoerprobe des ersten Eintrags an. Jetzt bleibt man auf dem Eintrag stehen, den man umgeschaltet hat, und hoert seinen neuen Zustand. Technisch: Enter entfernt den Filter, BEVOR es die Aktion ausfuehrt - der Menue-Knoten ruft dafuer ApplyFilter("") auf. Dessen Aufraeumen endete mit einem pauschalen OnFirst() auf der Ebene, der Cursor wanderte also in JEDEM Fall an den Listenanfang. Die Umschaltung selbst war nie betroffen: sie arbeitet auf dem Knoten selbst (actionInPlace), nicht auf dem Cursor. Falsch war nur, was danach vorgelesen wurde - und OnFirst loeste beim Landen zusaetzlich das OnEnter des ersten Eintrags aus, was bei den Auren-Toenen die Hoerprobe ist. ApplyFilter("") folgt jetzt derselben Regel, der ClearFilter schon folgt: die wiederhergestellte Liste enthaelt dieselben Knoten-Objekte, ein Cursor auf einem echten Eintrag bleibt also gueltig; nur die kuenstliche Zeile "Filter;" hat dort keinen Platz mehr, und allein fuer sie laeuft weiterhin das vollstaendige OnFirst() samt OnEnter, damit die Hoerprobe beim Landen nicht verloren geht. Ohne aktiven Filter war ApplyFilter("") immer schon wirkungslos - deshalb hat das Umschalten in einer ungefilterten Liste nie gefehlt; beide Faelle verhalten sich jetzt gleich. Nebenwirkung derselben Regel: Backspace laesst den Cursor jetzt auf dem Eintrag stehen, auf dem er stand, statt an den Listenanfang zu springen. Dungeonbrowser: eine angenommene Einladung fuehrt nicht mehr in den Browser Einfach: Wer im Dungeonbrowser angemeldet war und dann eine Gruppeneinladung annahm, stand danach ohne einen einzigen Tastendruck im Dungeonbrowser: das Menue ging von selbst wieder auf, der Cursor stand auf "Nicht angemeldet". Fuer sehende Spieler passiert an dieser Stelle nichts - Blizzards Gruppensuche-Fenster geht beim Annehmen einer Einladung nie auf. Jetzt bleibt es auch bei Sku still: man bleibt dort, wo man vorher war. Technisch: Zwei Wege fuehrten dorthin, beide sind jetzt zu. (1) Sobald der Server die eigene Anmeldung loescht - genau das tut er, wenn man einer Gruppe beitritt -, kommt LFG_LIST_ACTIVE_ENTRY_UPDATE, und der Browser baute daraufhin seinen Menuepunkt neu auf. Dieser Neuaufbau endete mit einem SlashFunc auf den eigenen Menuepfad, und der oeffnet ein GESCHLOSSENES Menue wieder und steigt hinein. Er laeuft jetzt nur noch, wenn das Menue offen ist UND der Cursor tatsaechlich im Dungeonbrowser steht - nur dann muessen die neu gebauten Eintraege ueberhaupt wieder unter den Cursor gelegt werden. Faellt er aus, kostet das nichts: der Menuepunkt ist "dynamic" und baut sich beim naechsten Betreten ohnehin neu auf. Damit kann auch keine Anmeldungsaenderung, die man nicht selbst ausgeloest hat (Ablauf, Aenderung durch den Gruppenanfuehrer), einen mehr aus den Taschen in den Browser reissen. (2) Eine drittel Sekunde nachdem das Einladungsfenster verschwunden ist, prueft der Browser, ob er sich wieder oeffnen soll. Er fragte dabei nur "ist gerade irgendein Gruppensuche-Fenster offen?" und machte daraus ein Oeffnen. Jetzt wird beim EINTREFFEN der Einladung gemerkt, was vorher da war, und nur genau das wird wiederhergestellt. Hat die Einladung in eine Gruppe gefuehrt, geschieht gar nichts mehr - weder oeffnen noch schliessen. Neuer Tastenbefehl: den vollstaendigen Tooltip des Ziels vorlesen Einfach: Bei einem Zielwechsel sagt Sku eine feste, kurze Auswahl an - Name, Stufe, Elite oder Selten, dazu die zweite Tooltip-Zeile mit der Kreaturenart. Alles, was darunter im Tooltip steht, war bisher gar nicht erreichbar: die Fraktionszeile, die PvP-Kennzeichnung und vor allem das, was die Jaegerfaehigkeit Tierkunde bei einem Wildtier offenlegt - Familie, Nahrung und ob es zaehmbar ist. Der neue Tastenbefehl (Standard: Strg+Umschalt+V) liest auf Wunsch den kompletten Tooltip vor. Er wirkt ausschliesslich auf Tastendruck: die normale Zielansage bleibt unveraendert kurz, und wer die Zusatzinformation nicht braucht, hoert nie etwas davon. Genau deshalb gibt es dafuer auch keine Option - der Tastendruck selbst ist die Nachfrage. Ist kein hartes Ziel vorhanden, gilt der Befehl dem aktuellen Soft-Ziel, sodass sich auch etwas beschreiben laesst, auf das man sich noch gar nicht festgelegt hat. Umzubelegen unter Sku Tastenbelegung, Ziel und Soft Targeting. Technisch: Idee, Nachweis und Referenzumsetzung stammen von ZenqFR, aus dem Begleit-Addon SkuBeastLore (github.com/ZenqFR/Sku-BeastLore); die Tierkunde-Ausgabe ist dort an einem echten Jaeger getestet worden. Hier ist die Funktion nativ gegen Skus eigene Schnittstellen neu gebaut, damit kein zusaetzliches Addon noetig ist. Die Tierkunde-Zeilen erzeugt der Client selbst im Unit-Tooltip; kein Lua der Blizzard-Oberflaeche baut sie, und keine Programmschnittstelle liefert sie einzeln - den Tooltip zu lesen ist der einzige Weg dorthin. Deshalb ist eine getrennte Option nur fuer die Jaegerinformation auch nicht moeglich: die Zeilen liessen sich nur ueber sprachabhaengigen Textvergleich herausloesen. SkuMob:OutputTargetTooltip loest target, softenemy, softfriend und softinteract der Reihe nach auf und liest ueber Skus gemeinsam genutzten SkuScanningTooltip. Weil dieser Frame geteilt ist - Taschen, Auktionshaus, Chatlinks und Questtexte lesen denselben -, wird davor UND danach geleert und der Besitzer exakt so wiederhergestellt, wie SkuCore ihn beim Anmelden setzt. Quests verfolgen und wieder abwaehlen Einfach: Im Menue jeder Quest steht jetzt als letzter Eintrag "Quest verfolgen". Enter schaltet ihn um, der Cursor bleibt stehen, und der neue Zustand wird sofort angesagt - "Quest verfolgen;Ein" oder "Quest verfolgen;Aus". Verfolgt heisst: WoWs eigene Markierung auf der Mini- und der Weltkarte. Wer noch etwas sieht, findet Questziele damit schneller; wer nichts sieht, hat von den Markern nichts. Deshalb laesst sich der Eintrag komplett abschalten - unter Sku Einstellungen, SkuQuest, "Eintrag Quest verfolgen anzeigen"; ab Werk ist er an. Er erscheint nur bei Quests im eigenen Questlog, denn eine Quest aus der Questdatenbank hat man noch gar nicht. Zwei Grenzen setzt das Spiel selbst: in The Burning Crusade lassen sich hoechstens fuenf Quests gleichzeitig verfolgen, und eine Quest ganz ohne Ziele gar nicht. In beiden Faellen sagt Sku die Meldung des Spiels an und der Zustand bleibt, wie er war. Technisch: Idee und Referenzumsetzung stammen von ZenqFR, aus dem Begleit-Addon SkuQuestNearby (github.com/ZenqFR/Sku-QuestNearby); hier ist die Funktion mit ZenqFRs Zustimmung nativ gegen Skus eigene Schnittstellen neu gebaut, damit kein zusaetzliches Addon noetig ist. Der Eintrag haengt im chunk-lokalen CreateQuestSubmenu statt an einem Hook auf dem oeffentlichen Wrapper - deshalb bekommt ihn jede Questansicht: Questlog, Questdatenbank und die Questmenues von SkuChat. Auf 2.5.6 gibt es kein C_QuestLog: AddQuestWatch, RemoveQuestWatch und IsQuestWatched nehmen einen Questlog-Index, keine Quest-ID, und dieser Index verschiebt sich bei jeder angenommenen oder abgegebenen Quest. Sku haelt darum eine Zuordnung Quest-ID auf Index, prueft den gemerkten Index bei jedem Lesen nach und verwirft die Zuordnung bei den Questereignissen; ohne diesen Zwischenspeicher liefe die Liste "Questdatenbank, Alle" einen vollen Questlog-Durchlauf pro Quest. Eingeschaltet wird ueber AutoQuestWatch_Insert mit QUEST_WATCH_NO_EXPIRE, damit die Quest in QUEST_WATCH_LIST landet und kein Ablauftimer sie wieder herausnimmt; beim Abwaehlen wird zuerst der Eintrag aus QUEST_WATCH_LIST entfernt und dann RemoveQuestWatch gerufen - genau wie in Blizzards eigenem Klickpfad, sonst zaehlt eine laengst nicht mehr verfolgte Quest weiter gegen das Limit von fuenf. QuestWatch_Update laeuft nur ausserhalb des Kampfes, weil es am Ende geschuetzte Frames verschiebt; das naechste QUEST_LOG_UPDATE holt es ohnehin nach. Neuer Tastenbefehl "Naechstes Questziel ins Ziel nehmen" (Alt+H) Einfach: Ein Druck nimmt eine Kreatur ins Ziel, die zu einem noch offenen Questziel gehoert - und zwar auch dann, wenn man sie gar nicht toeten muss, sondern sie nur einen benoetigten Gegenstand fallen laesst. Beispiel: fuer "Essenzen fuer die Motoren" nennt das Questlog nur den Gegenstand; die Taste nimmt trotzdem das Managespenst ins Ziel, das ihn fallen laesst. Passt nichts in Reichweite, sagt Sku "kein Questziel in Reichweite"; ist im Questlog ueberhaupt nichts Passendes, "kein Questziel im Questlog". Die Taste liegt ab Werk auf Alt+H und laesst sich unter Sku Tastenbelegung, "Ziel und Soft Targeting" umlegen. Technisch: Idee und Referenzumsetzung stammen von ZenqFR, aus dem Begleit-Addon SkuQuestTarget (github.com/ZenqFR/Sku-QuestTarget); hier ist die Funktion mit ZenqFRs Zustimmung nativ neu gebaut, damit kein zusaetzliches Addon noetig ist. Die Kandidaten kommen aus dem eigenen Questlog ueber SkuQuest:GetQuestTargetIds; Gegenstandsziele werden ueber die Fallquelle (npcDrops, eine Ebene tief auch itemDrops) auf die Kreaturen zurueckgefuehrt, die sie fallen lassen. Gesucht wird zuerst in der Zone, in der man selbst steht - wer dort keinen Spawnpunkt hat, kann gar nicht in Zielreichweite sein und darf keinen Platz im Makro belegen; erst wenn in der eigenen Zone nichts hinterlegt ist, wird ueber den ganzen Kontinent sortiert. Die Entfernung nimmt den naechstgelegenen aufgezeichneten Spawnpunkt, nicht den ersten der Liste. Das Makro ist mehrzeilig, und dabei entscheidet eine Eigenheit des Spiels: jede passende Zeile feuert, und jeder Treffer ueberschreibt den vorherigen - es gewinnt also die LETZTE. Aufgenommen wird deshalb von nah nach fern, damit das Laengenbudget nur Weitentferntes kappt, ausgegeben aber umgekehrt, damit der naechstgelegene Kandidat die letzte Zeile ist. Gebaut wird ausserhalb des Kampfes bei jedem Tastendruck; im Kampf feuert der zuletzt gebaute Text. "Naechster Gegner im Kampf" findet auch, was man nicht anschaut (Strg+H) Einfach: Die Taste konnte bisher nur finden, was man ohnehin anschaut - stand derselbe Gegner fuenf Meter hinter einem, meldete sie nichts. Das ist keine Einstellung, sondern das Verhalten der Tabulator-Zielsuche des Spiels. Sku merkt sich deshalb jetzt die Namen feindlicher Kreaturen, an denen man vorbeikommt, und probiert sie zusaetzlich ueber den Namen - und ein Name funktioniert in jede Richtung. In der Praxis heisst das: was man einmal gesehen, angegriffen oder ins Ziel genommen hat, bleibt zwei Minuten lang von ueberall aus erreichbar, auch weggedreht. Ausserdem beginnt die Suche jetzt bei jedem Druck beim naechstgelegenen Gegner, statt im Kreis weiterzuspringen. Die Taste liegt ab Werk auf Strg+H. Technisch: Die Anregung stammt aus ZenqFRs SkuQuestTarget, das denselben Weg fuer seine Nebenfunktion benutzt. /targetenemy ist Tabulator und sucht im Sichtkegel - daran ist nichts zu aendern. "/tar Name" dagegen sucht ueber die Namensliste des Clients und ist richtungsunabhaengig, braucht aber einen Namen, und es gibt keine Schnittstelle, die Einheiten hinter einem aufzaehlt. Sku sammelt die Namen deshalb laufend aus vier Quellen: feindliche Namensplaketten, das eigene Ziel, die Einheit unter dem Mauszeiger und die Gegnerliste der Kampfueberwachung. Das Einsammeln laeuft im Sekundentakt, solange die Taste belegt ist, denn eine Plakette gibt es nur, solange die Kreatur im Blick ist - genau dann braucht man die Taste aber nicht. Dort werden nur Namen gesammelt; die teure Entfernungsmessung laeuft einmal pro Tastendruck. Gemerkte Namen halten zwei Minuten. Das Makro ist "/cleartarget", dann "/targetenemy", dann die gemerkten Namen von fern nach nah - die letzte passende Zeile gewinnt, also der naechstgelegene. Neue Liste "Quests in der Naehe" Einfach: Im Questmenue steht als dritter Eintrag, nach "Aktuelle Quests" und "Questdatenbank", jetzt "Quests in der Naehe". Darin liegt das ganze Questlog in EINER Liste - angefangene und fertige gemischt -, sortiert danach, wie weit das weg ist, worum es bei der jeweiligen Quest gerade geht. Jeder Eintrag nennt zuerst die Entfernung, dann die Himmelsrichtung, dann die Art und dann den Questnamen, also etwa "180 Meter; nordost; Questziel; Diebische Kobolde" oder "340 Meter; sued; Questabgabe; Der Wolfsrudelfuehrer". Bei einer Quest, die noch offene Ziele hat, ist das die Entfernung zum naechsten Ziel; bei einer fertig gemeldeten Quest die Entfernung zur Abgabestelle. "Aktuelle Quests" gruppiert nach den Ueberschriften des Questlogs, sortiert also nach Zone - die neue Liste beantwortet dagegen die Frage "was ist von hier aus das Naechste". Enter oeffnet dasselbe Questmenue wie ueberall sonst, samt Wegpunkten und dem Eintrag "Quest verfolgen". Die Liste ist ab Werk AUS und wird unter Sku Einstellungen, SkuQuest, "Eintrag Quests in der Naehe anzeigen" eingeschaltet: sie rechnet bei jedem Oeffnen das ganze Questlog gegen Skus Spawn-Datenbank durch, und das soll nur zahlen, wer sie auch benutzt. Wo Skus Daten keinen Ort hergeben, steht statt der Entfernung "Ort unbekannt", und die Quest rutscht ans Ende - sie verschwindet nicht. Technisch: Idee und Referenzumsetzung stammen von ZenqFR, aus dem Begleit-Addon SkuQuestNearby (github.com/ZenqFR/Sku-QuestNearby); hier ist die Funktion mit ZenqFRs Zustimmung nativ neu gebaut, damit kein zusaetzliches Addon noetig ist - insbesondere ohne Questie und ohne GatherMate2. Die Rechnung liegt in der neuen Datei SkuQuest/Proximity.lua und ist zustandslos. Zwei Stufen, und die Reihenfolge ist der Punkt: zuerst der naechstgelegene aufgezeichnete Spawnpunkt IN DER Zone, in der man selbst steht - die Auswahl laeuft billig in Kartenkoordinaten, nur der Gewinner wird einmal in Weltkoordinaten umgerechnet; erst wenn das nichts hergibt, das Minimum ueber alle Zonen desselben Kontinents. Ein anderer Kontinent ist keine ungenaue Entfernung, sondern gar keine, und bleibt draussen. Gegenstandsziele werden ueber die Fallquelle auf Kreaturen und Weltobjekte zurueckgefuehrt, Erkundungsziele ueber die hinterlegten Koordinaten. Anders als beim Wegpunkt-Pfad werden ALLE Ziellisten einer Quest gelesen, nicht nur die erste nichtleere - eine Quest mit "toete acht Woelfe UND sammle fuenf Felle" haette sonst nur die Woelfe. Gefiltert wird nur nach ZIELART: welche Arten noch offen sind, sagt Blizzards eigene Fortschrittsanzeige ("monster", "item", "object"), und die passt eins zu eins auf die drei Listen; ein Abgleich Zeile gegen einzelnen Datenbankeintrag waere dagegen geraten, weil beide Reihenfolgen nirgends aneinander gebunden sind. Pro Quest und Art werden hoechstens zwoelf IDs durchgerechnet - die Grenze ist das Skript-Budget der Hardcore-Realms, nicht die letzte Nachkommastelle. Die Himmelsrichtung kommt aus denselben Weltkoordinaten, ueber dieselbe Funktion, die auch die Wegpunktlisten und der Minimap-Scanner benutzen. Bewusst die Himmelsrichtung und nicht eine Uhrzeit: eine Uhrzeit gilt relativ zur Blickrichtung und waere falsch, sobald man sich dreht - die Liste wird aber einmal gebaut und dann durchgelesen. Questdatenbank: "Start in Zone" ohne Zwischenebene Einfach: Unter "Questdatenbank, Start in Zone" lag bisher noch genau ein Eintrag, "Nach Entfernung", und darin erst die Quests. Eine Ebene, in der es nichts zu waehlen gibt, ist nur ein Tastendruck. Die Liste steht jetzt direkt unter "Start in Zone". Ausserdem war diese Liste kaputt: sie brach nach der ersten Quest ab, man bekam also genau einen Eintrag statt aller Quests der Zone. Technisch: Die Zwischenebene stammte daher, dass daneben einmal eine zweite Sortierung ("Nach Schwierigkeit") stehen sollte; deren Baustelle stand seit Jahren auskommentiert daneben und wurde nie gebaut. Der Abbruch kam von einer Zeile "tcount = tcount + 1" im Aufbau der Liste: tcount war dort keine lokale Variable, sondern eine nie gesetzte globale, das Hochzaehlen also ein Fehler auf nil. Ein Fehler im Kindaufbau eines Menues wird verschluckt - der Aufbau endete damit stillschweigend nach dem ersten Eintrag. Der Zaehler wurde von nichts gelesen und ist ersatzlos entfernt. Alles in der Bank in einer Liste, und die Bank wird auch unter Bagnon erkannt Einfach: Im Taschenmenue gab es "alle taschen" - eine flache Liste ueber alle Taschen hinweg, nach Namen sortiert. Fuer die Bank gab es das nicht: an der offenen Bank standen zwar "Bank" und "Bank Tasche 1" bis "Bank Tasche 7" im Menue, aber wer etwas suchte, musste jedes Fach einzeln durchgehen. Jetzt steht direkt hinter "alle taschen" der Eintrag "alle bank", solange die Bank offen ist: alles, was in der Bank liegt, in einer Liste, mit demselben Tippfilter. Strg+Eingabe holt einen Gegenstand von dort in die Taschen - genau wie bisher schon in den einzelnen Bankfaechern. Ausserdem erkennt Sku jetzt an den Meldungen des Spiels selbst, ob die Bank offen ist, und nicht mehr am Fenster von Blizzard. Wer ein Taschen-Ersatz-Addon wie Bagnon benutzt, das dieses Fenster versteckt, hatte bisher gar keine Bank im Menue - Sku hielt sie fuer geschlossen und liess saemtliche Bankfaecher verschwinden. Dafuer ist jetzt kein Bruecken-Addon mehr noetig. Technisch: Die Anregung stammt aus ZenqFRs Begleit-Addon SkuBagnonBridge (github.com/ZenqFR/Sku-BagnonBridge), das dieselbe Luecke auf seine Weise schliesst und die Bank ebenfalls ueber die Ereignisse des Spiels erkennt; hier ist mit ZenqFRs Zustimmung der Teil nativ gebaut, der ohne ein weiteres Addon auskommt. Die flache Liste war auf die Taschen 0 bis 4 begrenzt; die Bankbehaelter (-1, -3, 5 bis 11) wurden nie in sie kopiert. Sie sammeln sich jetzt in einer eigenen Liste, absichtlich getrennt von der Taschenliste: aus dieser leitet sich SkuCore.combatBagOrder ab, die Spiegelung fuer den Kampf, und die kann von Haus aus nur Taschenfaecher benutzen. Die Eintraege der neuen Liste sind Kopien derselben Fach-Eintraege und tragen Tasche und Fach mit, also greifen alle vorhandenen Aktionen unveraendert. Der Zustand der Bank haengt jetzt an BANKFRAME_OPENED und BANKFRAME_CLOSED: beide kommen aus der Interaktion mit dem Bankier selbst und sind unabhaengig davon, wer das Fenster zeichnet. Beim Laden und nach /reload wird der Zustand zurueckgesetzt, und die alte Fensterpruefung bleibt zusaetzlich erhalten - die Erkennung kann dadurch nur mehr Faelle richtig treffen als vorher, keine weniger. Loeschen eines eigenen Wegpunkts raeumte den falschen Eintrag ab Einfach: Beim Loeschen eines selbst angelegten Wegpunkts wurde intern nicht dessen eigene Kennung aus einer Nachschlagetabelle entfernt, sondern die eines anderen Wegpunkts. Ausserdem meldete "/skucheck wp" vier Fehler bei den vier Schnellwegpunkten, obwohl mit ihnen alles in Ordnung war. Technisch: Die wpId ist die Identitaet eines Wegpunkts - die Verbindungstabelle ist ueber sie verschluesselt -, keine Beschreibung seines Ortes. Die in ihr steckende Gebiets-ID stammt aus dem Moment des Cache-Aufbaus und bleibt stehen, wenn ein eigener Wegpunkt umzieht; genau das passiert den vier Schnellwegpunkten bei jedem Ladebildschirm, denn dabei werden sie auf die Spielerposition neu gesetzt. Die Pruefung baute die Kennung aus dem aktuellen areaId des Datensatzes neu auf und verglich - sie rechnet jetzt mit der in der Kennung selbst steckenden Gebiets-ID. Der Loeschpfad baute die Kennung ueber ".areaid" (das Feld heisst areaId), also mit Gebiet 1 statt des echten, und raeumte damit den Eintrag desjenigen Datensatzes ab, dem dieser Schluessel wirklich gehoert; er benutzt jetzt die gespeicherte Kennung. Die Chateingabe ist bedienbar geworden Einfach: Die Chatzeile war das einzige Eingabefeld in Sku, in das man blind tippte. Es gab einen Ton beim Oeffnen und einen beim Schliessen, sonst nichts - kein Zeichen-Echo, kein Vorlesen unter dem Cursor, und keine Auskunft darueber, wohin die Nachricht eigentlich ginge. Jetzt verhaelt sie sich wie jedes andere Sku-Eingabefeld. Jedes getippte und geloeschte Zeichen wird gesprochen, Pfeil links und rechts lesen das Zeichen unter dem Cursor und mit Strg das ganze Wort, Pfeil hoch holt die zuletzt gesendeten Nachrichten zurueck - zum erneuten Absenden oder zum Aendern - und sagt dabei den Kanal mit, denn den sieht man einer zurueckgeholten Zeile nicht an. Angesagt wird der Kanal ausserdem beim Oeffnen und bei jedem Wechsel, aber bewusst nicht bei "Sagen": das ist der harmlose Fall, und ihn jedes Mal vorzusagen waere nur Geraeusch. Wem die Kanalansage im eigenen Ablauf nicht passt, schaltet sie in den Chat-Einstellungen unter "Kanal der Chateingabe ansagen" ab, ab Werk ist sie an; das nimmt dann auch den Kanal vor der mit Pfeil hoch zurueckgeholten Zeile weg. Ein Gegenstand im Chat zaehlt beim Lesen als ein einziges Zeichen statt als fuenfundsechzig Zeichen Steuerkram. Und ein vertippter Befehl wie "/tets" sagt jetzt "Unbekannter Befehl", statt einfach nichts zu tun. Technisch: Das Tastatur-Echo der Sku-eigenen Felder haengt ueber SkuOptions:AttachInputEcho jetzt auch an fremden. Drei Dinge sind dort anders: angehaengt wird mit HookScript statt SetScript, weil auf Blizzards Feld dessen eigene Handler fuer Verlauf und Namensvervollstaendigung liegen; die Vorlage traegt ignoreArrows, weshalb schlichte Pfeile an das Spiel gingen und der Textcursor ALT brauchte - das wird zurueckgedreht; und scharf geschaltet wird am Fokus, weil ein fremdes Feld kein Oeffnen-und-Schliessen-Paar hat, an dem das Echo haengen koennte. Der Kanal wird aus der Kopfzeile der Eingabe gelesen statt aus chatType nachgebaut - die Kopfzeile ist bereits uebersetzt und deckt Fluesterziele, nummerierte Kanaele und Blizzards eigene Umschaltungen mitten im Aufruf ab. Ihre Ansage laeuft verzoegert und in einem einzigen Slot, denn jeder Kanalwechsel wird durch einen Tastendruck ausgeloest, und dessen Zeichen-Echo hatte die Ansage sonst jedes Mal aus der Warteschlange geworfen, bevor sie ueberhaupt gesprochen war. Gegenstandslinks werden als Name gelesen, nicht als Farbcode Einfach: Ein Gegenstand - im Chat, in der Post, in der Beute - wurde als lange Folge aus Farbcodes, Kennungen und Doppelpunkten vorgelesen statt schlicht als sein Name. Technisch: In der Sprachausgabe wurden erst alle senkrechten Striche durch Leerzeichen ersetzt und DANACH die Funktion gerufen, die Farbcodes, Links und Texturen entfernt. Deren Muster suchen alle nach einem senkrechten Strich, den es zu dem Zeitpunkt nicht mehr gab - sie liefen also seit jeher ins Leere. Reihenfolge getauscht; der pauschale Ersatz ist jetzt nur noch ein Auffangnetz dahinter. Questdatenbank: "Start in Zone" nennt auch die Himmelsrichtung Einfach: Die Liste der Quests, die in dieser Zone beginnen, sagte bisher nur, wie weit der Questgeber entfernt ist. Jetzt sagt sie wie die Liste "Quests in der Naehe" auch, in welcher Richtung er liegt - erst die Entfernung, dann die Himmelsrichtung. Technisch: Die Weltkoordinaten des Questgebers lagen in dieser Liste ohnehin schon vor; die Richtung kommt aus derselben Funktion, die auch die Wegpunktlisten benutzen. Bewusst die Himmelsrichtung und nicht die Uhrzeit: eine Uhrzeit gilt relativ zur Blickrichtung und waere falsch, sobald man sich dreht, waehrend diese Liste einmal gebaut und dann durchgelesen wird. Die Quest-ID eines Eintrags kommt jetzt direkt aus der Zeile statt aus einer Nachschlagetabelle, deren Schluessel der alte Beschriftungstext ohne Richtung war. ------------------------------------------------------------------------------------------------------- Tastatur-Echo: Zeichen kommen sofort Einfach: Beim Tippen in ein Eingabefeld kamen die Buchstaben nicht im Takt der Finger: manche wurden verschluckt, andere kamen deutlich zu spaet, und Doppelbuchstaben wie in "Wasser" oder "alle" waren regelmaessig nur einmal zu hoeren. Jetzt kommt jedes getippte Zeichen sofort, und ein zweimal gedrueckter Buchstabe wird auch zweimal gesprochen. Technisch: Das Echo lief bisher durch dieselbe Warteschlange wie jede Menueansage, und die ist fuer Ansagen gebaut, nicht fuer Tastendruecke. Sie sammelte Zeichen eine Zehntelsekunde lang und sprach sie ueberschreibend - und Ueberschreiben heisst hier: erst StopSpeakingText, dann noch einmal eine Zehntelsekunde warten, damit dieser Stop nicht ausgerechnet die Ansage abraeumt, fuer die er Platz machen soll. Beides nacheinander sind rund 0.2 Sekunden je Anschlag, und der Stop des einen Anschlags landete regelmaessig auf dem naechsten. Dazu kam die in dieser Version neu eingefuehrte Dublettensperre der Sprachausgabe, fuer die ein einzelnes Zeichen als Aeusserung mit sich selbst identisch ist - daher die verschluckten Doppelbuchstaben. Getippte Zeichen laufen jetzt ueber eine eigene Schnellspur: ein einziger Platz, in dem der neueste Anschlag gewinnt, Ausgabe im selben Frame, der Stop nur noch einmal zu Beginn einer Tippfolge statt bei jedem Anschlag, und die Dublettensperre sieht getippte Zeichen gar nicht mehr. Hintergrund: ein Bildschirmleser braucht so etwas nie, weil seine Schnittstelle das Abbrechen als Teil des Sprechbefehls anbietet - eine einzige Operation. Die Schnittstelle des Spiels kann das nicht, also muss Sku sie aus zwei Aufrufen nachbauen, die einander ueberholen koennen. Neu ist, das nur noch einmal je Tippfolge zu tun. Eine per Taste erneut angeforderte Zeile wird wieder gesprochen Einfach: Wer eine Menuezeile per Tastendruck noch einmal hoeren wollte, bekam gelegentlich Stille - die Sprachausgabe hielt die Wiederholung fuer ueberfluessig. Technisch: Die Dublettensperre verwirft eine Zeile, die innerhalb einer Sekunde genauso schon einmal gesprochen wurde. Das ist richtig fuer den ueberfluessigen Nachschlag eines Menue-Neuaufbaus und falsch fuer denselben Text, den der Nutzer gerade per Taste angefordert hat. Am Text sind die beiden nicht zu unterscheiden, und keine Zeitspanne trennt sie - nur der Ausloeser. Die Tastenauswertung des Menues markiert ihre Ansage deshalb jetzt als tastenausgeloest, und die Sperre laesst markierte Zeilen immer durch. Ueberfluessige Wiederholungen werden weiterhin verworfen, jetzt unabhaengig davon, wie schnell sie eintreffen. Quests mit gemischten Zielen zeigen alle Zielarten Einfach: Bei einer Quest wie "toete 8 Woelfe UND sammle 5 Felle" zeigte der Eintrag "Ziel" im Questmenue nur die erste Zielart - meist die Gegner; die Fundorte des Sammelgegenstands oder ein Erkundungspunkt fehlten still. Betroffen waren 95 Quests. Jetzt stehen alle Zielarten nebeneinander in einer Liste, und auch der Tastenbefehl "Naechstes Questziel ins Ziel nehmen" kennt bei solchen Quests beide Haelften. Nebenbei behoben: eine Quest, die nur einen Erkundungspunkt und sonst keine Zieldaten hat, bekommt ueberhaupt erst einen "Ziel"-Eintrag, und ein nicht aufloesbarer Erkundungspunkt erzeugt keinen Eintrag mehr, der nur noch "leer" ansagt. Technisch: SkuQuest:GetQuestTargetIds war eine elseif-Kette ueber die Ziellisten der Questdatenbank (Kreaturen, sonst Objekte, sonst Gegenstaende, ...) und konnte schon per Signatur nur EINE Liste mit EINEM Typ zurueckgeben. Ersetzt durch GetQuestTargetGroups: ein Feld von Gruppen {targets, type} - Kreaturen samt deduplizierten Toetungs-Credits, Objekte, Gegenstaende und, nur fuer die objectives-Aufrufer, der triggerEnd-Punkt der Quest. Alle sieben Aufrufer sind umgestellt (Questmenue, Wegpunkt-Cache, Questmarker, Questziel-Taste); der alte Name bleibt als Erste-Gruppe-Wrapper fuer den WowVision-Port stehen. Dazu ist der item-Zweig von GetResultingWps gegen unbekannte Gegenstands-IDs abgesichert: der indizierte bisher ungeprueft und liess den verschluckten Menueaufbau als stilles "Liste leer" sterben. Questdatenbank auf den aktuellen Questie-Stand gebracht Einfach: Skus eingebaute Questdatenbank stammt von Questie und war rund zwei Jahre alt. Nach dem Abgleich haben 33 Quests, deren "Ziel" bisher leer blieb, echte Ziele (die Dunkelmond-Kartensets, die wiederholbaren Ogri'la- und Violettes-Auge-Quests, "Den Schluesselmeister finden"), die sechs "Untersucht die Geissel"-Quests haben jetzt Erkundungspunkte, fuenf fehlende Quests sind ergaenzt, und rund 2000 Datensaetze tragen kleinere Korrekturen an Namen, Stufen, Questgebern und Vorquest-Ketten. Geprueft: die Korrekturen sind fuer Era und TBC identisch, die Aktualisierung ist auf beiden sicher. Technisch: Semantischer Abgleich statt Byte-Kopie (neues Werkzeug dev/rework-docs/_refresh_questdata_from_questie.py, danach _db_convert.py): Questies Schema divergiert ab Feld 27, uebernommen werden nur die Felder 1-26; Skus eigene Felder extraObjectives und skuData bleiben je Datensatz erhalten. Die requiredRaces-Konvention (alte Alle-Rassen-Maske 2047, neu 0 - fuer Skus Logik dasselbe) gilt beim Vergleich als gleich, sonst haetten 2117 Datensaetze ohne inhaltliche Aenderung im Diff gestanden. Jede referenzierte Kreatur-, Objekt- und Gegenstands-ID wurde gegen die mitgelieferten Datenbanken (Basis + WotLK) validiert; ein Datensatz blieb deshalb beim alten Stand. Ereignisquests tauchen direkt nach dem Laden nicht mehr auf Einfach: In den ersten Sekunden nach einem /reload konnten in "Start in Zone" Quests inaktiver Weltereignisse auftauchen - etwa Sonnenwendquests im August. Sobald Questie fertig geladen war, verschwanden sie von selbst wieder; jetzt sind sie auch in diesem Zeitfenster ausgeblendet. Technisch: Die beiden Verfuegbarkeits-Tore fragten Questie erst ab Questie.started, und das Flag kippt ganz am Ende von Questies Initialisierung. Questies statische Ausschlussliste QuestieCorrections.hiddenQuests - entfernte Quests plus ALLE Ereignisquests; die aktiven werden erst nach der Kalender-Antwort des Servers freigeschaltet - existiert aber viel frueher. IsQuestieUnavailable liest sie vor started jetzt direkt: das ist ein reiner Tabellenzugriff, die Memoize-Vergiftungsgefahr hinter dem started-Tor betrifft nur IsDoable. Der Wert "HIDE_ON_MAP" wird wie bei Questie selbst uebersprungen, und jede Vor-Start-Ausblendung schreibt eine dprint-Zeile ins Log. Quests in Dungeons fuehren zum Eingang statt ins Leere Einfach: Bei rund 300 Quests liegt der Questgeber, das Ziel oder die Abgabe in einem Dungeon - "Rache fuer Vorrel" beginnt im Scharlachroten Kloster, "Willix der Importeur" endet im Kral von Rasierklingenfarn. Annahme, Ziel und Abgabe waren dort bisher leer, weil es in Instanzen keine Weltkarte gibt. Jetzt steht dort stattdessen der Eintrag "NPC, Eingang, Dungeonname, Zone" mit Route zum Dungeoneingang - auch bei Schlachtfeldquests (Alteractal je Fraktion am richtigen Eingang). Fundquellen eines GEGENSTANDS im selben Dungeon werden dabei zu einem einzigen Eintrag "Dungeonname, Eingang, Zone" zusammengefasst - "Ramaladnis Schicksal" nannte sonst 29 Naxxramas-Trashmobs einzeln, die alle zum selben Tor fuehren; Toetungsziele behalten ihre einzelnen Mobnamen. Technisch: Neue generierte Tabelle SkuDB.InstanceEntrances (aus Questies Dungeon-Tabelle, Werkzeug dev/rework-docs/_gen_instance_entrances.py): Instanz-AreaId -> Eingaenge {Elternzone, x, y, ggf. Fraktion}, inklusive der Nebenfluegel-IDs und einem GetBuildInfo-Tor fuer die WotLK-Verschiebungen. Die Spawn-Aufloeser (CreatureIdHelper, Objekt- und Gegenstands-Zweig von GetResultingWps) ueberspringen kartenlose Gebiete nicht mehr, sondern beantworten sie wie der triggerEnd-Umweg von v43.2: Eingangskoordinaten in Weltkoordinaten wandeln, naechsten Routen-Wegpunkt nehmen. Memoisiert je Wegpunktcache-Generation; der Fraktionsfilter liest UnitFactionGroup. 77 Feldziel-Quests haben jetzt ein echtes Questziel Einfach: Fuer 77 Quests, deren Ziel ein Ort oder Gegenstand im Feld ist (die Wasserbrunnen von Mulgore, der Mondfederstein der Druiden, die Kristallpylonen im Krater von Un'Goro, Rolfs Leichnam, die vier Draenei-Totems, die Tierzaehmungs-Questreihe der Jaeger und viele mehr), gab es bisher keinerlei Zieldaten - der Eintrag "Ziel" fehlte einfach. Jetzt haben alle ein echtes, routbares Questziel. Wichtig: Die Objekte und Kreaturen kommen aus Skus eigenen Spawndaten, aber 26 Ortsangaben stammen aus Webquellen (warcraft.wiki.gg, Wowhead) und konnten nicht alle im Spiel geprueft werden. Sie sind mit Bedacht gewaehlt, koennen aber im Einzelfall danebenliegen - eine Rueckmeldung, ob so ein Ziel stimmt oder nicht, hilft sehr. Auch ein ungenauer Punkt ist besser als gar keiner: die Route fuehrt in die richtige Gegend. Technisch: Ergebnis der Pruefliste dev/rework-docs/QUEST-TARGET-PROPOSALS.txt (Abschnitte 1-3, von Hand geprueft): 27 Objekt- und 24 Kreaturenziele als objectives-Eintraege in quests_fixes.lua (IDs gegen die eigenen Datenbanken validiert, Spawnzonen verifiziert, keine -1,-1-Positionen im Freiland) plus 26 triggerEnd-Koordinaten aus der Webrecherche. Zwei Quests (9410, 10166) trugen die richtige Objekt-ID schon in extraObjectives, das die Zielmenues nicht lesen - dort ist das objectives-Feld ergaenzt. Dreizehn Sprich-mit-Quests haben wieder eine Abgabe Einfach: Dreizehn Quests - vor allem die alten Priester-Zauberquests (Sterne Elunes, Elunes Anmut, Furchtlosigkeit, Schwaechungsfluch), dazu unter anderem "Der Foliant des Adels" und "Verbuendeter des Netherschwingenclans" - standen ohne Abgabepunkt in den Daten: weder Ziel noch Abgabe, nichts war routbar. Jetzt fuehrt die Abgabe zu dem NPC, den der Questtext selbst nennt. Technisch: finishedBy-Eintraege in quests_fixes.lua; die Kreatur-IDs sind aus dem Questtext gegen die Kreaturdatenbank aufgeloest (jeder Name ist dort eindeutig, die Spawns liegen in der im Text genannten Zone). Die Kandidaten stammen aus dem neuen Werkzeug dev/rework-docs/_quest_target_candidates.py, das alle zielllosen Quests klassifiziert und fuer die restlichen (echte Feldziele ohne Koordinatenquelle) die Pruefliste QUEST-TARGET-CANDIDATES.txt schreibt. Experimentell: Sammelrouten Einfach: Du waehlst eine Ressource - ein Erz, ein Kraut, eine Gaswolke oder eine Truhensorte - und Sku fuehrt dich durch die Zone, Vorkommen fuer Vorkommen, immer das naechstgelegene zuerst. Wo Wegedaten vorliegen, geht es ueber eine echte Route; ist keine da, gibt es einen direkten Peilton, und Sku sagt das dazu - ein Peilton kann durch eine Wand zeigen, eine Route nicht. Im Flug wird nie geroutet: dort ist die Gerade der richtige Weg, nicht der Notbehelf. Am Vorkommen wartet Sku kurz, waehrend du abbaust, und geht dann weiter. Der Tastenbefehl "naechster Routenwegpunkt" (ab Werk Strg+Umschalt+W) ueberspringt waehrend einer Sammelroute das aktuelle Vorkommen - es braucht also keine neue Taste. Ist die passende Suche aktiv (Mineralien finden, Kraeuter finden), prueft der Minikartenscanner beim Herangehen, ob das Vorkommen ueberhaupt noch da ist, und ueberspringt abgebaute mit einer eigenen Ansage. Ohne Suche laeuft die Route trotzdem, nur eben ohne diese Pruefung. Zu finden unter Einstellungen -> Scan -> ressourcen scan -> Sammelrouten; dort liegen auch Pruefradius, Anzahl der Vorkommen je Route und der Schalter fuer die Pruefung. Fuer Erze, Kraeuter und Truhen muss "Wegpunkte fuer Kraeuter und Bergbau anzeigen" in den Navigationseinstellungen an sein - sonst liegen diese Vorkommen gar nicht als Wegpunkte vor, und Sku sagt beim Start genau das, statt die Zone faelschlich fuer leer zu erklaeren. Gaswolken brauchen die Einstellung nicht. Wichtig: Diese Funktion ist ausdruecklich experimentell. Sie ist im Spiel erst in Ansaetzen erprobt, und die Pruefung "ist das Vorkommen ueberhaupt noch da" konnte gar nicht unter echten Bedingungen laufen, weil hier kein Charakter einen Sammelberuf hat - ohne Mineralien finden oder Kraeuter finden gibt es keine Punkte auf der Minikarte, die der Scanner lesen koennte. Wer Bergbau oder Kraeuterkunde spielt: bitte ausprobieren und berichten, was schiefgeht. Technisch: Idee und Referenzumsetzung stammen von ZenqFR, aus dem Begleit-Addon SkuGatherRoute (github.com/ZenqFR/Sku-GatherRoute); die Routenmechanik ist dort erdacht und vorgefuehrt worden - eine Wegpunktfamilie unter einem gemeinsamen Basisnamen, jedes Vorkommen ueber eine nahe Route, eine eigene Ansage fuer jeden Uebergang, und der vorhandene Tastenbefehl als Ueberspringer. Hier ist die Funktion mit ZenqFRs Zustimmung nativ neu gebaut, damit kein zusaetzliches Addon noetig ist. Ein Unterschied ist bewusst: das Original setzt GatherMate2 voraus, diese Fassung nicht. Wir sehen darin keinen Vorteil - die Vorkommen stehen samt Weltkoordinaten laengst in SkuNavs Wegpunkt-Cache, und zwar so benannt, dass die Ressource der Basisname des Wegpunkts ist; eine zweite Datenquelle und ein zweites Addon wuerden dem nichts hinzufuegen, kosteten aber jeden Nutzer eine weitere Installation. Sollte GatherMate2 etwas leisten, das wir uebersehen haben - das Selbstaufzeichnen tatsaechlich abgebauter Knoten waere der Kandidat -, dann sagt uns bitte wofuer, und wir sehen es uns an. Die Praesenzpruefung haengt sich in MinimapScanner:MinimapScanFastStop, den Punkt, durch den jeder Scan laeuft. Ist "bei Ressourcen benachrichtigen" an, reicht der ohnehin laufende Scan; sonst scannt die Route selbst, gedrosselt und nur in Reichweite des Ziels, und diese Scans bleiben stumm. Ein Treffer bestaetigt, ein Fehlschlag beweist nichts - ein Scan meldet immer nur einen Namen und kann einen anderen Punkt erwischt haben. Erst nach mehreren erfolglosen Scans in Reichweite gilt ein Vorkommen als weg. Im Zweifel wird nie uebersprungen: ein zu Unrecht behaltenes Vorkommen kostet ein paar Schritte, ein zu Unrecht uebersprungenes faellt gar nicht auf. Das Menue bleibt beim Gehen bedienbar Einfach: Oeffnete man das Menue waehrend man lief, stand es zwar da und sagte "Menue geoeffnet", aber keine Taste tat noch etwas - keine Pfeiltaste, kein Buchstabe, kein Eingabe. Nur Escape kam durch. Bedienbar wurde es erst, wenn man stehen blieb. Das ist behoben: ein offenes Menue nimmt Tasten jetzt entgegen, egal ob man geht, laeuft oder autolaeuft. Technisch: Es gab zwei Bewegungssperren, nicht eine. Die erste verhindert das OEFFNEN, waehrend eine Bewegungstaste gedrueckt gehalten wird - die bleibt, sie ist noetig: die Tastenbelegungen des Menues wuerden das Loslassen schlucken und man liefe endlos weiter. Autolaufen ist davon seit v42.00 ausgenommen (eigenes Flag AutoRun, das IsPlayerMoving bewusst nicht liest). Die zweite sass im Tastenhandler des Menues selbst und liess, solange eine Bewegungssperre stand, jeden Tastendruck ausser Escape verfallen. Diese zweite Sperre kauft nichts: ist das Menue erst offen, gehoeren ihm die Tasten ohnehin schon, das Verwerfen stoppt keine Bewegung - es macht nur das Menue taub und setzt zu allem Ueberfluss das Merkzeichen "spaeter oeffnen" auf ein laengst offenes Menue, das die Wiederoeffnungs-Schleife dann wieder abraeumen muss. Sie greift jetzt nur noch, wenn das Menue NICHT offen ist. Die vier verbliebenen Oeffnungssperren schreiben ausserdem eine Zeile ins Debug-Log, die die haltende Bewegungstaste beim Namen nennt - vorher waren sie stumm, und ein Bericht "das Menue ging beim Laufen nicht auf" hatte keinerlei Spur. Navigation: "Aktuelle Karte Entfernung" steht jetzt vorn Einfach: Unter "Direkter Wegpunkt" stand "Letzte" an erster und "Aktuelle Karte Entfernung" an zweiter Stelle. Die beiden sind getauscht - die Liste der Wegpunkte in der aktuellen Zone ist der haeufigere Einstieg und liegt jetzt direkt unter dem Cursor. Technisch: Reine Reihenfolge der Injektionen in SkuNav:MenuBuilder. "Letzte" bleibt an eine nicht leere Liste zuletzt benutzter Wegpunkte gebunden; ist sie leer, steht "Aktuelle Karte Entfernung" ohnehin an erster Stelle, wie vorher auch. Der Tippfilter ignoriert Akzente Einfach: In jeder Liste, die sich durch Tippen einengen laesst, wurden Akzente wie Zeichen einer anderen Sprache behandelt. Auf einem franzoesischen Client fand "general" nichts, obwohl "Fournitures generales" dastand, und "ingenieur" fand "Ingenieur" nicht - "ing" dagegen schon. Das traf auch Deutsch: ein Eintrag, der mit einem grossen Umlaut beginnt, war ueber den Filter nie erreichbar. Jetzt zaehlt der Buchstabe, nicht der Akzent. Dazu tippt auf einer franzoesischen AZERTY-Tastatur die Taste ù jetzt ebenfalls in den Filter - sie ist der einzige akzentuierte Buchstabe, den diese Tastatur als echtes Tastenereignis liefert. Technisch: string.lower ist in Lua bytweise und bildet ausschliesslich A-Z ab, es faltet also auf keiner Seite des Vergleichs je ein akzentuiertes Zeichen. SkuMenuFilterMatch (benutzt von ApplyFilter und JumpToFilterMatch) und SettingsSearchMatch falten Eintragsnamen und Suchtext jetzt vorher auf akzentfreies ASCII; nur 2-Byte-Sequenzen aus Latin-1 Supplement und Latin Extended-A werden angefasst, reines ASCII nimmt den schnellen Weg. Streng durchlaessiger als vorher: was frueher passte, passt weiterhin. Ausserdem laufen die beiden string.find jetzt mit plain=true - der Suchtext wurde als Lua-Suchmuster gelesen, weshalb eine Eingabe wie "50%" oder "(lang" nichts fand oder mit einem Fehler abbrach. Die Akzentfaltung stammt aus PR #9 (ZenqFR), die ù-Taste aus PR #13 (Naxedim). Aktionsleisten: der Zauber-Tooltip wird wieder vorgelesen Einfach: Im Aktionsleisten-Menue (Umschalt+F11) las Umschalt+Ab auf einem Zauber der Zuweisungsliste gar nichts mehr vor. Jetzt kommt der Tooltip wieder - ebenso bei der aktuellen Belegung einer Taste und bei den beiden Begleiter-Faehigkeiten daneben, die dieselbe Schwaeche hatten. Technisch: Zwei unabhaengige Ursachen, beide behoben, weil sich aus dem Code keine ausschliessen liess. Erstens wird SkuScanningTooltip einmalig beim Login ohne Vorlage erzeugt und von jedem Modul geteilt; wer ihn zuletzt benutzt hat, kann ihn ohne brauchbaren Besitzer zuruecklassen, und danach fuellt jeder Set*-Aufruf nichts mehr - lautlos, ohne Fehler. Er wird jetzt unmittelbar vor dem Fuellen neu in Besitz genommen. Zweitens bekam SetSpellByID den dritten Rueckgabewert von GetSpellBookItemName, der auf diesem Client der Classic-Signatur folgt und nur (name, rank) liefert - die Id ist eine Retail-Ergaenzung und war nil. Die Id kommt jetzt aus GetSpellBookItemInfo, gefuellt wird mit SetSpellBookItem, das gar keine Id braucht. Der Lesevorgang laeuft zusaetzlich in einem pcall, weil er bei jeder Cursorbewegung ausgeloest wird. Aus PR #10 (ZenqFR). Questziel: der Ort stand in den Daten, gefunden wurde er nie Einfach: 174 Quests, bei denen man einen Ort erkunden oder dort etwas benutzen soll, antworteten unter "Questziel" nur "Leer". Jetzt fuehrt der Eintrag zum naechstgelegenen Routenwegpunkt an diesem Ort. Technisch: GetTriggerEndWps setzte einen Wegpunkt-NAMEN zusammen (";;;;") und liess ihn ueber die exakte Namenssuche im Wegpunkt-Cache aufloesen. Einen Wegpunkt unter diesem Namen erzeugt aber nichts - anders als bei Kreaturen- und Objektvorkommen -, er traf also nur, wenn jemand ihn von Hand in die Routendaten geschrieben hatte: genau einer existiert (Quest 10211, Shattrath). Der zusammengesetzte Name wird weiter benutzt, wenn er aufloest; sonst uebernimmt jetzt die Geometrie - Kartenkoordinaten in Weltkoordinaten, dann der naechste echte ROUTEN-Wegpunkt. GetNearestWpToCoords2 bekam dafuer einen optionalen typeId-Filter, damit die Ersatzsuche nicht in den rund 145000 erzeugten Vorkommenspunkten landet, und eine Absicherung gegen einen fehlenden Kontinent-Eimer, wo pairs(nil) warf. Ausserdem werden jetzt alle Koordinatenpaare jeder Zone gelesen statt nur des ersten, und das Ergebnis wird pro Cache-Generation gemerkt. Franzoesisch: die Wegpunktkommentare sprechen wieder - und jetzt franzoesisch Einfach: Die Kommentare an Wegpunkten - darunter die sicherheitsrelevanten wie "Vorsicht, ab hier fuehrt die Route am Rand einer Schlucht entlang", "hier auf den Zeppelin warten" oder "dieser NPC bewegt sich" - blieben auf einem franzoesischen Client seit v42.11 restlos stumm. Sie sprechen wieder, und sie sprechen jetzt Franzoesisch: 207 Texte, die auf 546 Wegpunkten sitzen. Technisch: Die Routendaten fuehren lComments nur fuer enUS und deDE (rund 296 Wegpunkte). SkuNav:PlayWpComments las comments[Sku.Loc] ohne Rueckfall. Bis v42.11 war Sku.Loc auf einem franzoesischen Client "enUS", weil es keine frFR-Locale gab, und man hoerte die englischen Texte; seit locales/frFR.lua existiert, ist Sku.Loc "frFR", die Suche liefert nil, und die Funktion kehrt wortlos zurueck. Neu ist Sku.locList (SkuUtil.lua), das Listengegenstueck zu Sku.locStr: es liefert die erste NICHT LEERE Liste aus Sku.Loc / enUS / deDE. "Nicht leer" ist entscheidend, weil SkuMM.lua an jedem gezeichneten Wegpunkt ein leeres comments[Sku.Loc] anlegt - eine einfache oder-Kette bliebe daran haengen. Die Uebersetzung ist aus dem DEUTSCHEN Original gemacht, nicht ueber das Englische: das Englische hat auf genau diesen Sicherheitstexten Details verloren (die Schlucht-Warnung ohne "du gehst am Rand" und ohne Laufrichtung, "extrem schmale Bruecke mit Schlucht" zu "extrem schmale Bruecke"), und mehrere englische Eintraege sind leer, darunter die Warnung vor toedlichen Aufzuegen auf acht Wegpunkten. Franzoesisch: Ressourcennamen und die Hoehle der Nebel Einfach: Zwei Fehler, die nur einen franzoesischen Client trafen. Erstens waren 22 der 94 Ressourcennamen des Minikartenscanners falsch - der Scanner vergleicht sie mit dem Tooltip des Spiels, ein falscher Name heisst also, dass dieses Vorkommen nie angesagt wird, ohne Fehlermeldung. Zweitens blieb in der Hoehle der Nebel die Wegpunktliste leer, waehrend eine draussen gestartete Route weiterlief. Technisch: Die 22 Namen wurden einzeln gegen eine von beiden Addons unabhaengige Quelle entschieden: 19 ueber SkuDBs eigene frFR-Tabellen (aus Questies Blizzard-Strings), drei ueber die Tooltip-Schnittstelle von Wowhead. Bei der Hoehle vergleicht Geo.lua GetMinimapZoneText() woertlich mit L["Hoehle der Nebel"]; die generierte frFR-Locale trug "Grotte des Brumes", eine freie Uebersetzung - der Client sagt "Caverne des Brumes". Der Vergleich lief also ins Leere, uiMap blieb auf dem Kontinent, GetAreaIdFromUiMapId antwortete -1 und GetCurrentAreaId nil, worauf ListWaypoints2 aufgab. Der Wert wurde mit /szp in der Zone gelesen, nicht uebersetzt, und liegt jetzt sowohl in der generierten Datei als auch in der TSV-Ablage, aus der sie zusammengebaut wird - samt der Notiz, dass er nicht frei uebersetzt werden darf. Aus den PRs #14 und #16 (Naxedim). Zum Beacon drehen: genauer, und mit Vorhalt Einfach: Die automatische Drehung zum Funkfeuer (T) sitzt jetzt deutlich genauer. Vorher lief sie so schnell, dass allein das framegenaue Stoppen je nach Bildrate zwanzig Grad und mehr Ueberdreh kosten konnte. Jetzt richtet sich das Tempo nach der Groesse der Drehung, und keine Drehung dauert laenger als eine Viertelsekunde. Waehrend man sich bewegt, wird ausserdem vorgehalten: gezielt wird dorthin, wo der Wegpunkt am Ende der Drehung liegen wird - das beendet das Im-Kreis-Laufen um nahe Wegpunkte, das vor allem beritten und im Flug auftrat. Und ein Druck waehrend einer laufenden Drehung wird verworfen statt die Drehung mittendrin abzubrechen; gewohntes Mehrfachdruecken verfeinert weiter wie bisher. Technisch: Vier Teile, die zusammen getestet wurden. Der Schnappschuss auf die Standardkamera vor der Drehung bleibt - er ist fuer die Gierung tragend, ohne ihn stimmt der Winkel nicht. Die Drehgeschwindigkeit wird aus dem Restwinkel gedeckelt, statt fest zu laufen. Der Vorhalt rechnet aus der aktuellen Geschwindigkeit und der voraussichtlichen Dauer der Drehung, wo der Wegpunkt am Ende steht. Dazu eine Absicherung gegen den Fehler, dass nach schnell hintereinander ausgeloesten Drehungen die Drehgeschwindigkeit der Kamera- Tasten dauerhaft vervierfacht haengenblieb. Das Installationsprogramm merkt sich, wo WoW liegt Einfach: Das Installationsprogramm sucht das Spiel an den ueblichen Stellen - Programme, dazu eine Handvoll wahrscheinlicher Ordner auf C, D und E. Wer sein WoW woanders hat, musste den Ordner von Hand suchen, und das nicht einmal, sondern bei JEDEM Update: das Installationsprogramm vergass die Antwort in dem Moment, in dem es sich schloss. Jetzt schreibt es den Ordner auf, sobald eine Installation durchgelaufen ist, und faengt beim naechsten Mal dort an. Zeigt man ihm einen Client, findet es auch den zweiten daneben - eine Classic Era neben einer Anniversary auf demselben ungewoehnlichen Laufwerk wird von selbst mitgenommen. Zieht das Spiel spaeter um oder wird deinstalliert, wird die Notiz verworfen und es wird gesucht wie vorher. Das Installationsprogramm steht damit auf Version 4.5. Technisch: Neue Datei PathMemory.cs. Das Installationsmanifest taugt dafuer nicht - SkuInstall.json liegt IM AddOns-Ordner, es zu lesen setzt also voraus, den Ordner schon gefunden zu haben, den man sich merken will. Der Ordner jedes Clients wird deshalb als einfache Zeile "produkt=pfad" in SkuPaths.txt geschrieben, und zwar an zwei Stellen: %LOCALAPPDATA%\SkuUpdater, neben der dauerhaften Kopie des Updaters, die die Verknuepfung "Sku Updater" startet, und %ProgramData%\SkuUpdater als maschinenweite Spiegelung. Die Spiegelung ist kein Selbstzweck: das Installationsprogramm fordert Adminrechte an, ein Standardbenutzer, der die UAC-Abfrage mit den Adminzugangsdaten eines anderen beantwortet, laeuft also komplett unter jenem Profil und wuerde die Notiz sonst in ein LOCALAPPDATA schreiben, das er nie wiedersieht. Beim naechsten Start schlaegt ein gemerkter Ordner die Erkennung - er ist eine Entscheidung, die Erkennung nur eine Vermutung ueber eine kurze Laufwerksliste - und sein Basisverzeichnis wird der Suchliste vorangestellt; genau das macht das Merken eines Clients fuer den anderen bezahlt. Absicherungen gegen eine veraltete Notiz: der Ordner muss noch existieren, und seine .flavor.info darf nicht inzwischen einen anderen Client melden - sonst wird die Notiz ignoriert, statt eine Installation ins Leere zu schicken. Geschrieben wird erst, nachdem ein Client sauber installiert wurde, ein abgebrochener oder fehlgeschlagener Lauf hinterlaesst also nichts. Klartext mit Absicht - die Datei laesst sich vorlesen und im Editor korrigieren, und wer eine Zeile loescht, bekommt fuer diesen Client die automatische Erkennung zurueck. Neue Pruefung ohne Oberflaeche, "SkuSelfTest pathmemory": sie gibt aus, was auf diesem Rechner vermerkt ist, und spielt Schreiben, Lesen und die Faelle veralteter Notizen gegen einen Wegwerfspeicher durch, ohne den echten anzufassen. Das Lesefenster laesst sich einstellen Einfach: Questtexte, Tooltips, der Chatverlauf und die Wiki-Seiten landen alle im selben Lesefenster. Wie dieses Fenster aussieht, stand bisher fest im Code: Playfair Display in 12 Punkt, eine duenne Schrift mit Serifen in der kleinsten Groesse, die das Addon ueberhaupt verwendet. Fuer jemanden mit Restsehvermoegen war das ausgerechnet die wichtigste Flaeche im Addon und zugleich die am schlechtesten lesbare. Unter Einstellungen -> Visuelle Hilfen -> Textfenster stehen jetzt Schriftgroesse von 14 bis 44 Punkt, vier Schriftarten, vier Farbkombinationen (weiss auf schwarz, gelb auf schwarz, schwarz auf weiss, weiss auf blau), die Deckkraft des Hintergrunds und ein Umriss zur Wahl. Ab Werk laeuft das Fenster jetzt serifenlos in 18 Punkt. Wer nichts umstellt, bekommt also trotzdem eine deutlich besser lesbare Flaeche als vorher. Technisch: Die Flaeche selbst gehoert Libs/SkuTTS-1.0 (Frame SkuTTSMainFrame samt FontString .FS); dort stand die Darstellung als ein einziger harter SetFont-Aufruf. Die Einstellungen liegen jetzt in SkuCore VisualAids unter visualAids.textWindow, und SkuTTS:Output ruft vor jedem Anzeigen VisualAids:TextWindowLayout auf - pcall- gesichert und in derselben Richtung, in der SkuZOptions schon den Lesebalken fuettert. Die Lib muss so nichts ueber die Optionen wissen, und ein abgeschaltetes Modul Visuelle Hilfen laesst das Fenster einfach beim alten Aussehen. Jede Schriftzuweisung ist geprueft und faellt auf die Client-Standardschrift zurueck, statt eine leere Flaeche zu hinterlassen - die beiden mitgelieferten Familien Raleway und Playfair liegen unter Libs/SkuTTS-1.0/fonts und kommen nur ueber das Release-ZIP mit. Die Groessenstufen sind bewusst kleiner als beim Lesebalken: hier steht ein ganzer Questtext, und das Fenster hat keinen Rollbalken, schneidet also unten umso frueher ab, je groesser die Schrift ist. Gesprochen wird weiterhin alles, die Anzeige ist die Zweitspur. Der Lesebalken zeigt, was Sku sagt - und er funktioniert im Kampf Einfach: Zwei Dinge auf einmal. Erstens blieb der Balken im Kampf leer, also genau dann, wenn Vorlesen und Mitlesen am wichtigsten sind. Zweitens zeigte er nur den Namen eines Menueeintrags: bei einem Ein/Aus-Schalter stand dort der Name, aber nicht der Zustand, bei einer Taschenzeile der Name, aber nicht die Anzahl - alles, was Sku zusaetzlich vorliest, fehlte auf dem Balken. Beides ist behoben; der Balken zeigt jetzt dieselbe Zeile, die Sku spricht, und er tut es auch mitten im Kampf. Ausserdem sind Schriftart und Farbkombination jetzt auch fuer ihn waehlbar, mit eigenen Werten neben denen des Textfensters. Technisch: Die Kampf-Sperre war eine Verwechslung von sichtbar und offen: die Pruefung haengte an SkuOptions:IsMenuOpen(), und das testet OnSkuOptionsMain:IsVisible(). Dieser Frame ist Vorfahr der sicheren ENTER-Buttons und damit geschuetzt, sein Show() ist im Kampf blockiert - das Kampfmenue laeuft absichtlich headless und meldet sich stattdessen ueber SkuOptions.combatMenuActive. Genau dieses Paar pruefen templates.lua und SkuZOptions ohnehin schon; der Lesebalken kannte es nur nicht. Er selbst ist ein gewoehnlicher Frame ohne sichere Kinder, sein Show() war im Kampf nie das Problem. Weil das Kampfmenue nur logisch schliesst (der Frame-Hide ist dort geschuetzt) und das an sechs Stellen tut, blendet sich der Balken jetzt selbst aus: ein OnUpdate prueft alle 0,25 s, ob das Menue noch offen ist - WoW ruft OnUpdate ausschliesslich bei sichtbaren Frames auf, im ausgeblendeten Zustand kostet das also nichts. Der Inhalt war schlicht ein weggeworfener Parameter: der Aufrufer uebergab immer schon den vollstaendigen Sprechstring, angezeigt wurde trotzdem currentMenuPosition.name. Jetzt hat der uebergebene String Vorrang, die Semikolons der Sprechtrennung werden fuer die Anzeige zu Bindestrichen. Namensplaketten: die Einstellungen, die das Spiel versteckt Einfach: Der Client kann seine Namensplaketten laengst groesser, farbiger und kontrastreicher darstellen - er bietet es nur nirgends an. Blizzards eigenes Optionsfenster zeigt in Classic keine einzige dieser Einstellungen; die Checkbox fuer groessere Plaketten, die es im aktuellen WoW gibt, ist in Classic ausdruecklich leer gelassen. Ohne Sku kaeme man nur ueber Konsolenbefehle heran. Das neue Menue unter Einstellungen -> Visuelle Hilfen -> Namensplaketten macht sie zugaenglich: Plakettengroesse, Hervorhebung des Ziels, Abschwaechung aller uebrigen Plaketten, Klassenfarben fuer Gegner und Verbuendete sowie nur Namen bei freundlichen Spielern. Anders als die aelteren Plaketten-Farben faerbt das nicht etwas hinter die Plakette, sondern veraendert die echte Plakette selbst. Ab Werk steht alles so, wie der Client es ausliefert - wer nichts auswaehlt, sieht keine Veraenderung. Technisch: Reine CVar-Einstellungen, kein eigener Frame, kein Taint. Plakettengroesse setzt nameplateMinScale und nameplateMaxScale gemeinsam (getrennt ergaebe das eine entfernungsabhaengige Skalierung, die hier niemand will), Hervorhebung setzt nameplateSelectedScale, Abschwaechung nameplateMinAlpha, dazu nameplateShowClassColor, nameplateShowFriendlyClassColor und nameplateShowOnlyNameForFriendlyPlayerUnits. Alle Werte und die Existenz jeder einzelnen CVar wurden am lebenden Client 2.5.6.69546 gemessen, die Obergrenze 2.0 gegen die Klemmung des Clients geprueft. Wichtig fuer kuenftige Arbeit: die entpackte BlizzardInterfaceCode im Client-Ordner ist ein Abzug von Maerz/April 2026 und damit aelter als die Plaketten-Umstellung vom Juli; sie nennt Retail-Namen wie NamePlateVerticalScale oder ShowClassColorInNameplate, die es in dieser exe gar nicht gibt. Massgeblich sind die Strings der exe. Schreibzugriffe auf CVars sind im Kampf gesperrt und scheitern still, eine dort gemachte Aenderung wird deshalb vorgemerkt und bei PLAYER_REGEN_ENABLED nachgeholt. Beim Login zieht Sku die Werte nach, aber erst, nachdem im Menue wirklich einmal etwas ausgewaehlt wurde - wer seine Plaketten frueher von Hand per Konsole eingestellt hat, behaelt sie unangetastet. Die Plaketten-Farben ueberleben einen Neustart Einfach: Wer die Plaketten-Faerbung einschaltete, hatte sie genau so lange, bis er sich neu einloggte oder die Oberflaeche neu lud. Danach stand der Schalter weiter auf an, gefaerbt wurde aber nichts mehr. Wieder in Gang brachte man es nur, indem man den Schalter von Hand aus- und wieder einschaltete - und das in jeder Sitzung erneut. Das ist behoben; die Einstellung wirkt jetzt einfach. Technisch: Das Scharfschalten des Ereignis-Treibers (NAME_PLATE_UNIT_ADDED, _REMOVED und PLAYER_TARGET_CHANGED) haengte ausschliesslich am OnAction des Menue-Schalters. Der gespeicherte Wert wurde beim Laden zwar gelesen, aber nirgends angewandt, also war nach jedem Login kein einziges Ereignis registriert. Das Armieren sitzt jetzt in VisualAids:OnEnable, wo die Folgen-Warnung und der Naechster-Gegner-Button schon immer armiert wurden, mit einem verzoegerten zweiten Versuch fuer den Fall, dass das Profil beim ersten Durchlauf noch nicht steht. Ein geschlossenes Fenster wird nicht mehr nachtraeglich angesagt Einfach: Wer beim Lehrer schnell mehrere Zauber lernte, das Fenster zuegig schloss und dann sein Berufsfenster oeffnete, hoerte nach einer Weile wieder das Lehrerfenster - manchmal erst, nachdem er einen Tooltip gelesen hatte. Sku merkte sich, wohin es im Menue eigentlich noch springen wollte, und holte das spaeter nach, ohne zu pruefen, ob es dieses Fenster ueberhaupt noch gibt. Technisch: Der aufgeschobene Menuesprung besteht aus drei Feldern (openMenuAfterCombat, openMenuAfterMoving, openMenuAfterPath), die bisher unabhaengig voneinander beschrieben wurden. SlashFunc setzt Merker UND Pfad gemeinsam; andere Stellen setzten nur den Merker - und erbten damit den Pfad, der noch herumlag. Geloescht wurde der Pfad ausserdem nur im verzoegerten Teil von CheckFrames, der in Bewegung abbricht und erst eine halbe Sekunde spaeter nachfasst, waehrend die Freigabe im Bild-Takt genau in dem Moment feuert, in dem man stehen bleibt - ein Rennen, das die Freigabe gewann. Die drei Felder sind jetzt eine Einheit (SkuCore:ClearDeferredMenuOpen), das Setzen eines Merkers loescht den Pfad, und geleert wird im Hide-Hook des Fensters (SkuCore:GENERIC_OnClose) - also genau dann, wenn der Sprung ungueltig wird. Bewusst ohne Verfallszeit und ohne Sichtbarkeitspruefung: der Zustand wird dort geloescht, wo er falsch wird, statt einem Fehler davonzulaufen. Das Menue oeffnet nicht mehr von selbst die oberste Ebene Einfach: Ab und zu ging das Menue von allein auf - und dann auch noch ganz oben, statt dort, wo man hinwollte. Technisch: SkuCoreControlOption1 haelt Tastenbelegungen (Zielentfernung, Panikmodus, Minikartenscan, Flug abbrechen, zu Einheit drehen) und hat mit dem Menue nichts zu tun. Sein OnShow bricht ab, solange man sich bewegt oder im Kampf ist, weil SetOverrideBindingClick dort nicht erlaubt ist und einer gehaltenen Bewegungstaste das Loslassen wegnehmen wuerde - es brach aber ab, indem es openMenuAfterMoving setzte, und die Freigabe machte daraus mangels Pfad ein Menue-Oeffnen auf der Wurzel. Der Frame hat jetzt seinen eigenen Merker (rebindControlKeysAfterBlock) und bekommt nur noch seine Tasten zurueck. Das Schliessen eines zweiten offenen Fensters wird wieder bemerkt Einfach: Waren zwei Fenster gleichzeitig offen - etwa Haendler und Taschen -, wurde nur das erste Schliessen bemerkt. Beim zweiten baute sich das Menue nicht neu auf und schloss sich nicht. Technisch: Einer der beiden Hook-Installateure klammerte Show und Hide um einen einzigen gemeinsamen Schalter (SkuDropdownlistGenericFlag): jedes Show setzte ihn, und nur das erste Hide danach verbrauchte ihn. Welcher Installateur ein Fenster erwischte, war reine Zeitfrage - dieser nimmt alles, was eine Sekunde nach dem Betreten der Welt existiert, waehrend Fenster wie Lehrer, Beruf und Auktionshaus erst spaeter entstehen und dem anderen zufallen. Der Schalter ist weg; GENERIC_OnClose fasst ohnehin selbst zusammen. Kein Inhalt eines geschlossenen Fensters mehr unter "Lokal" Einfach: Nach dem Schliessen eines Fensters konnten dessen Eintraege unter "Lokal" stehenbleiben und beim naechsten Oeffnen des Menues noch einmal auftauchen. Technisch: SkuCore.GossipList ist die Datenquelle des Lokal-Menues, wurde aber nur geleert, wenn das Menue in genau diesem Moment offen war. Beim Schliessen per Escape ist es das nie: der Menue-Frame geht absichtlich vor den Fenstern zu, und der zustaendige Programmteil laeuft ein Bild spaeter. Jetzt wird geleert, sobald kein Fenster mehr offen ist. Lehrer: nach dem Schliessen ist Ruhe Einfach: Wer mehrere Zauber schnell hintereinander lernte und das Fenster gleich danach schloss, hoerte die Ansagen des Lehrers noch weiter. Technisch: Jeder Klick auf "Erlernen" stellte eine Neuerfassung nach einer halben Sekunde und eine Ansage nach 0,85 Sekunden in die Warteschlange, ohne Abbruchmoeglichkeit. Beide Schritte pruefen jetzt, ob ClassTrainerFrame ueberhaupt noch sichtbar ist. Die Sperre aus v43.1, die nicht in ein geschlossenes Menue hineinspricht, half hier nicht: sobald das naechste Fenster das Menue wieder oeffnete, war sie offen. Ausserdem verlor die Wiederholung stiller Neuerfassungen in Bewegung ihren Stumm-Auftrag und wurde je Klick einmal eingeplant - sie traegt ihre Argumente jetzt mit und laeuft nur noch einmal. Auktionshaus: die Trefferliste ist wirklich sortiert Einfach: Wer nach "Level absteigend" sortierte, bekam trotzdem eine Liste, die mit niedrigstufigem Kram anfing. Sortiert wurde naemlich nur innerhalb einer Seite - und eine Seite sind die 50 billigsten Auktionen. Ganz oben stand also das Hoechststufige unter dem billigsten Graugut, waehrend die Stufe-70-Sachen Hunderte Eintraege weiter unten lagen. Auch nach dem Fertig-Ton, denn nachsortiert wurde nie. Jetzt sortiert der Server die Trefferliste selbst nach Stufe; bei gleicher Stufe entscheidet der Preis je Stueck. Technisch: Jede Abfrage ging mit fest verdrahteter Server-Sortierung "unitprice" raus, und die Ergebnisliste wird seitenweise und nur anhaengend aufgebaut (neue Gegenstaende kommen ans Ende, damit der Cursor des Nutzers nicht springt). Die Reihenfolge der Liste ist damit immer die des Servers, die eigene Sortierung wirkt nur je Seite. Bei "Level auf-" und "absteigend" wird die Server-Antwort jetzt nach der Spalte "level" sortiert - genau die Spalte, die auch Blizzards eigener Stufen-Sortierknopf setzt. Kauf und Strategiekauf bleiben auf "unitprice", die brauchen den guenstigsten Treffer auf Seite 0. Eine Namenssuche ebenfalls: dort haben alle Treffer dieselbe Stufe, der Server haette nach einem Feld sortiert, in dem sich nichts unterscheidet, und die Seiten kaemen in seiner Zufallsreihenfolge statt der billigsten zuerst. Zusaetzlich haben die Stufen-Vergleiche jetzt den Stueckpreis als zweiten Schluessel; Nur-Gebot-Auktionen zaehlen dabei mit ihrem Gebot je Stueck statt mit einem Kaufpreis von 0. Auktionshaus: "Stufe" heisst ueberall Stufenanforderung Einfach: Die Stufe in den Ergebnissen war mal die Stufenanforderung, mal die Gegenstandsstufe - je nachdem, aus welcher Liste sie kam und ob der Gegenstand ueberhaupt eine Anforderung hat. Ein Stapel Netherstoff (Anforderung 0, Gegenstandsstufe 55) stand damit ueber einem Stufe-40-Schwert. Jetzt ist es immer die Stufenanforderung, also die Spalte, die auch das Auktionshaus selbst "Stufe" nennt. Und sie wird nur noch dort vorgelesen, wo sie die Eintraege unterscheidet: in einer Kategorie oder in der Komplettscan-Liste. Eine Suche nach einem Gegenstandsnamen liefert lauter Auktionen desselben Gegenstands - dort war es 800 Mal dieselbe Zahl. Wer nach Stufe filtert, bekommt sie weiterhin ueberall angesagt. Technisch: Ein gemeinsamer Leser fuer beide Ergebnislisten: Feld 6 der Server-Antwort, sonst der Wert aus SkuDB. Feld 7 wird beachtet - bei Rezepten steht in Feld 6 der geforderte Berufs-Skill, bei Behaeltern die Zahl der Taschenplaetze, beides keine Stufe. Die Gegenstandsstufe wird nie mehr ersatzweise eingesetzt. 0 heisst jetzt "keine Anforderung" statt "unbekannt", weshalb auch kein "Level 0" mehr angesagt wird (0 ist in Lua wahr, deshalb kam es ueberhaupt heraus). Auktionshaus: "Nur benutzbare" versteckt nichts mehr Einfach: In der Komplettscan-Liste liess dieser Filter in manchen Kategorien nur noch niedrigstufiges Zeug uebrig - ausgerechnet das Hochstufige, nach dem man sucht, war weg. In der normalen Suche war das nie so. Technisch: In der Live-Liste filtert der Server. Der Komplettscan holt alles ungefiltert, Sku entscheidet selbst - bisher stur nach dem Feld canUse aus der Scan-Antwort. Das kann der Client nur fuellen, wenn er die Gegenstandsdaten der Zeile schon hatte; beim Komplettscan hat er sie fuer den Grossteil der Zeilen nicht. Es sind genau dieselben Zeilen, fuer die Name, Stufe und Qualitaet nachgetragen werden muessen - nur fuer canUse gab es keine Nachbesserung. Damit verschwand, was der Spieler noch nie gesehen hat, und das ist ueberwiegend das Hochstufige. Jetzt zaehlt ein "nicht benutzbar" nur bei vollstaendiger Zeile; sonst entscheidet die Stufenanforderung aus SkuDB. Klassen- und Rassenbeschraenkungen kennt die Datenbank nicht - im Zweifel wird lieber ein Gegenstand zu viel gezeigt als der gesuchte verschwiegen. Auktionshaus: ohne Filter wird nicht gefiltert Einfach: Die Komplettscan-Liste liess auch ohne gesetzten Filter alles weg, was keine Stufenanforderung hat - Handelswaren, Materialien, viele Rezepte - und ausserdem alles Graue, obwohl das Qualitaetsmenue unveraendert "Arm" anzeigte, also "keine Einschraenkung". Technisch: Die Vorgaben der ungesetzten Filter waren je eine 1 statt einer 0, und die Stufe wurde roh aus der Scan-Antwort gelesen. Eine Zeile, deren Stufe der Client beim Scan nicht kannte, kam als 0 zurueck und fiel damit unter die Mindeststufe 1; die Reparatur aus der Datenbank sprang nur bei einem fehlenden, nicht bei einem 0-Wert an. Beide Vorgaben sind jetzt 0, die Stufe kommt aus dem gemeinsamen Leser, und die Nachbesserung beim Einlesen behandelt 0 als "fehlt". Der frueher als letzter Ausweg eingesetzte eigene Mindeststufen-Wert ist weg: eine Zeile bestand damit immer ihren eigenen Filter und wurde auch noch mit dieser Stufe angesagt. Auktionshaus: Kategorien ohne Unterkategorien zeigen wieder Gegenstaende Einfach: Unter "Auktionen nach Gegenstand" gab es Kategorien, die ausser "Alle" nichts enthielten - zum Beispiel Questgegenstaende. Technisch: Die Gegenstandsliste verglich die Unterklasse auch dann, wenn es gar keine gibt. Eine Kategorie ohne Unterkategorien wird ohne Unterklasse aufgebaut, und der Vergleich ist dann fuer jeden Gegenstand falsch. Der Komplettscan-Zwilling hatte die Absicherung von Anfang an, die Gegenstandsliste jetzt auch. Auktionshaus: ein abgebrochener Kauf bleibt abgebrochen Einfach: Wer einen Kauf abbrach und danach etwas anderes tat, konnte aus dem Nichts wieder den Kauf-Dialog bekommen - und die naechste Eingabetaste, die eigentlich das Suchfeld oeffnen sollte, kaufte. Gekauft wurde immerhin das Richtige, aber ungefragt. Technisch: Der Abbruch loeste Timer und Tastenbelegungen, loeschte aber das Kaufziel nicht. Die Abfragefunktion erkennt ihren Modus genau daran - es gibt ein Kaufziel, also ist das eine Kauf-Abfrage -, und so lief die naechste, voellig fremde Abfrage des Nutzers in den Kauf-Pfad: der fand das alte Ziel in der frischen Liste wieder, baute den Dialog auf und schaltete die Eingabetaste scharf. Im Log vom 01.09.2026 liegen Abbruch (18:45:40), neue Suche (18:46:12, sofort "MATCH FOUND, showing popup") und der Kauf (18:46:16, "Gebot akzeptiert") nur vier Menue-Tastendruecke auseinander. Das Kaufziel wird jetzt an den drei Stellen geloescht, an denen der Kaufwunsch endet: Abbruch des Dialogs (auch durch die 30-Sekunden-Sicherung), Start einer neuen Suche oder Liste, und Schliessen des Auktionshauses. Der Kaufweg selbst bleibt unangetastet - er laeuft nicht ueber den Sucheinstieg, und die Wiederholung nach einem verlorenen Wettlauf behaelt ihr Ziel. Auktionshaus: eine abgebrochene Suche sagt es Einfach: Bricht eine Suche ab, weil der Server nicht mehr antwortet, blieb die halb gefuellte Trefferliste stehen und sah aus wie ein fertiges Ergebnis. Jetzt kommt "Suche abgebrochen, Liste unvollstaendig". Technisch: Der Waechter beendet eine seitenweise Suche nach 60 Sekunden ohne Server-Antwort bzw. nach 180 Sekunden Gesamtdauer - bisher lautlos. Der Fertig-Ton ist das Signal fuer "vollstaendig", sein Ausbleiben aber hoert man nicht. Angesagt wird nur, wenn der Nutzer auch wirklich in dieser Ergebnisliste steht; laeuft die Suche im Hintergrund, bleibt es still. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.1 Ueberblick Aenderungen Der Kauf mehrerer Stuecke im Auktionshaus laeuft jetzt durch, solange es weitere Angebote zum gleichen hoerbaren Preis gibt. Jeder gelungene Kauf wird sofort mit "Gekauft, n von m" bestaetigt. Ist ein Preis ausverkauft, meldet Sku "Keine weiteren Angebote zu diesem Preis" samt Bilanz und bleibt in der Ergebnisliste stehen. Neue Einstellung "Tastatur-Echo ansagen" (Einstellungen -> Allgemein, standardmaessig an): das zeichenweise Vorlesen beim Tippen in Eingabefeldern laesst sich abschalten. Auktionshaus: der Komplettscan bestaetigt sich schon nach 5 Sekunden zum ersten Mal, danach wie bisher alle 10 Sekunden. Questmenue: der Eintrag "Gruppenmitglieder" steht jetzt an dritter Stelle statt in der Mitte, "Aktuelle Quests" und "Questdatenbank" behalten dadurch immer ihren Platz. Fehlerbehebungen Auktionshaus: der Kauf mehrerer Stuecke brach nach fast jedem gelungenen Kauf faelschlich mit "Auktion vergriffen" ab und warf aus der Suche. Nach dem Schliessen des Menues sprachen verzoegerte Ansagen weiter ("Neuer Brief plus", "Betreff: ", "Gesendet", "Alle geoeffnet" aus dem laengst geschlossenen Briefkasten). Auktionshaus: eine unvollstaendige Server-Antwort beendet die Suche nicht mehr faelschlich mit "leer" - eine echte Suche ohne Treffer antwortet weiterhin sofort. Auktionshaus: eine Suche, die gar nicht erst starten kann, nennt jetzt den Grund ("Nicht moeglich, scan laeuft" bzw. "Auktionshaus beschaeftigt") statt "leer" zu sagen. Auktionshaus: eine Suche ohne Treffer sagt jetzt "keine Ergebnisse" statt "leer" - und das Suchfeld bleibt in der Liste, der Cursor landet direkt darauf. Auktionshaus: ein per Schliessen abgebrochener Komplettscan blockierte danach jede Suche mit "Nicht moeglich, scan laeuft", obwohl kein Scan mehr lief. Auktionshaus: der Komplettscan brach manchmal direkt nach der Startansage stillschweigend ab; die 16-Minuten-Sperre war trotzdem verbraucht. Franzoesische Clients: in mehreren Zonen war die Wegpunktliste leer (Korrektur von Naxedim). Neue Einstellung: Tastatur-Echo ansagen Einfach: In Eingabefeldern (Brief schreiben, Suche, Profilname...) liest Sku jedes getippte Zeichen vor, ebenso Ruecktaste und die Cursor-Lesungen mit den Pfeiltasten. Wer das nicht mag oder es doppelt hoert, schaltet es jetzt unter Einstellungen -> Allgemein, "Tastatur-Echo ansagen" ab (direkt neben "Menuenummern ansagen" und "Untermenues ansagen"). Standard ist AN, es aendert sich also nichts, wer nichts umstellt. Statusansagen wie "Abgebrochen" oder die Feld-Bestaetigung nach ENTER bleiben immer. Keine Ansagen mehr in ein geschlossenes Menue hinein Einfach: Wer ein Eingabefeld mit ENTER bestaetigte und gleich darauf das Menue schloss, hoerte trotzdem noch "Betreff: " - als kaeme das Tastatur-Echo nach dem Schliessen hinterher. Genauso sprachen aus dem laengst geschlossenen Briefkasten noch "Neuer Brief plus", "Gesendet" oder "Alle geoeffnet". Jetzt gilt: was einen Menue-Eintrag ansagen will, prueft erst, ob das Menue ueberhaupt noch offen ist - und die Briefkasten-Quittungen pruefen, ob der Briefkasten noch offen ist. Die Server-Systemzeile "Post verschickt." im Chat bleibt davon unberuehrt. Technisch: Die Nachzuegler waren nie die Sprach-Queue (das Schliessen leert sie schon per queuereset + StopSpeakingText), sondern Erzeuger, die NACH dem Schliessen erst einspeisen: C_Timer-Bestaetigungen (0,3 s nach Anhaengen/Feldeingabe/Senden, 0,5 s nach "Alle oeffnen") und Server-Events (MAIL_SEND_SUCCESS). Eine weitere pauschale Queue-Leerung beim Fensterschliessen wuerde sie deshalb nicht erwischen, aber legitime Ansagen (Chat, Kampf, Navigation) mitten im Wort abschiessen. Stattdessen: zentrales Gate in SkuOptions:VocalizeCurrentMenuName (kein offenes Menue, kein kopfloses Kampfmenue und kein SkuChat-Zeilenmenue -> stumm; der String-Modus liefert weiter Text), plus drei Erzeuger-Gates in der Post (MailboxOpenFlag fuer "Gesendet", IsMenuOpen fuer die Feld-Bestaetigung, MailFrame-Sichtbarkeit fuer "Alle geoeffnet"). MAIL_FAILED bleibt bewusst ungefiltert - ein Fehlschlag muss auch nach dem Schliessen hoerbar sein. Auktionshaus: der Kauf mehrerer Stuecke brach nach fast jedem Kauf faelschlich mit "Auktion vergriffen" ab Einfach: Wer in der Ergebnisliste einen Eintrag wie "14 mal Sphaere der Leere" waehlte und davon fuenf Stueck kaufen wollte, hoerte fast nach jedem Kauf "Auktion vergriffen" und stand wieder ausserhalb der Suche - obwohl der Kauf gelungen war und das Geld korrekt abging. Da der Erfolg selbst nie angesagt wurde, klang das nach lauter Fehlschlaegen, waehrend die Stuecke laengst im Beutel lagen. Die Ursache: Verkaeufer unterbieten sich um je 1 Kupfer. Die Ergebnisliste fasst alle Auktionen zusammen, deren Preis GLEICH KLINGT - ab 1 Gold wird der Kupferanteil nicht mitgesprochen -, der Weiterkauf suchte das naechste Stueck aber zum exakten Kupferbetrag, und den gab es nach dem Kauf des billigsten meist nicht mehr. Jetzt kauft der Weiterkauf eine solche Gruppe Stueck fuer Stueck durch: das naechste Angebot darf sich nur im Kupfer unterscheiden, also im nicht hoerbaren Teil des Preises. Ein hoerbar teureres Angebot - egal ob 1 Silber oder 100 Gold teurer - wird NIE automatisch angeboten, und jedes einzelne Stueck verlangt weiterhin seine eigene Eingabe. Technisch: Belegt im Debug-Log vom 2026-08-25: fuenf Kaeufe zu 52g99s81k bis 52g99s84k, jeder Lauf kaufte genau ein Stueck und brach dann ab. Die Fortsetzung (_ABReQueryBuy → Match-Scan) verglich Item-ID + Stueckzahl + EXAKTEN Sofortkaufpreis; die Ergebnisliste gruppiert aber nach dem formatierten Label (SkuGetCoinText very-short laesst Kupfer ab 1 Gold weg), eine Gruppe umfasst also einen 1-Silber-Eimer. Der Scan merkt sich jetzt das billigste kaufbare Angebot mit gleicher Item-ID und Stueckzahl im gleichen Eimer (floor(buyout/100) identisch, nur ab 10000 Kupfer) und uebernimmt dessen Preisfelder (8/9/10/11) in QueryBuyData; der failCount startet fuer die neue Preisgruppe bei 0. Unter 1 Gold spricht das Label den Kupfer mit - dort bleibt das alte exakte Verhalten. Gebots-Kaeufe behalten den strengen 17-Feld-Vergleich. Auktionshaus: jeder Kauf wird bestaetigt, das Ende einer Preisgruppe meldet die Bilanz und bleibt in der Liste Einfach: Nach jedem gelungenen Stueck sagt Sku jetzt sofort "Gekauft, n von m" - vorher war das einzige Erfolgssignal der naechste Kaufprompt. Sind alle Angebote zum gleichen hoerbaren Preis weg, heisst es "Keine weiteren Angebote zu diesem Preis" mit der Bilanz, etwa "2 von 5 gekauft", und der Cursor bleibt auf dem Eintrag in der Ergebnisliste stehen, statt wie bisher mehrere Ebenen nach oben auf "Auktionen" zu springen. Von dort laesst sich direkt zum naechsten, teureren Eintrag navigieren und dort neu kaufen. Technisch: Die Erfolgsansage sitzt in _ABContinueOrFinish, direkt nach dem Server-"Gebot akzeptiert.". Der Vergriffen-Pfad positioniert zuerst (AuctionStayOnResultsEntry; schlaegt das Pruning fehl, weil der Datensatz nach dem Kauf bereits entfernt war, haelt ein Fallback ueber AuctionResultsItemEntryFromCursor den Cursor auf dem Item-Eintrag) und spricht die Meldung 0,4 s spaeter ohne Unterbrechung - dasselbe Muster wie beim bestehenden "Fertig. Alle gekauft". Auktionshaus: unvollstaendige Server-Antwort gilt nicht mehr als "keine Treffer" Einfach: Antwortet der Server widerspruechlich - er meldet Treffer, liefert aber keine einzige Zeile -, dann beendete Sku die Suche bisher sofort mit "leer". Jetzt wartet es in diesem Fall auf die vollstaendige Antwort und fragt die Seite noch einmal an. Eine Suche, die wirklich nichts findet (Tippfehler im Suchfeld, leere Kategorie), antwortet unveraendert sofort - mit der Trefferzahl 0 und "keine Ergebnisse". Technisch: In AUCTION_ITEM_LIST_UPDATE_LIST gilt eine leere Seite nur dann als verfrueht, wenn der Server sich widerspricht: tBatch == 0 (keine Zeile auf dieser Seite) bei tCount > 0 (Gesamttrefferzahl groesser 0). Dann zaehlt QueryListEmptyWaits hoch, der Scan bleibt auf "waiting" und der Ticker fragt dieselbe Seite erneut an; nach 10 solchen Antworten wird das Ergebnis doch akzeptiert (Notausstieg). tCount == 0 ist dagegen die ehrliche Antwort "keine Treffer" und muss ohne Verzoegerung durchlaufen: der Kauf-Pfad zaehlt an dieser Stelle JEDE leere Antwort (QueryBuyEmptyWaits), weil er eine womoeglich noch lebende Auktion wiederfinden will - fuer die Suche waere dieselbe Regel falsch. Im Debug-Log vom 2026-08-26 beantwortet der Server die Suche "feuerpartiekel" in derselben Sekunde mit 0 von 0; das ist die echte Antwort, keine Spuk-Antwort. Auktionshaus: eine Suche, die gar nicht erst starten kann, nennt jetzt den Grund Einfach: Es gibt Momente, in denen das Auktionshaus eine Suche nicht annimmt: waehrend im Hintergrund ein Komplettscan laeuft, waehrend ein Kauf scharf ist, oder wenn der Server gerade drosselt. Bisher merkte Sku das nicht - es baute die Liste trotzdem auf und sagte "leer", als haette die Suche nichts gefunden. Beim ersten Aufruf in einer Sitzung klang das nach einer leeren Kategorie, spaeter zeigte die Liste sogar die Treffer der VORIGEN Suche. Jetzt nennt Sku den Grund. Laeuft ein Komplettscan, steht sofort beim Oeffnen "Nicht moeglich, scan laeuft" in der Liste - dieselbe Meldung, die das Verkaufen-Menue in dieser Lage schon immer gibt. Warten hat dort keinen Sinn: ein Komplettscan belegt das Auktionshaus minutenlang. Bei den kurzen Huerden (scharfer Kauf, Drossel) bleibt Sku auf "Warten" stehen und versucht es von selbst weiter; kommt die Suche innerhalb von 5 Sekunden durch, laeuft alles wie gewohnt weiter, sonst heisst es "Auktionshaus beschaeftigt, Suche nicht gestartet". Faengt waehrend dieser Versuche ein Komplettscan an, bricht Sku sie gleich ab und sagt es. Mit Pfeil links und wieder rechts startet man jederzeit einen neuen Versuch. Technisch: AuctionHouseStartQuery liefert an drei Stellen false und seit dieser Version den GRUND als zweiten Rueckgabewert ("secureBuy", "getAllRunning", "getAllCooldown", "queryThrew"). Die drei Browse-Aufrufer - Suchfeld, "Alle" und Einzel-Item in AuctionHouseBuildItemDBMenu - hatten den Rueckgabewert ignoriert und trotzdem QueryResultsHost gesetzt, children geleert und neu gebaut; der ResultsMenuBuilder fand state == "idle", uebersprang seinen "Warten"-Zweig und fiel auf die Leer-Pruefung durch. Sie laufen jetzt ueber AuctionBrowseStart, das am Grund entscheidet: getAll-Gruende sofort melden, alles andere als Wiederholversuch einreihen (QueryStartPending). AuctionBrowseRetryTick haengt am bestehenden AH-OnUpdate-Ticker - bewusst frame-getrieben und nicht als C_Timer-Kette, weil eine abgewuergte Kette ihre Re-Arm-Zeile nie erreicht -, steht ganz vorn vor dessen fruehen Returns (sonst fror er waehrend des getAll-Ingests ein), versucht hoechstens alle 0,25 s und nur bei CanSendAuctionQuery, prueft den Grund erneut und reiht sich nach einem Fehlversuch explizit wieder ein - StartQuery ruft intern ResetQuery auf und loescht dabei den Merker, auch wenn es danach doch false liefert. Nach Erfolg wird QueryResultsHost neu gesetzt, weil der frische Query-Aufbau ihn nilt. QueryStartFailed traegt den anzuzeigenden TEXT (AH_QueryBusy bzw. die Scan-Meldung des Verkaufen-Menues) und wird VOR der "Warten"-Bedingung geprueft: der blockierende Scan haelt AuctionScan.state selbst auf "waiting"/"paging", also gewaenne sonst immer "Warten" und die Begruendung waere unerreichbar. Der Sofort-Pfad spricht bewusst NICHT selbst - die Meldung ist der einzige Listeneintrag und wird beim Oeffnen ohnehin vorgelesen, waehrend eine eigene Ansage vom folgenden Vocalize abgeschnitten wuerde und bei jedem Vorbeinavigieren erneut feuerte (OnEnter laeuft schon beim Ankommen). ResetQuery raeumt beide Merker ab. Auktionshaus: "keine Ergebnisse" statt "leer", und das Suchfeld bleibt erreichbar Einfach: Eine Suche ohne Treffer - etwa mit einem Tippfehler - sagte bisher "leer". Das klingt nach einer leeren Liste, gemeint ist aber "nichts gefunden": jetzt heisst es "keine Ergebnisse". Ausserdem war das Suchfeld nach einer Suche aus der Liste verschwunden; fuer eine zweite Suche musste man erst raus- und wieder reinnavigieren. Es steht jetzt weiterhin als "Suchbegriff eingeben" in der Liste, und bei null Treffern springt der Cursor gleich darauf - einmal ENTER und man tippt den naechsten Begriff. Gibt es Treffer, landet der Cursor wie gewohnt auf dem ersten Treffer. Technisch: Der inkrementelle Aufbau rief den ResultsMenuBuilder direkt auf und umging damit BuildChildren des Suchfeld-Eintrags - genau dort wird "Suchbegriff eingeben" eingehaengt, deshalb war es nach der ersten Seite weg. Er ruft jetzt aHost:BuildChildren(aHost) (fuer "Alle"/Einzel-Item IST das der ResultsMenuBuilder). Damit der Suchfeld-Eintrag dabei nicht auf "Warten" zurueckfaellt, prueft sein Gate zusaetzlich QueryResultsPartialReady. Die Cursor-Wahl uebernimmt AuctionFocusAfterResults: erster Eintrag, der weder Eingabefeld noch "keine Ergebnisse" noch "Warten" ist; gibt es keinen, das Eingabefeld. Die Nulltreffer-Ansage laeuft als EINE Ausgabe ("keine Ergebnisse;Suchbegriff eingeben") - ein zweites OutputStringBTtts haette das erste abgeschnitten. In der Komplettscan-Kategorieliste heisst der Nulltreffer-Eintrag ebenfalls "keine Ergebnisse"; der Zweig ohne jegliche Scan-Daten bleibt "leer", weil das eine andere Aussage ist. Auktionshaus: abgebrochener Komplettscan blockierte danach jede Suche Einfach: Wer einen laufenden Komplettscan abbricht, indem er das Auktionshaus schliesst, bekam danach bei JEDER Suche und jeder Kategorie "Nicht moeglich, scan laeuft" zu hoeren - obwohl gar kein Scan mehr lief. Das blieb so, bis man einen neuen Komplettscan startete und ihn auch durchlaufen liess. Jetzt raeumt das Schliessen den Scan richtig ab, und die naechste Suche laeuft normal. (Die 16-Minuten-Sperre des Servers fuer den naechsten Komplettscan bleibt davon unberuehrt - die ist serverseitig und auch nach einem Abbruch aktiv.) Technisch: AuctionHouseResetQuery verweigert den Reset, solange ein getAll-Scan laeuft, ausser der Aufrufer besteht mit force darauf - das schuetzt einen laufenden Komplettscan davor, von einem beilaeufigen Reset (Verkaufen-Menue, Browse-Pfade) abgewuergt zu werden. AUCTION_HOUSE_CLOSED rief AuctionScanFinish OHNE force auf, also blieb nach dem Schliessen mitten im Scan state = "waiting" mit QueryData.getAll = true stehen; genau das prueft die Verweigerungslogik der Suche, also wurde ab da jede Query mit "getAllRunning" abgewiesen. Das Schliessen forciert jetzt - es IST das Scan-Ende, danach kommen ohnehin keine Events mehr. Zwei Log-Luecken, die den Fehler versteckt haben, sind mit gefixt: die Verweigerung in AuctionHouseResetQuery schreibt jetzt eine eigene Zeile (vorher sah man nur den Aufruf davor und hielt den Zustand fuer geraeumt), und AuctionScanFinish meldet "finished" erst NACH dem Reset, mit reset=true/false - vorher behauptete das Log ein Scan-Ende, das nie stattfand. Auktionshaus: erste Komplettscan-Ansage schon nach 5 Sekunden Einfach: Waehrend der Komplettscan auf die Antwort des Servers wartet, meldet Sku alle 10 Sekunden "voller Scan, n Sekunden". Die allererste dieser Ansagen kam damit auch erst nach 10 Sekunden - zehn Sekunden, in denen man nach dem Start nicht wusste, ob der Scan ueberhaupt laeuft. Die erste Bestaetigung kommt jetzt nach 5 Sekunden, die zweite 10 Sekunden spaeter, danach weiter im 10-Sekunden-Takt (also bei 5, 15, 25 ... Sekunden). Am Ende aendert sich nichts: die 25-Prozent-Meldungen der Einlesephase und die Abschlussansage bleiben. Technisch: Der Takt im AH-OnUpdate-Ticker liegt jetzt in tFullScanSpeakNext, das mit tFullScanSpeakFirst (5) startet und nach der ersten Ansage auf tFullScanSpeakEvery (10) umschaltet. Der Zaehler wird um den jeweils gueltigen Schwellwert vermindert statt fest um 10, damit die Phase stimmt. Endet die Arbeitsphase, faellt der Schwellwert wieder auf 5 zurueck - sonst haette der naechste Scan erst nach 10 Sekunden seine erste Bestaetigung gegeben. Auktionshaus: der Komplettscan brach manchmal direkt nach der Startansage stillschweigend ab Einfach: Manchmal folgte auf "Komplettscan gestartet" einfach nichts mehr: keine 10-Sekunden-Fortschrittsansage, keine Fertigmeldung, und die Menues, die waehrend eines Scans gesperrt sein sollten, waren es nicht - die 16-Minuten-Sperre war trotzdem verbraucht. Das traf vor allem, wer die Wartezeit bis zum naechsten Scan direkt am offenen Auktionshaus absass. Der Scan wurde intern sofort nach dem Start wieder abgewuergt; jetzt startet er immer mit frisch genullter Uhr. Technisch: Belegt im Debug-Log vom 2026-08-26: QueryAuctionItems und "watchdog: getAll timeout 600s" in DERSELBEN Sekunde. Die Watchdog-Zaehler des Scan-Tickers waren schon vor dem Start voll: tTime sammelte die komplette Leerlauf-Standzeit am offenen AH (der Idle-Zweig setzte es nie zurueck - die 16-Minuten-Wartezeit > 600 s reichte allein), und tFullScanElapsed ueberlebte jedes Scan-Ende, weil sein Reset hinter dem 0,2-s-Tick-Gate des Serialize-Zweigs liegt, das eine schnelle Serialisierung nie passiert. Der erste Watchdog-Tick nach dem Start addierte beides und wuergte den frischen Scan ab; dabei nullte der Watchdog sich selbst, weshalb die naechsten Versuche wieder liefen - daher das "meistens geht es". Jetzt nullt SkuCore.AuctionScanWatchdogReset beide Zaehler nach jedem wirklich abgesetzten QueryAuctionItems, und der Idle-Zweig setzt tTime selbst zurueck (schuetzt auch den Stall-Watchdog der paginierten Suchen). Verifiziert 2026-08-26: Scan nach ~28 min Standzeit am AH lief durch, 173841 Auktionen eingelesen. Franzoesische Clients: in mehreren Zonen war die Wegpunktliste leer (Korrektur von Naxedim) Einfach: In den Hoehlen des Wehklagens, in der Tiefenbahn, in der Holzschlundfeste und in Onyxias Hort meldete Sku eine leere Wegpunktliste, obwohl die Zone vollstaendig kartiert ist. Zwei Beobachtungen grenzten es ein: eine bereits laufende Route lief weiter, und von ausserhalb der Zone liessen sich dieselben Wegpunkte anwaehlen. Es fehlten also keine Daten - Sku wusste nur nicht, in welcher Zone der Charakter steht. Auf deutschen und englischen Clients trat das nie auf. Technisch: Zwei unabhaengige Ursachen mit demselben Symptom, beide von Naxedim auf einem franzoesischen Client gefunden, behoben und im Spiel geprueft (PR #8). Erstens vergleicht SkuNav/Geo.lua eine Handvoll Zonennamen WOERTLICH mit GetMinimapZoneText(); vier davon waren in locales/frFR.lua frei uebersetzt worden, also traf kein Vergleich mehr, und GetBestMapForUnit lieferte die Kontinentkarte statt der Zonenkarte. Die neuen Werte stammen aus C_Map.GetAreaInfo() auf einem franzoesischen Client, nicht aus einer Uebersetzung. Zweitens haengen Instanzen, deren echte Area-Zeile in SkuDB/assets/maps.lua auskommentiert ist, an einer synthetischen Zeile (id ab 100000), fuer die C_Map nichts aufloesen kann; sie blieb englisch, waehrend der letzte Fallback von GetCurrentAreaId sie gegen den lokalisierten KARTENnamen prueft - kein Treffer, keine AreaId, kein Kontinent, leere Liste. Diese Zeilen bekommen ihren Namen jetzt von der uiMap mit demselben englischen Namen; auf franzoesisch sind das genau zwei, Onyxias Hort und die Hoehlen des Wehklagens. Danach ergaenzt: eine Sperre, damit dabei keine synthetische Zeile einen Namen erhaelt, den eine echte Zeile schon traegt (Tausendwinter), die Markierung "nicht frei uebersetzen" an allen woertlich verglichenen Zonennamen in locales/enUS.lua, und ein franzoesischer Uebersetzungsspeicher, der ueber den Schluessel statt ueber die Zeilennummer gefuehrt wird - er war um eine Zeile verrutscht und haette bei der naechsten Neugenerierung fast die ganze Tabelle verschoben. Nebenbei fuer englische Clients: L["Die Hoehlen des Wehklagens"] stand auf "The Wailing Caverns", was kein Client so sagt. Derselbe Sonderfall war dort also ebenfalls tot und ist jetzt korrigiert. Questmenue: "Gruppenmitglieder" haengt sich hinten an Einfach: Mit geladenem Questie zeigt Sku in einer Gruppe zusaetzlich die Quests der Mitspieler an. Dieser Eintrag stand bisher zwischen "Aktuelle Quests" und "Questdatenbank" - und weil er mit der Gruppe kommt und geht, rutschte die Questdatenbank je nach Gruppenstatus zwischen Platz zwei und Platz drei hin und her. Wer den Weg dorthin im Muskelgedaechtnis hat, landete solo woanders als in der Gruppe. Jetzt steht "Gruppenmitglieder" immer ganz hinten an dritter Stelle; die ersten beiden Eintraege bleiben an derselben Stelle, allein wie in der Gruppe. Technisch: In SkuQuest:MenuBuilder wandert der bedingte tSpecs-Block (showGroupQuests + QuestieReady + IsInGroup) hinter den "Questdatenbank"-Block. SkuMenu:Build rendert die Specs in Array-Reihenfolge ohne jede Sortierung, die Reihenfolge im Quellcode ist also die Reihenfolge im Menue. Am Eintrag selbst, an seiner Bedingung und an seinen Untermenues aendert sich nichts. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v43.0 Ueberblick Neu Shift-F9 bis Shift-F12 haben jetzt eigene Eintraege in der Tastenbelegung, die Schnellzugriffe 1 bis 4 sind wieder frei. Die Ansagen im Taxiflug lassen sich abschalten, und sie nennen nie mehr den Start- oder Zielpunkt als Landemoeglichkeit. Neue Aura-Bedingung "Buff Debuff nur selbst gewirkte" filtert die Buff- und Debufflisten auf Effekte, die du selbst gewirkt hast. Neuer Befehl /skucheck prueft feste Regeln gegen den laufenden Spielzustand; er hat auch die Datenbank-Werkzeuge als Unterbefehle uebernommen (wp, db, mem). Der Installer sammelt auf Knopfdruck alle Logdateien fuer eine Fehlermeldung. Der Anmeldebildschirm ist mit dem Anmelde-Tool jetzt bedienbar. Wegpunktlisten sagen an, wie weit das Laden fortgeschritten ist. Aenderungen Auren-Ablaufwarnungen kommen puenktlich statt erst beim naechsten Kampfereignis. Die Aurenauswertung pro Kampfereignis ist deutlich billiger geworden. Navigation abbrechen liegt nur noch auf einer Taste. Der Energiemonitor kann der Ressourcenleiste folgen, die das Spiel gerade zeigt - ein Druide bekommt so je nach Gestalt Mana, Wut oder Energie. Das Protokoll des Anmelde-Tools ueberlebt einen Neustart des Tools. Die Wegpunktdaten der Routen sind nach dem Anmelden deutlich frueher benutzbar, der eigene Kontinent zuerst, und brauchen rund 22 MB weniger Arbeitsspeicher; der Teil der Routendaten, den die eigene Spielversion nicht liest, wird gar nicht mehr aufgebaut. Auren sind jetzt international austauschbar: eine Aura wirkt auf jedem Sprachclient. Geteilte Aurensets kommen bei Mitspielern anderer Sprache benutzbar an. Alle Raenge eines Zaubers zaehlen fuer eine Aura als ein Eintrag. Zaubernamen, die im Spiel mehrfach vergeben sind, lassen sich in den Auswahllisten jetzt unterscheiden. Die mitgelieferten Aurensets gibt es nicht mehr nur auf deutschen Clients. Das Menue zum Anlegen einer Aura ist neu aufgebaut: nach Namen sortierte Attributliste, Bedingungen mit zwei Werten als Schalter, Zauber auch tippbar statt nur waehlbar, und alle Wertelisten oeffnen schneller. Jeder Menueeintrag im ganzen Addon wird rund 13 mal guenstiger erzeugt; die grossen Zauberlisten oeffnen dadurch etwa dreimal so schnell. Eine Liste, deren Aufbau vom Server abgebrochen wurde, wird im naechsten Frame weitergebaut statt unbemerkt unvollstaendig zu bleiben. Einstellungen mit zwei Werten sagen ihren Wert gleich mit und schalten mit Enter um; Pfeil rechts und das Untermenue entfallen. Die Lautstaerkeregler im Sku-Menue stellen die Spieleinstellung direkt ein; Sku speichert keine eigene Kopie mehr. Fehlerbehebungen Franzoesische Clients: alle Aura-Sounds und aufgenommenen Sprachclips waren stumm (Korrektur von Naxedim). Franzoesische Clients: die Entfernungspruefung sagte nichts an und ihr Menue warf einen Fehler (Korrektur von Naxedim). Franzoesische Clients: zwei Nachzuegler aus demselben Bericht behoben. Neun Uebersetzungstexte bedeuteten je nach Sprache etwas anderes (Korrektur von ZenqFR). Auren: manche Gruppenplaetze wurden als Piepser statt als Wort angesagt. Auren: eine Aura mit "einmal" konnte im dichten Kampf mehrfach hintereinander feuern. Menue: die Wegpunktliste auf Shift-F9 oeffnete sich auf grossen Karten erst beim zweiten Versuch. Die Schluessel im Schluesselbund wurden als "Leer" angesagt. Auf Hardcore-Realms baut Sku seine Wegpunktdaten jetzt fertig statt still stehenzubleiben. Navigation: die Routenliste konnte leer und stumm bleiben, wenn die Wegpunktdaten waehrend eines offenen Menues neu aufgebaut wurden. Fehlende Routendaten werden jetzt gemeldet, statt als leere Liste zu erscheinen. Ein Popup, das im Kampf aufging (Gruppeneinladung, Beschwoerung, Wiederbeleben), liess sich lesen, aber nicht beantworten. Eine Route liess sich nicht starten, wenn ihre Liste waehrend des Ladens fertig wurde. Das Anmelde-Tool hielt den Anmeldebildschirm faelschlich fuer die Charakterauswahl. Anmelde-Tool: Auf Realms mit zehn oder mehr Charakteren war die Charakterliste unvollstaendig, falsch nummeriert oder liess sich nicht zurueckblaettern. Energiemonitor: die Ressourcenauswahl "nichts" warf laufend Lua-Fehler. Energiemonitor: ein im Funktionsmenue abgeschalteter Monitor sagte Ressourcenaenderungen trotzdem an. Franzoesische Clients: die Liste der Waffenverzauberungen fuer Auren war leer. Der Bereitschaftscheck sprang nicht direkt auf "Bereit", wie es jedes andere Popup tut. Eine im Sku-Menue gesetzte Spiel-Lautstaerke konnte auf einem anderen Charakter wieder auf einem alten Wert stehen. Die vier Standardprofile werden angelegt, ohne dazwischen das Profil zu wechseln - auf Hardcore-Realms konnte man dabei in einem fremden Profil landen. Mit Dank an Naxedim und ZenqFR Die naechsten vier Korrekturen sind die ersten direkten Code-Beitraege zum inzwischen oeffentlichen Sku-Repository. Naxedim hat die beiden Fehler gefunden, analysiert und behoben, die auf franzoesischen Spielclients grosse Teile der Sku-Audioausgabe stumm geschaltet hatten; ZenqFR hat die Uebersetzungsdateien geprueft, alle widerspruechlichen Duplikate auf der englischen und franzoesischen Seite aufgeloest und das Werkzeug verbessert, das vor neuen schuetzt. Die volle Anerkennung fuer diese Korrekturen gebuehrt den beiden. Franzoesische Clients: alle Aura-Sounds und aufgenommene Sprachclips waren stumm (Korrektur von Naxedim) Einfach: Auf einem franzoesischen Spielclient spielte seit v42.11 jede Aura, deren Ausgabe ein Sound ist, gar nichts mehr ab - kein Fehler, keine Logzeile, einfach Stille - und jeder aufgenommene Sprachclip fiel unbemerkt auf reines TTS zurueck. Die Ursache: Seit Sku franzoesisch spricht, sucht es auch ein FRANZOESISCHES Sprachpaket, und ein solches Paket gibt es nicht, also fand die Suche nichts und alles, was das Sprachpaket bereitstellt, verstummte. Sprachausgaben wurden nur zu TTS herabgestuft, aber ein Soundeffekt hat nichts, worauf er zurueckfallen koennte - deshalb fuehlte es sich an wie "meine Auren gehen nicht mehr" statt "die Audioausgabe hat sich geaendert". Die Paketsuche nutzt jetzt denselben englischen Rueckfall, den der Rest des Audiosystems seit v42.09 verwendet. Deutsche und englische Clients sind vollstaendig unberuehrt. Technisch: Der Sprachpaket-Resolver in Core.lua verglich die Paket-Locales mit Sku.Loc; seit v42.11 locales/frFR.lua mitliefert, ist Sku.Loc auf franzoesischen Clients "frFR", kein Paket konnte das deklarieren, Sku.AudiodataPath blieb "" und VoicePackAudioDir() lieferte nil - stumm wurden damit alle 64 Eintraege von SkuCore.outputSoundFiles (Aura-Sounds, SkuMob-Kampfsound, SkuChat-Zeilensound) plus jeder Sprachclip des Pakets. Verglichen wird jetzt Sku.LocAudio oder Sku.Loc, exakt die "auf welche aufgenommene Sprache falle ich zurueck"-Regel, die IntegratedAudioDir() bereits nutzt; Sku.LocAudio ist auf jedem nicht-deutschen Client "enUS", deDE/enUS verhalten sich also byte-identisch. Auf einem echten franzoesischen Client gefunden, behoben und im Spiel verifiziert von Naxedim (PR #5). Franzoesische Clients: die Entfernungspruefung sagte keine Distanzen mehr an und ihr Menue warf einen Fehler (Korrektur von Naxedim) Einfach: Auf einem franzoesischen Client sagte die Entfernungspruefung keinerlei Distanz mehr an, egal bei welchem Ziel, und das Oeffnen des Entfernungs-Menues erzeugte einen Fehler statt des Menues. Zwei Ursachen, beide nur franzoesisch: Erstens wird die Einstellung "Distanz sprechen" als uebersetztes WORT fuer "Gesprochen" in der Konfiguration gespeichert - eine Konfiguration, die geschrieben wurde, als Sku noch englisch lief (vor v42.11), enthaelt das englische Wort, das der jetzt franzoesische Client nicht mehr erkennt. Zweitens existieren die Zahlenclips nur auf Deutsch und Englisch, und der Code zaehlte genau diese beiden Sprachen auf - ein franzoesischer Client bekam also selbst mit frisch geschriebener franzoesischer Konfiguration Stille. Der gespeicherte Marker wird jetzt in allen drei Sprachen akzeptiert, ein unbekannter Wert kann das Menue nicht mehr zerlegen, und die Clips fallen wie der Rest des Audiosystems auf die englischen Aufnahmen zurueck. Deutsche und englische Clients sind unveraendert: gleicher Marker, gleiche Clips, gleiche Audioausgabe. Technisch: Ein neues RangeCheck:IsSpokenSound() akzeptiert "Gesprochen"/"Spoken"/"Parlé" (plus das live uebersetzte L["vocalized"]), genutzt von DoRangeCheck und dem Menuebauer in Options.lua - letzterer lief bei unbekanntem Wert bisher in den else-Zweig und verkettete nil aus SkuCore.RangeCheckSounds, was den Fehler warf. Der Clip-Ordner kommt jetzt aus Sku.LocAudio (hans_de-de fuer deDE, sonst hans_en-us) statt aus einer Sku.Loc-Kette, die auf frFR keinen Zweig traf. Neue Eintraege schreiben weiter L["vocalized"]; keine Datenmigration. Auf einem echten franzoesischen Client gefunden und verifiziert von Naxedim (PR #6). Uebersetzungen: neun Texte bedeuteten je nach Sprache etwas anderes (Korrektur von ZenqFR) Einfach: Neun Texte standen doppelt mit zwei VERSCHIEDENEN Bedeutungen in den Uebersetzungsdateien, und jede Sprache konnte am Ende eine andere der beiden erwischen. Am hoerbarsten auf englischen Clients, wo mehrfach der falsche Zwilling gewann: Die Haltungs-Aktionsleiste wurde als "Special Action bar" angesagt (eine ganz andere Leiste), die Debug-Taste als "debug mode" statt "debug output", eine Menuekategorie als "Features" statt "Values". Fuer jedes Paar wurde anhand der Verwendung im Code die tatsaechlich richtige Bedeutung bestimmt und der falsche Zwilling in allen drei Sprachen geloescht - Englisch, Deutsch und Franzoesisch sind sich bei allen neun jetzt einig. Sechs rein deutsche Duplikate bleiben bewusst offen, bis ein deutscher Muttersprachler entscheidet. Technisch: AceLocale loest doppelte Schluessel fuer die Standardsprache (enUS) nach "erster gewinnt" auf, ueberall sonst nach "letzter gewinnt" - ein Duplikat mit zwei Werten bedeutet also still etwas anderes pro Sprache. ZenqFR hat fuer jeden Schluessel die echten Aufrufstellen verfolgt, um den ueberlebenden Wert zu bestimmen (PR #3), und dev/rework-docs/_locale_dupes.py beigebracht, nur das geparste Lua-String-Literal statt der rohen Zeile zu vergleichen, damit angehaengte "--"-Kommentare nicht mehr als Konflikt zaehlen (PR #4) - von 64 gemeldeten Konflikten waren nur 30 echt; enUS und frFR linten jetzt auf null, deDE auf die sechs deutschen Formulierungspaare, die einem Muttersprachler ueberlassen bleiben. Franzoesische Clients: zwei Nachzuegler aus Naxedims Sprachpaket-Bericht Einfach: Der Sound namens "bring" - eine Glocke, benannt nach ihrem Klang - stand in franzoesischen Menues als "apporter": Die Uebersetzung hatte ihn als das englische Verb "to bring" gelesen. Es ist ein Name, kein Wort, und bleibt jetzt wie seine unuebersetzten Geschwister "brang", "dang" und "drmm" einfach "bring". Ausserdem nennt die interne Diagnose, die festhaelt, welches Sprachpaket gefunden wurde, jetzt die tatsaechlich gesuchte Sprache statt der Client-Sprache - vorher haette ein franzoesischer Client ohne installiertes englisches Paket "no voice pack found for frFR" behauptet und damit auf ein Paket gezeigt, das es gar nicht geben kann. Technisch: locales/frFR.lua setzt L["bring"] auf die Onomatopoesie zurueck. Core.lua setzt Sku.AudiodataPathInfo jetzt in einem else-Zweig des Resolvers aus tWantedLoc (dem Sku.LocAudio-basierten Suchschluessel) plus der Client-Locale; auslesbar per /wdeval Sku.AudiodataPathInfo. Der dritte Punkt aus dem PR-#5-Bericht - frFR uebersetzt das Ausgabe-Label-Praefix zu "aura;son" - wurde geprueft und bewusst BEHALTEN: Jede Vergleichsstelle baut das Praefix zur Laufzeit aus der aktiven Locale-Tabelle, und gespeicherte Einstellungen/Auren halten Identifier-Schluessel ("sound-brass1"), nie das Label - die Uebersetzung ist also sicher; franzoesisches TTS fuer ein franzoesisches Label ist besser als ein englischer Clip. Taschen: die Schluessel im Schluesselbund wurden als "Leer" angesagt Einfach: Seit v42.13 sprach jeder Platz im Schluesselbund "Leer", obwohl die Schluessel da waren und sich weiter benutzen liessen - aufgefallen ist es erst, als jemand den Schluesselbund wirklich brauchte. Ausgeloest hat es die Bankkorrektur aus v42.13: Der Schluesselbund hat im Spielclient dieselbe Eigenheit wie das Bankhauptfach und brauchte dieselbe Sonderbehandlung, die damals nur die Bank bekommen hat. Jetzt werden die Schluessel wieder mit Namen angesagt. Ausserdem zeigt der Schluesselbund nur noch so viele Plaetze, wie er wirklich nutzt, statt stur alle 32 - vorher kamen nach den Schluesseln Dutzende leere Plaetze. Technisch: GameTooltip:SetBagItem(-2, slot) befuellt auf dem Client nichts, genau wie beim Bankcontainer -1. Die Schluesselnamen funktionierten nur ueber den generischen SetHyperlink-Rueckfall aus 67f2132; als v42.13 diesen Rueckfall absichtlich entfernte und nur die Bank (-1) auf SetInventoryItem umstellte, fiel der Schluesselbund still auf das leere SetBagItem zurueck. tSetTooltipContainerItem liest -2 jetzt ueber SetInventoryItem("player", KeyRingButtonIDToInvSlotID(slot)) - exakt das, was Blizzards eigenes ContainerFrameItemButton_OnEnter fuer den Schluesselbund tut. Build_BagsFrame begrenzt die Platzzahl von -2 zusaetzlich mit GetKeyRingSize() (belegte Plaetze auf volle Viererreihen gerundet), so wie Blizzards Schluesselbund-Fenster, statt die rohen 32 aus GetContainerNumSlots zu uebernehmen. Diagnose: neuer Befehl /skucheck prueft feste Regeln gegen den laufenden Spielzustand Einfach: /skucheck geht alle Taschendaten durch und prueft, ob jeder belegte Platz einen ansagbaren Namen liefert; das Ergebnis kommt als eine gesprochene Zeile, etwa "Taschenpruefung: 64 geprueft, keine Probleme", bei Problemen mit Verweis auf das Log. Der Befehl prueft die Daten selbst, nicht die Menues - er haette den Schluesselbund-Fehler also auch gemeldet, wenn man den Schluesselbund nie oeffnet. Die Pruefliste waechst nur mit behobenen Fehlern: Jede Korrektur bringt kuenftig ihre eigene Stolperdraht-Regel mit, damit eine spaetere Aenderung denselben Fehler nicht unbemerkt wieder einbauen kann. Seit dieser Version ist /skucheck ausserdem der einzige Pruefbefehl: Die drei Datenbank-Werkzeuge sind Unterbefehle geworden - /skucheck wp prueft die Wegpunktdaten und laeuft bei einem blossen /skucheck automatisch mit, /skucheck db und /skucheck mem sind Messungen und laufen nur auf Anforderung. Die alten Namen /skudbwpcheck, /skudbcheck und /skudbmem funktionieren weiter. Technisch: Am Ende von LocalMenu.lua; laeuft ueber tBagSlotListSorted mit derselben Container-API und derselben Namensaufloesung wie das Taschenmenue. Regel 1: Platz mit Item-Id, aber leerem Tooltiptext = Verstoss; jeder Verstoss landet als "skucheck"-Zeile mit Tasche, Platz, Item-Id und Link im SkuDebugLog-Ring. Die geschlossene Bank wird mit Logzeile uebersprungen (nicht still), der Schluesselbund absichtlich mit allen rohen 32 Plaetzen geprueft, und noch nicht vom Server geladene Items zaehlen als "ausstehend" statt als Fehler. Die Domaenen wp/db/mem rufen SkuDBTools.RunWpCheck/RunDbCheck/RunMem (SkuDBTools.lua); sie laufen als Hintergrundjob und sagen ihr Ergebnis selbst an, schreiben es aber zusaetzlich als "skucheck"-Zeilen in den Ring - die Wegpunkt-Verstoesse einzeln, die vorher nur in den SavedVariables lesbar waren. /skucheck db meldet zusaetzlich, wie viele Datensaetze sich gegenueber der vorherigen Aufnahme geaendert haben. Grund fuer die Zusammenlegung: Mit drei getrennten Befehlen liess sich "die Pruefung" laufen lassen und die Wegpunktregeln dabei komplett verfehlen. Auren: Ablauf-Warnungen kommen puenktlich, nicht erst beim naechsten Kampfereignis Einfach: Zwei alte Beschwerden hatten dieselbe Ursache: Eine Aura wie "Debuff auf dem Ziel unter 3 Sekunden" oder "mein Debuff ist vom Ziel abgefallen" wurde nur dann neu geprueft, wenn irgendein anderes Kampfereignis eintraf. In einem reinen Nahkampf kam die Warnung deshalb bis zu einem ganzen Waffenschlag zu spaet, ausserhalb des Kampfes um Minuten - oder gar nicht vor dem Ablauf. Jetzt merkt sich Sku beim Pruefen des Effekts, WANN die Schwelle erreicht sein wird, und weckt die Pruefung genau in diesem Moment; auch das Erscheinen oder Wegfallen eines Effekts selbst stoesst die Pruefung direkt an. Ausserdem duerfen die gesprochenen Woerter einer Aura jetzt wie die Signaltoene an wartenden Ansagen vorbeiziehen - sie unterbrechen nichts und ueberlappen nichts, sie stellen sich nur nicht mehr hinten an. Waffenverzauberungs-Warnungen profitieren mit: statt bis zu einer Sekunde Verzug feuern sie jetzt auf den Frame genau. Technisch: Drei Mechanismen: (1) Termin-Planer in SkuAuras/Core.lua - jeder Auswertungslauf merkt sich in tNextDurationDeadline den fruehesten Schwellen-Zeitpunkt (expirationTime minus Schwelle) aller aktiven Dauer-Bedingungen (kleiner-Operator); der Frame-Treiber vergleicht pro Frame eine Zahl und feuert dann EINEN synthetischen DURATION_DEADLINE-Lauf. Ersetzt die sekuendliche Naeherungs-Neupruefung der Waffenverzauberungen. (2) UNIT_AURA stoesst bei echter Mengen-Aenderung der Effekte (dazu/weg, nicht bei Stapel- oder Dauer-Updates) eine Auswertung an - Namens-Diff gegen einen Schnappschuss, entprellt gegen Kampflog-Laeufe im selben Frame und gegen Zielwechsel. (3) Die Wort-Ausgaben nutzen den vorhandenen, aber nie angeschlossenen aInstant-Pfad von OutputString (Einfuegen vorne statt hinten); ein Frame-Cursor haelt mehrteilige Ausgaben in Sprechreihenfolge. Auren: Auswertung pro Kampfereignis deutlich verbilligt Einfach: Im Schlachtzug wertet Sku Auren hunderte Male pro Sekunde aus. Mehrere versteckte Kostentreiber sind raus: Bedingungen wurden doppelt geprueft, Restdauern bei jedem Ereignis neu vom Client erfragt, und fuer jedes Ereignis wurde die komplette Gruppe per Einzelabfrage durchsucht. Nebenbei zwei stille Fehler behoben: Eine Aura ohne "Zauber auf Abklingzeit"-Bedingung konnte den Abklingzeit-Namen einer ANDEREN Aura ansagen, und Gegenstands-Abklingzeiten wurden bei jeder Taschenaenderung neu gestempelt. /skucheck kennt dafuer jetzt die Domaene "auras" und prueft, dass die Auswertung keine Globals mehr schreibt. Technisch: Einmal auswerten statt doppelt (der einwertige Zweig der Attributschleife lief versehentlich zweimal; dazu zwei geleakte Globals, tSpellNameOnCdValue injizierte veraltete Werte quer ueber Auren). Restdauern kommen aus einer expirationTime-Erweiterung des Tier-2-Listencaches statt aus UnitAura-Neuscans (/skuauracache verify prueft jetzt auch die exp-Werte, /skuauracache off schaltet beides ab). Gruppen-GUIDs loesen ueber eine bei Roster-Ereignissen invalidierte Karte auf statt ueber raid1..40-Schleifen pro Ereignis (Ergebnis-Reihenfolge und das historische raid1..25-Fenster des RoleCheckers bleiben exakt erhalten). targetUnitDistance und targetTargetUnitId sind lazy, LogRecorder macht einen Settings-Zugriff statt vier, und der UNIT_INVENTORY_CHANGED-Wachausdruck prueft die echte itemID statt eines nil-Globals. Installer: eine Taste sammelt alle Logdateien fuer eine Fehlermeldung Einfach: Der Installer hat auf seinem Startbildschirm eine neue Taste "Alle Protokolle sammeln". Sie legt EINE ZIP-Datei im Downloads-Ordner an, die alles enthaelt, was zur Fehlersuche gebraucht wird - und zwar fuer ALLE gefundenen Spielversionen auf einmal, nicht nur fuer eine: Skus Debug- und Fehlerprotokoll, die Aufzeichnungen von BugGrabber/BugSack und WVDebug, die Protokolle des Spiels selbst samt seiner Lua-Fehler, die CVar-Datei Config.wtf, eine Liste aller installierten Addons mit Version, das Protokoll des Anmelde-Tools und das des Installers. Bisher musste man diese Dateien einzeln aus drei verschiedenen Verzeichnisbaeumen zusammensuchen, und wer eine davon vergass, bekam eine Rueckfrage statt einer Antwort. Die Datei heisst Sku-Logs-.zip, der Installer nennt den vollstaendigen Pfad und oeffnet den Ordner mit der bereits ausgewaehlten Datei, so dass sie sich direkt an eine Fehlermeldung anhaengen laesst. Eine typische Sammlung sind rund 7 MB. Technisch: Neue Datei LogCollector.cs im Installer, angestossen von einer vierten Taste in UpdatePromptForm (Beschriftung und Vorlesetext in allen drei Sprachen). Gesammelt wird pro Client in einen eigenen Unterordner: SavedVariables aus der Konto- UND der Charakterebene (Sku legt beides an) einschliesslich der .bak-Zweitkopien - die sind der Stand der VORIGEN Sitzung und damit oft die einzige noch vorhandene Fassung des Debug-Rings, ueber den berichtet wird -, dazu Logs, Errors, Config.wtf, Sku.toc, .build.info und eine Addon-Liste mit TOC-Versionen und Symlink-Markierung. Dazu kommen system-info.txt (Betriebssystem, Sprache, ein Block je Client und eine Liste dessen, was NICHT mitkam und warum - eine Auslassung soll als Auslassung lesbar sein und nicht als Abwesenheit) sowie das Installerprotokoll, das dafuer erst aus Loggers Speicherpuffer auf die Platte gezwungen wird. Der Ordner Errors ist bewusst von der 30-Tage-Altersgrenze ausgenommen - dort steht nur etwas, wenn wirklich etwas kaputt ging, und der erste Testlauf lieferte sonst null von 21 vorhandenen Absturzberichten - und stattdessen auf die 25 neuesten begrenzt. Der Installer traegt damit die Version 4.2. Anmelde-Tool: das Protokoll ueberlebt jetzt einen Neustart des Tools Einfach: Das Anmelde-Tool loeschte sein Protokoll bei JEDEM Start. Wer also auf einen Fehler stiess, das Tool schloss und es noch einmal oeffnete, bevor er die Logdateien einsammelte, hatte genau den Nachweis geloescht, um den es ging - und das ist der haeufigste Ablauf einer Fehlermeldung ueberhaupt. Die letzten fuenf Sitzungen bleiben jetzt als log-1.txt bis log-5.txt neben dem laufenden log.txt liegen, und die neue Sammeltaste des Installers nimmt sie automatisch mit. Technisch: log.ahk schreibt jetzt auf einen ABSOLUTEN, aus dem Skriptort abgeleiteten Pfad statt auf den relativen Namen "log.txt", der gegen das Arbeitsverzeichnis des Prozesses aufgeloest wird - START.ahk setzt das zwar passend, aber es ist prozessweiter Zustand, den jede spaetere Stelle aendern kann, und ein Protokoll an einem Ort, an dem niemand nachsieht, ist so gut wie keines. ClearLogFile() rotiert jetzt, statt zu loeschen. Verpackung und .gitignore schliessen log-*.txt genauso aus wie log.txt; die Protokolle einer bestehenden Installation werden bei einem Upgrade nicht angetastet. Anmelde-Tool: der Anmeldebildschirm meldete sich als Charakterauswahl Einfach: Wenn das Spiel beim Start keine Verbindung zum Server bekommt, landet man nicht in der Charakterauswahl, sondern auf dem Anmeldebildschirm mit Accountname, Passwort und Login-Knopf. Das Tool fuehrte dort ins Hauptmenue, dessen erster Eintrag "Charakter auswaehlen" heisst - ausgerechnet der Bildschirm, der beweist, dass es gerade gar keine Charakterliste gibt, sagte sich also als Charakterauswahl an. Wer ihn nicht sehen kann, hoerte nichts, was ihn von der echten Charakterauswahl unterschieden haette. Das Tool sagt jetzt beim Ankommen einmal: nicht angemeldet, entweder besteht keine Verbindung zum Server oder Accountname und Passwort muessen im Spiel noch eingegeben werden. Und es merkt jetzt auch, wenn der Bildschirm gewechselt wird: wer sich von Hand anmeldet, bekommt die Charakterliste sofort gebaut, statt das Tool stumm auf dem alten Menue stehen zu lassen. Technisch: "Keine Verbindung" ist KEIN eigener Bildschirm - am laufenden 2.5.6-Client geprueft, er ist pixel- und OCR-identisch mit einem normalen Anmeldebildschirm (gleiche Widget-Proben, checks.login = true, kein Popup). Es gibt also nichts zu markieren; angesagt wird nur, was auf diesem Bildschirm immer stimmt: dieser Client ist nicht angemeldet. Das Menue ist jetzt ein eigener Baum statt des Hauptmenues, und InitLogin lief bisher nur beim MODUSwechsel, weshalb ein Bildschirmwechsel unbemerkt blieb; der Waechter loest jetzt eine volle Neuinitialisierung aus, sobald der Anmeldebildschirm betreten oder verlassen wird. Anmelde-Tool: der Anmeldebildschirm ist jetzt bedienbar Einfach: Das Menue auf dem Anmeldebildschirm fuehrt jetzt mit den Bedienelementen des Bildschirms selbst: Accountname, Passwort, Anmelden, Accountnamen speichern - und danach unveraendert Stimme, Sprache, Spieltyp, Region und Version, damit die Einstellungen auch dann erreichbar bleiben, wenn die Anmeldung scheitert. Das Tool speichert dabei NICHTS und tippt nichts: es setzt nur den Cursor des Spiels in das Feld und gibt die Tastatur an den Client weiter, getippt wird von Hand. Einen Autologin gibt es nicht und wird es nicht geben. Der Accountname wird vorgelesen, leer als "leer"; das Passwort wird NIE vorgelesen. Solange die Tastatur an einem Feld haengt, gehen die Pfeiltasten ans Spiel, damit man einen Tippfehler auch erreichen kann; Enter beendet die Eingabe, Escape verlaesst sie, und keins von beiden wird ans Spiel weitergereicht - Anmelden ist ein eigener Eintrag, damit nichts versehentlich abgeschickt wird. Meist ist Battle.net schliessen und neu oeffnen der schnellere Weg; der manuelle Weg ist fuer die Faelle da, in denen man ihn will. Technisch: Vier neue Widgets in data.ini ([Classic] und [BurningCrusade]): LoginAccountField 10000,403, LoginPasswordField 10000,478, LoginSubmitButton 10000,531 und LoginSaveAccountCheckbox 26,662 - am laufenden Client bei 2880x1800 vermessen und in den 768er UI-Raum umgerechnet, also aufloesungsunabhaengig, und gegen bereits vorhandene Eintraege gegengeprueft ("Account erstellen" gemessen 549 gegen die gespeicherten 550). Der Feldinhalt wird per OCR NUR des Feldes gelesen, damit kein Label von woanders als Inhalt durchgeht. "Anmelden" verfolgt den Versuch: einbuttonige Fortschrittsdialoge werden vorgelesen und NICHT geklickt, weil ihr einziger Knopf Abbrechen ist und die laufende Anmeldung trennt - dieselbe Falle wie beim Realmbeitritt; zweibuttonige Dialoge werden vorgelesen und beantwortet. Wo die Widgets fehlen (Cata, Retail), sagen die Eintraege das und tun nichts. Anmelde-Tool: die Charakterliste auf Realms mit zehn oder mehr Charakteren Einfach: Die Charakterleiste zeigt genau neun Charaktere gleichzeitig. Ab dem zehnten blaettert die Liste, und damit ging alles auf einmal schief: Charaktere fehlten, die Nummerierung passte nicht zur tatsaechlichen Liste, und der Weg zurueck an den Anfang der Liste klappte nicht zuverlaessig. Alle drei haben dieselbe Ursache. Das Tool laeuft die Liste mit den Pfeiltasten ab und beobachtet dabei, wie sich die Auswahlleiste bewegt - sobald die Liste blaettert, bewegt sie sich aber nicht mehr, und "nichts hat sich geaendert" wurde als "hier endet die Liste" gelesen. Ein vom Spiel verschluckter Tastendruck sieht genau gleich aus, und der hat die Listen abgeschnitten. Mit neun Charakteren oder weniger blaettert die Liste nie, deshalb war davon nie etwas zu sehen. Das Tool fragt jetzt zweimal nach, bevor es ein Listenende glaubt, und zieht den grossen Charakternamen unter dem Charaktermodell zur Entscheidung heran - der zeigt den ausgewaehlten Charakter, egal wie weit die Liste gescrollt ist. Ausserdem sagt es alle zehn Charaktere den Stand an, weil eine lange Liste sonst eine halbe Minute Stille ist, und das Menue bleibt waehrend des Neuaufbaus bedienbar statt tot. NICHT GETESTET im Spiel: Hier gibt es keinen Realm mit mehr als neun Charakteren. Sollte die Liste weiterhin falsch sein, benennt das Log des Tools jetzt genau die Entscheidung, die schiefging. Technisch: Gegen den Interface-Quelltext des Clients selbst geprueft. Blizzard_GlueXML_TBC.toc laedt Vanilla\CharacterSelectConstants.lua mit CHARACTER_SELECT_MAX_CHARACTERS = 9, und CharacterSelect_OnShow setzt MAX_CHARACTERS_DISPLAYED darauf. Jede Abbruch- bedingung im Walk, die auf EINER Beobachtung beruhte, braucht jetzt zwei mit laengerer Wartezeit dazwischen und drueckt erst dann erneut, wenn ein Blick bewiesen hat, dass sich nichts bewegt hat - ein zweiter Druck auf einen bereits angekommenen Schritt ueberspringt spurlos einen Charakter. Die Umbruch-Erkennung verlangt jetzt exakt Slot 1, denn CharacterSelectScrollDown_OnClick setzt nach dem letzten Charakter CHARACTER_LIST_OFFSET = 0 und dann SelectCharacter(1); ausserdem wird das Zurueckscrollen abgewartet, bevor bestaetigt wird. Der Notbehelf, der nur den sichtbaren Ausschnitt liest, faehrt jetzt zuerst nach oben, denn UpdateCharacterSelection setzt den Offset auf selectedIndex - MAX_CHARACTERS_DISPLAYED, sobald der zuletzt gespielte Charakter unter der Kante sitzt - die neun sichtbaren Zeilen waren dann Charakter 6 bis 14, angesagt als 1 bis 9. Die Pixelproben der Auswahlleiste wurden nach links verschoben: ab zehn Charakteren verbreitert UpdateCharacterList die Leiste von 260 auf 280 und blendet eine Scrollbar ein, deren Hintergrund schwarz genau auf dem Streifen liegt, den die Auswahlleiste freigibt. Das Menue wird jetzt wie die Realmliste losgeloest aufgebaut und in einer einzigen Zuweisung veroeffentlicht. Hardcore-Realms: Sku baut seine Wegpunktdaten jetzt fertig, statt still stehenzubleiben Einfach: Auf Hardcore-Realms raeumt der Spielclient Addons deutlich weniger Rechenzeit pro Bild ein als auf normalen Realms. Sku baut direkt nach dem Anmelden seine Wegpunkt- und Routendaten auf, und genau dieser Aufbau lief dort in diese Grenze: Der Client brach den laufenden Vorgang einfach ab, und Sku bekam davon nichts mit. Ergebnis: Jede Wegpunktliste antwortete die ganze Sitzung lang nur mit "Wegpunkte werden noch geladen" - ohne Fehlermeldung, ohne Sprachausgabe, ohne Logeintrag, und auch ein Neuladen der Oberflaeche half nicht. Sku merkt jetzt, wenn der Client bremst, verkleinert seine Arbeitspakete und macht weiter, statt liegen zu bleiben; wird ein Paket doch abgeschossen, startet der Aufbau von selbst neu. Der Preis dafuer: Auf solchen Realms dauert es nach dem Anmelden ein paar Sekunden laenger, bis Routen und Wegpunkte vollstaendig da sind. Alles andere in Sku ist sofort benutzbar, und die Wegpunktlisten sagen jetzt an, wie weit der Aufbau ist (naechster Eintrag). Normale Realms sind unveraendert. Technisch: Der Client meldet den Abbruch als LUA_WARNING "insecure scripts exceeded execution limit for addon Sku" oder als "script ran too long" mitten im laufenden Coroutine-Abschnitt. Auf dem Hardcore-Realm kam das bei jedem einzelnen Anmelden (52/25/25 Meldungen pro Login), in acht aufgezeichneten Sitzungen auf normalen Era- und Anniversary-Realms kein einziges Mal - bei identischer Arbeit (1936 ms auf Era gegenueber 1955 ms auf Hardcore fuer denselben Aufbau). Sku:BuildFrameBudgetMs ist jetzt adaptiv: Jede solche Meldung halbiert die Frame-Obergrenze (150 -> 75 -> 37,5 -> 20 ms), wovon der gesamte Aufbau nach dem Anmelden profitiert, nicht nur der Wegpunkt-Cache. Getaktet wird der Cache-Aufbau nicht mehr von einer sich selbst neu setzenden C_Timer-Kette - genau dieses Neusetzen fiel dem Abbruch zum Opfer, die Coroutine blieb danach fuer immer angehalten und niemand weckte sie wieder - sondern von einem OnUpdate-Treiber, den der Client selbst in jedem Bild aufruft; ein abgeschossenes Paket kostet damit ein Bild statt den ganzen Aufbau. Stirbt die Coroutine trotzdem, wird bis zu dreimal neu aufgebaut, und der Build-Step legt seine Anforderung zurueck, statt sie in einem pcall zu verlieren. Navigation: eine Routenliste konnte leer bleiben, ohne zu sagen warum Einfach: Ein Tester auf einem Hardcore-Realm meldete, dass die Routenliste auf Shift-F10 nur "Liste leer" sagte, obwohl es dort Routen gibt. Dahinter steckten zwei verschiedene Wege, auf denen eine Liste leer werden konnte, ohne dass irgendetwas darauf hinwies. Erstens: Seit Sku seinen Wegpunktaufbau auf Hardcore-Realms notfalls neu startet (siehe oben), koennen die Wegpunkte waehrend eines geoeffneten Menues ausgetauscht werden. Eine Liste, die noch aus dem alten Aufbau stammte, zeigte dann auf einen Wegpunkt, den es nicht mehr gab. Das warf einen Fehler mitten im Aufbau der Untereintraege, und weil dieser Fehler abgefangen wurde, blieb einfach eine leere Ebene stehen: keine Eintraege, kein Hinweis, keine Fehlermeldung, nichts zu hoeren. Zweitens: Fehlten die Routendaten selbst, meldete Sku trotzdem "fertig geladen", und dann waren alle Routenlisten leer - auch das ohne jeden Hinweis. Beides faellt jetzt auf: Die Liste antwortet ordentlich, statt stumm zu bleiben, und fehlende Routendaten werden angesagt wie jeder andere Datenbankfehler. Technisch: Drei Stellen, alle nach demselben Muster - ein Fehlschlag darf nicht unsichtbar sein. 1. SkuNav:GetAllMetaTargetsFromWp5 griff ohne Pruefung auf den Startwegpunkt zu (.worldX). Nach einem Neuaufbau des Wegpunkt-Cache - neu in v43.0, weil der Aufbau sich auf Hardcore-Realms selbst neu startet und weil CleanupWaypoints Wegpunkte ohne Verbindungen loescht - kann dieser Name weg sein. Die Funktion liefert jetzt eine leere Antwort und schreibt eine Logzeile mit der Cache-Generation. 2. SkuOptions:VocalizeCurrentMenuName und der Pfadlaeufer rufen BuildChildren in einem pcall auf, damit ein defekter Untermenue-Aufbau nie die Ansage des Eintragsnamens verschluckt. Das bleibt so - aber der Fehler wird jetzt mit Knotennamen protokolliert und der Knoten markiert (buildChildrenFailed). Ohne das war eine Ebene mit null Eintraegen von einer Ebene, die wirklich leer ist, nicht zu unterscheiden. 3. Sku:EnsureData uebersprang ein Builder-Global, das keine Funktion ist, kommentarlos und meldete den Datensatz danach trotzdem als bereit. Genau das ist die schlimmste Form: Jede Pruefung im Rest des Codes fragt "ist es bereit", nicht "ist es da". Fuer die Routen endet das mit leeren Verbindungsdaten, geloeschten Routenwegpunkten und Menues, die seelenruhig "Liste leer" sagen. Jeder fehlende Builder wird jetzt einzeln protokolliert; fehlen ALLE, gilt der Datensatz als fehlgeschlagen und wird angesagt. Dazu kommt eine Logzeile in SkuNav:GetAllLinkedWPsInRangeToCoords: Wenn Sku das aktuelle Gebiet keinem Kontinent zuordnen kann (Hoehlen, die Tiefenbahn, nicht kartierte Unterzonen), bricht diese Abfrage leer ab - und die Liste sagte dann "Liste leer", was sich wie eine Aussage ueber die Daten anhoert und keine ist. /skuzoneprobe weist denselben Fall vollstaendig aus. Anmelden: die Wegpunktdaten der Routen stehen deutlich frueher bereit Einfach: Nach dem Anmelden baut Sku alle Wegpunkte und ihre Verbindungen neu auf; bis das fertig ist, antworten die Wegpunktlisten mit "Wegpunkte werden noch geladen". Mehr als die Haelfte dieser Wartezeit ging fuer die Verbindungen drauf, und dieselben Daten wurden dabei viermal durchlaufen. Jetzt ist es ein Durchlauf, und er beginnt mit dem Kontinent, auf dem ihr gerade steht: Der ist als erstes fertig, und ab diesem Moment sind eure Listen benutzbar, waehrend der Rest der Welt noch gebaut wird. Wer dabei auf dem Wartehinweis steht, bekommt den ersten Eintrag automatisch vorgelesen, ohne eine Taste zu druecken. Auf demselben Rechner gemessen: Der Verbindungsteil kostet noch etwa die Haelfte, und die Listen des eigenen Kontinents sind rund 0,7 Sekunden frueher da. An den Routen selbst aendert sich nichts - dieselben Wegpunkte, dieselben Verbindungen, nur frueher. Dazu braucht die Wegpunktverwaltung jetzt rund 22 MB weniger Arbeitsspeicher, weil jede Verbindung nicht mehr doppelt gespeichert wird - auf schwachen Rechnern ist das der spuerbarere Teil. Und ein weiteres Stueck Wartezeit faellt ganz weg: Sku liefert zwei grosse Routendateien mit, und von der zweiten braucht die TBC-Fassung nur die Verbindungen. Deren Wegpunkte wurden bisher trotzdem bei jedem Anmelden aufgebaut und einen Augenblick spaeter ungelesen wieder weggeworfen; sie werden jetzt gar nicht erst gebaut. Das spart rund eine viertel Sekunde und rund 21 MB Spitzenspeicher pro Anmeldung - auf Era-Realms, wo die ganze Datei ungenutzt ist, rund 0,4 Sekunden. Beide Dateien werden weiter vollstaendig ausgeliefert: Beim spaeteren Wechsel auf Wrath of the Lich King sind genau diese Daten die richtigen, dann wird andersherum ausgewaehlt. Technisch: Der Verbindungsteil des Wegpunkt-Cache-Aufbaus lief als VIER volle Durchlaeufe ueber ~197.000 gerichtete Kanten: pruefen und symmetrisieren (CheckAndUpdateProfileLinkData), byId/byName materialisieren, die ganze Tabelle aus dem Cache zurueckrechnen (SaveLinkDataToProfile) und ein Schlussdurchlauf ueber alle ~145.000 Cache-Eintraege (CleanupWaypoints). Jetzt ist es ein Durchlauf: Das Pruefen laeuft mit, die Gegenrichtung jeder Kante wird direkt in den Zieleintrag geschrieben - deshalb ist die Reihenfolge der Kontinente egal -, und das Zurueckrechnen entfaellt, weil es die Tabelle schrieb, die ohnehin schon dasteht. Der einzige Fall, in dem es doch etwas aendern koennte (ein Endpunkt, dessen Name im Cache zu einem anderen Eintrag gehoert), wird gezaehlt und loest den alten Weg aus; in den ausgelieferten Routendaten kommt er nicht vor. Der Schlussdurchlauf bekommt vom Custom-Pass die Liste der ueberhaupt loeschbaren Eintraege, nach Kontinent sortiert, und laeuft pro Kontinent, sobald dieser fertig ist. Nebenbei behoben: Der alte Pruefdurchlauf fuegte waehrend pairs() neue SCHLUESSEL in genau die Tabelle ein, ueber die er lief - in Lua undefiniertes Verhalten; die Gegenkanten werden jetzt gesammelt und danach eingetragen. Ausserdem war die im Juli eingebaute Zweiteilung "eigener Kontinent zuerst" beim Anmelden nie aktiv: Sie ermittelt die Zone ueber GetMinimapZoneText, und die ist beim Start des Aufbaus noch leer - der Kontinent wird jetzt vor dem Verbindungsteil erneut ermittelt. Belegt durch einen Nachbau beider Varianten ueber die echten Routendaten (dev/rework-docs/simulate_link_build.py: gleicher Cache, gleiche Verbindungstabelle, fuer jeden Kontinent) und im Spiel durch /skucheck wp, das jetzt auch prueft, dass jede Verbindung ihre Gegenrichtung hat. Technisch, zweiter Teil: Jede Verbindung lag doppelt im Speicher - einmal unter der Nummer des Zielwegpunkts (byId) und einmal unter seinem Namen (byName). byName ist entfallen, alle 14 Fundstellen arbeiten jetzt mit byId; neu ist dafuer WaypointCacheGetIdForIndex, das Gegenstueck zu WaypointCacheGetIdForName. Der Schreibweg in die Verbindungstabelle wurde dadurch sogar billiger: Er hat bisher jeden Zielnamen wieder in eine Id zurueckuebersetzt, jetzt hat er den Datensatz schon. Gemessen: rund 70.000 Tabellen und 224.000 Zeichenketten weniger, 22 MB weniger im Speicherbericht (/skucheck mem), und der Verbindungsteil des Aufbaus wurde noch einmal etwa 40 ms schneller. Warum das doppelt war: eine nie zu Ende gefuehrte Umstellung - schon in Sku 32.31 steht auskommentiert der Aufruf, der die byName-Tabelle direkt in die gespeicherte Verbindungstabelle schreiben sollte; byId kam spaeter als schneller Weg fuer die Routensuche dazu, und beide blieben. Drei latente Fehler sind mitgegangen: eine Schleife beim Wegpunktloeschen, die nur den geloeschten Wegpunkt gegen sich selbst aufraeumte, Ids die aus ".areaid" statt ".areaId" gebaut wurden (also immer mit Gebiet 1) und ein Zugriff auf Links[nil] bei temporaeren Wegpunkten. Technisch, dritter Teil: Die beiden Routendateien waren je EIN Builder, der die ganze Datei aufbaute. Gemessen im Spiel: 375 ms fuer die WotLK-Datei und 355 ms fuer die Basisdatei, jedes Mal. Auf TBC nutzt die Navigation die Wegpunkte der Basisdatei und von der WotLK-Datei nur die Verbindungen (die Vereinigung beider Graphen, seit Juli) - LoadDefaultMapData setzte die WotLK-Wegpunkte, -Level und -Sequenznummern direkt nach dem Verknuepfen wieder auf nil. Das sind 71% der Bytes dieser Datei, gebaut und ungelesen weggeworfen. Die Dateien werden jetzt pro ABSCHNITT verpackt (dev/rework-docs/_wrap_deferred.py, Modus "sections"): ein Builder je Top-Level-Abschnitt von routedata.global, jeder mit einem byte-genauen Ausschnitt der Originaldaten - das Werkzeug prueft, dass die Ausschnitte wieder exakt die Ursprungsdatei ergeben, es wird nichts neu serialisiert. SkuDeferredData.lua waehlt die Builder nach Spielversion (TBC: alle Abschnitte der Basisdatei plus die WotLK-Verbindungen; Era: nur die Basisdatei) und setzt die uebersprungenen Builder-Globals auf nil, sonst haengen ihre Quelltext-Konstanten weiter im Speicher. Neu: /skucheck routes. Die Pruefung ist absichtlich so gebaut, dass ein falsch gewaehlter Abschnitt laut wird statt still den halben Graphen zu kosten: Nach EnsureData darf kein einziges SkuDBBuildRoute*-Global mehr existieren - ein ueberlebendes bedeutet einen Abschnitt, den die Auswahl nicht kennt -, die Tabellen, die die Navigation liest, muessen da und nicht leer sein, und pro Spielversion muss genau die richtige Haelfte fehlen. Wegpunktlisten sagen jetzt an, wie weit das Laden fortgeschritten ist Einfach: Die Meldung "Wegpunkte werden noch geladen" war fuer ein, zwei Sekunden Wartezeit gedacht. Wenn der Client Sku ausbremst (siehe voriger Eintrag), kann sie aber zehn Sekunden und laenger stehen bleiben, und dann ist sie von einem Haenger nicht mehr zu unterscheiden. Sie nennt jetzt einen Prozentwert, also zum Beispiel "Wegpunkte werden noch geladen, 47%". Die Zahl bewegt sich von Anfang an: Die ersten Schritte sind die Datenbankteile, auf die der Aufbau ueberhaupt erst wartet (0, 20, 40 Prozent), danach zaehlt der Aufbau selbst bis 99 hoch. Jeder Tastendruck auf dem Eintrag sagt den aktuellen Stand an, und sobald alles da ist, wird wie bisher automatisch der erste echte Wegpunkt angesagt. Technisch: Der Massstab ist die Arbeitszeit eines VOLLSTAENDIGEN Aufbaus, die jeder erfolgreiche Lauf in den globalen SkuNav-Einstellungen hinterlegt (wpcTotalWorkMs). Gemessen wird Arbeit, nicht Wanduhrzeit: Die Arbeit ist stabil, die Wanduhrzeit schwankt jetzt mit der Budget-Drosselung. Damit stimmt der Prozentwert auf jedem Rechner; nur der allererste Aufbau nach einer Neuinstallation nutzt den Vorgabewert. Kosten pro Bild: ein Ganzzahlvergleich - nur ein GEAENDERTER Prozentwert baut den Text neu, und das auch nur fuer einen Eintrag, auf dem der Fokus gerade steht. Der Eintrag traegt dafuer eine Markierung, weil sein Name kein fester Text mehr ist: Die beiden Stellen, die ihn bisher am Namen erkannten - die Nicht-auswaehlbar-Sperre und die automatische Aktualisierung am Ende des Aufbaus - pruefen jetzt die Markierung. Shift-F9 bis Shift-F12: eigene Tastenbelegungen, und vier Schnellzugriffe zurueck Einfach: Vier Sku-Aktionen - die beiden Navigations-Schnelllisten (Shift-F9 und Shift-F10), das Aktionsleisten-Menue (Shift-F11) und das Abbrechen der Routennavigation (Shift-F12) - haengten direkt auf den Tasten der Audio-Menue-Schnellzugriffe 1 bis 4. Das hatte zwei Folgen. Diese vier Schnellzugriffe waren tot: Ihre Festlegen-Tasten (Strg-Shift-F9 bis Strg-Shift-F12) speicherten weiterhin einen Menuepfad und bestaetigten ihn auch laut, aber keine Taste konnte ihn je wieder aufrufen. Und die vier Aktionen liessen sich nur auf eine andere Taste legen, indem man einen Eintrag namens "audio menue schnell zugriff 1" bis "4" neu belegte - dort sucht niemand nach "Navigation abbrechen". Jede Aktion hat jetzt ihren eigenen Eintrag in der Tastenbelegung, unter ihrem eigenen Namen, weiterhin auf Shift-F9 bis Shift-F12. Die Schnellzugriffe 1 bis 4 sind wieder frei und unbelegt, genau wie die Plaetze 5 bis 10. Bestehende Einstellungen werden beim ersten Anmelden uebernommen: Welche Taste auch immer heute auf Schnellzugriff 1 bis 4 liegt, sie fuehrt weiterhin genau dieselbe Aktion aus - sie wandert nur auf den neuen Eintrag, fuer die Finger aendert sich nichts. Ein Platz, den du absichtlich geleert hattest, bleibt leer. Technisch: Der OnClick in SkuZOptions/Core.lua fing SKU_KEY_MENUQUICK1..4 ab und kehrte zurueck, bevor die allgemeine Schnellauswahl-Schleife weiter unten im selben Handler sie sehen konnte. Die drei verschobenen Aktionen heissen jetzt SKU_KEY_NAVWAYPOINTSQUICK, SKU_KEY_NAVROUTEDESTINATIONSQUICK und SKU_KEY_ACTIONBARSOPEN und werden von dem Modul verteilt, dem sie gehoeren; die beiden Navigationslisten stehen in der Gruppe "Navigation und Wegpunkte". Eine einmalige Migration in SkuKeyBindsUpdate verschiebt key und key2 vom alten Platz auf die neue Konstante; erkannt wird sie am Fehlen der neuen Konstante im Profil, laeuft also genau einmal und vor dem Setzen der Vorgaben. Gespeicherte Schnellauswahl-Pfade bleiben erhalten - eine Taste auf Platz 1 bis 4 stellt die alte Abkuerzung wieder her. Neue Stolperdrahtpruefung: /skucheck keys meldet jede Taste, die zwei Sku-Belegungen gleichzeitig haelt (ausgenommen die transienten Override-Tasten, die sie sich per Entwurf teilen). Navigation abbrechen lief ueber zwei verschiedene Tasten Einfach: Es gab zwei Wege, das Folgen einer Route oder eines Wegpunkts zu beenden, und sie verhielten sich unterschiedlich. Die richtig benannte Belegung "route oder wegpunkt folgen beenden" wurde ganz ohne Taste ausgeliefert, und wenn man ihr eine gab, sagte sie "folgen beendet" - dieselben Worte wie beim automatischen Ankommen, man konnte beides also nicht unterscheiden - und sie sagte ueberhaupt nichts, wenn man eine Route statt eines einzelnen Wegpunkts abbrach. Der andere Weg war das fest verdrahtete Shift-F12, das "Navigation abgebrochen" sagte, aber nur als Schnellzugriff 4 existierte. Beides ist jetzt eine Taste: "route oder wegpunkt folgen beenden", standardmaessig auf Shift-F12 und frei belegbar, mit dem Bestaetigungston und dem eindeutigen "Navigation abgebrochen". Sie bleibt vollkommen still, wenn es nichts abzubrechen gab, und funktioniert weiterhin in Bewegung und im Kampf. Technisch: Der SkuNav-OnClick-Zweig fuer SKU_KEY_STOPROUTEORWAYPOINT ruft jetzt SkuNav:CancelNavigationSilent() auf und spricht bzw. spielt Sound 835 nur bei einem true-Rueckgabewert. Damit faellt der alte ungeschuetzte Pfad weg, der SKU_NAVIGATION_STOPPED und den Ton auch dann ausloeste, wenn nichts lief, und dessen Ansage aus EndFollowingWpOrRt kam und an einen ausgewaehlten Wegpunkt gebunden war. EndFollowingWpOrRt selbst bleibt unveraendert - seine fuenfzehn anderen Aufrufstellen nutzen es als Abbau vor dem Auswaehlen eines neuen Ziels, wo das Loeschen temporaerer Wegpunkte falsch waere. Navigation: Eine Route liess sich nicht starten, wenn ihre Liste waehrend des Ladens fertig wurde Einfach: Wenn du die Routenliste (Shift-F10) geoeffnet hast, waehrend Sku seine Wegpunktdaten noch aufgebaut hat, hat sich die Liste in dem Moment aktualisiert, in dem diese Daten fertig waren - und ab da hat Enter auf einem Routenpunkt die Navigation nicht mehr gestartet. Stattdessen ist das Menue zurueck auf die Ebene der Einstiegspunkte gesprungen, so als haette die Taste gar nichts getan. Menue schliessen und neu oeffnen hat es behoben, was das Ganze zufaellig wirken liess. Die aktualisierte Liste verhaelt sich jetzt genau wie eine frisch geoeffnete: Enter startet die Navigation. Das gilt genauso fuer die Liste der Wegpunkte in der Naehe (Shift-F9) und fuer jede Wegpunktliste, die sich beim Eintreffen der Daten selbst aktualisiert. Technisch: Die Aktualisierung am Ende des asynchronen Wegpunkt-Cache-Aufbaus hat die Ebene mit einem blossen children = {} plus BuildChildren neu gebaut. Damit faellt weg, was OnPostSelect fuer eine Auswahl-Ebene tut: selectTarget auf der Ebene setzen und auf jedes frisch gebaute Kind kopieren. Ohne das erbt die gesamte Unterebene selectTarget = nil, also landet das Enter des Blatts im generischen Zweig von OnPostSelect - es laeuft kein OnAction (RouteFollowOnAction wurde nie aufgerufen) und der Cursor wird auf self.parent gesetzt, genau der beobachtete Sprung nach oben. Dieser Neuaufbau liegt jetzt an genau einer Stelle, SkuOptions:RebuildNodeChildren, benutzt von OnPostSelect selbst, von der Wegpunkt-Aktualisierung und von der Auffrischung veraenderlicher Listen - letztere im Behalten-Modus, damit eine laufende Auffrischung kein bereits ausgewaehltes Ziel wegwirft. Zwei Stolperdraehte gehoeren zur Korrektur: OnPostSelect protokolliert und zaehlt jedes Enter, das auf einem Blatt ohne selectTarget unterhalb einer Auswahl-Ebene landet, und /skucheck menu baut eine Wegwerf-Auswahl-Ebene neu auf, prueft die Zusicherung und meldet diese Sitzungszaehlung. Auren: Gruppenplaetze wurden als Piepser statt als Wort angesagt Einfach: Sagt eine Aura die Einheit an, die das Ereignis ausgeloest hat, kam bei manchen Gruppenplaetzen nur ein kurzer Piepser statt eines Wortes - der Ton, den Sku spielt, wenn ihm die Aufnahme fuer ein Wort fehlt. Betroffen waren Platz 3 und jeder "Ziel von"-Platz. Diese Angaben werden jetzt in Woerter zerlegt, die das Sprachpaket sicher enthaelt: "party 3", "ziel party 2". Alle anderen Einheiten sagen weiterhin ihren uebersetzten Namen. Technisch: sourceUnitId und destUnitId reichten das rohe Unit-Token als EIN Wort an die Audioausgabe. Die Pakete liefern party0/1/2/4, aber kein party3 und keine einzige partyNtarget-Datei, der Rest fiel also auf den missingAudio-Piepser zurueck (allein party3 zaehlte 129). tUnitIdToSpokenName in SkuAuras/data.lua splittet die Party-Tokens; andere Tokens fallen auf ihren uebersetzten friendlyName aus den Wertelisten und erst dann auf das rohe Token zurueck. Nebenbei behoben: notifyChat druckte die Tabellenreferenz statt der Einheit. Auren: eine Aura mit "einmal" konnte im dichten Kampf mehrfach hintereinander feuern Einfach: Eine Aura, die pro Anwendung nur EINMAL melden soll - typisch "Schattenwort: Schmerz laeuft in einer Sekunde ab" -, konnte im Bosskampf vier Toene in einer Sekunde abgeben. Das passierte, wenn mehrere Spieler denselben Effekt auf dem Ziel hatten oder die Restdauer in einem Durchlauf gar nicht ablesbar war: Sku wertete das faelschlich als "der Effekt ist wieder frisch" und hob die Einmal-Sperre auf. Fehlt die Ablesung, bleibt die Sperre jetzt zu. Eine echte Auffrischung oder eine neue Anwendung hebt sie weiterhin sofort auf. Technisch: Die Reset-Formel der Zaehl-Bedingung armierte used bei jedem Durchlauf neu, in dem die uebrigen Bedingungen hielten und die kleiner-Dauerbedingung false las - und ein Durchlauf OHNE Ablesung (Name nicht in der Liste, kein exp-Eintrag, oder die exp-Karte antwortet mit der gleichnamigen Aura eines anderen Wirkers) erfuellt genau das. tSmallerDurationNoRead in SkuAuras/Core.lua verhindert das Zuruecksetzen ohne Ablesung; der neue Logeintrag "aura gate re-armed" haelt jedes Entsperren fest. Beobachtet wurden vier Feuerungen in 987 ms (DURATION_DEADLINE, dann zweimal UNIT_POWER und SPELL_PERIODIC_DAMAGE). Menue: die Wegpunktliste auf Shift-F9 oeffnete sich auf grossen Karten erst beim zweiten Versuch Einfach: Auf Karten mit sehr vielen Wegpunkten blieb Shift-F9 auf dem obersten Eintrag stehen, statt die Liste zu oeffnen; ein weiterer Pfeildruck oeffnete sie dann doch. Grund war Arbeit, die dreimal statt einmal lief: Der Sprung baute dieselbe Liste - auf manchen Karten rund 1900 Eintraege - drei Mal in einem einzigen Frame, und der Spielclient brach das mit seiner Skript-Zeitgrenze ab. Der Abbruch passiert lautlos, deshalb schien einfach nichts zu geschehen. Dazu kam, dass jeder Tastendruck auf einem Eintrag dessen Unterliste erneut aufbaute und die Eintraege dabei verdoppelte. Beides ist weg, die Liste wird einmal gebaut. Shift-F10 war nie betroffen, weil diese Liste auf zehn Ziele begrenzt ist. Technisch: SlashFunc baute die Kinder dreimal: vor dem Namensvergleich, im OnSelect der Schleife und noch einmal im Nachlauf. Der Vergleich entscheidet jetzt VOR dem Bau, und der Nachlauf ueberspringt seine Wiederauswahl, wenn die Schleife denselben Knoten bereits gewaehlt hat (actionOnEnter-Knoten ausgenommen, dort unterscheiden sich die beiden Aufrufe wirklich). VocalizeCurrentMenuName baut nur noch, wenn es nichts zu zaehlen gibt - es braucht die Kinder allein fuer die ";plus"-Markierung, und die meisten Builder haengen ueber InjectMenuItems an, statt zu ersetzen (gemessen 1859 -> 3718 -> 5577 Eintraege beim Durchpfeilen). Nachtrag aus dem Test: Fenster-Ebenen unter "Lokal" (Dialog, Haendler, Quest, Flugmeister) bauen ihre Kinder lazy und tragen kein dynamic-Flag; mit uebersprungenem Vorbau sahen sie aus wie kinderlose Blaetter, und der Blattzweig ruft CloseMenu - Schliessen klickt aber jeden Fensterknopf aus interactFramesList, der Sprung zum Flugmeister schloss dessen Fenster also sofort wieder. Gebaut wird deshalb weiter, wenn die Liste leer ist, es sei denn der Knoten ist dynamic. Zwei Stolperdraehte in /skucheck menu zaehlen beide Faelle mit. Taxiflug: Die Ansagen lassen sich abschalten - und sie nennen nicht mehr den Startpunkt oder das Ziel des Fluges Einfach: Waehrend eines Taxiflugs sagt Sku "Naechster Flugpunkt X" und rund 800 Meter vorher "Vorzeitige Landung moeglich bei X", damit man mit der Tastenbelegung frueher aussteigen kann. Wer viel fliegt, empfindet das als Geschwaetz, deshalb gibt es jetzt einen Schalter: Einstellungen > Allgemein > "Flugpunkte zum Landen ansagen". Er steht auf Ja und schaltet ausschliesslich die SPRACHAUSGABE ab - der Flug wird weiter verfolgt, und die Taste fuer die vorzeitige Landung funktioniert unveraendert und bestaetigt weiterhin laut, was sie getan hat, denn das ist die Antwort auf einen gerade gedrueckten Tastendruck. Zweitens gab es Meldungen, Sku habe den Flugpunkt, an dem der Flug BEGONNEN hat, oder den Zielflugpunkt als Ort fuer eine vorzeitige Landung genannt. Beides ist keine vorzeitige Landung: das eine ist der Ort, an dem man ohnehin schon war, das andere ist schlicht das Ankommen. Beides ist jetzt ausgeschlossen. Drittens haelt Sku den Mund, sobald die vorzeitige Landung wirklich angefordert wurde. Bisher nannte es den Flugpunkt NACH dem, an dem man abgesetzt wurde - zehn Sekunden vor der Landung in Ratschet kam noch "Naechster Flugpunkt Astranaar", was klingt, als ginge der Flug weiter. Technisch: Die Ansage hatte einen blinden Fleck, den Rueckfall auf den naechstgelegenen Flugpunkt. Die Route wird beim Start von der Flugkarte erfasst (der einzige Moment, in dem die Routen-Schnittstelle ueberhaupt antwortet), und alle Ansagen haengen an dieser Route. Fehlt sie, faellt der Code auf "der naechstgelegene benutzbare Flugpunkt" zurueck - und der weiss nichts vom Flug: Kurz nach dem Start ist das eine Weile lang genau der Startpunkt, kurz vor der Landung der Zielpunkt. Die eine alltaegliche Art, die Route zu verlieren, ist ein /reload mitten im Flug: Der Erfassungshaken hat vor dem Neuladen ausgeloest und kann kein zweites Mal ausloesen. Genau deshalb war das fuer die Betroffenen reproduzierbar und hier nie zu sehen. Drei Aenderungen: (1) Die erfasste Route ueberlebt ein /reload - sie wird zusammen mit der aktuellen Teilstrecke in die charakterbezogenen Einstellungen geschrieben und im Flug wieder eingelesen, ein Neuladen fuehrt also gar nicht mehr in den Rueckfall; (2) der Startpunkt des Fluges wird jetzt ebenfalls aus der Routenerfassung gelesen (der Quellplatz der ersten Teilstrecke), damit sind Start und Ziel namentlich bekannt und koennen in keinem Modus mehr angesagt werden; (3) im Rueckfallbetrieb muss ein Flugpunkt NAEHER kommen, bevor er als Landemoeglichkeit angeboten wird - ein Punkt, von dem man wegfliegt, liegt hinter einem; (4) eine bewilligte Anforderung beendet die Route auch fuer den Streckenzeiger: Der angeforderte Halt ist das Flugende, ihn zu passieren ist Ankommen und keine Zwischenstation. Der Ausweg dafuer ist Geometrie statt Zeitschaltung - wer tausend Meter dahinter immer noch fliegt, dessen Anforderung hat der Server ignoriert, und die Route lebt sofort wieder auf. Die neue Pruefung "/skucheck taxi" haelt die Regel fest: Eine vorzeitige Landung ist nie der Start- oder Zielpunkt des eigenen Fluges. Der Schalter liegt pro Profil unter taxiAnnounceLandingPoints. Energiemonitor: aus "nichts" wird "Aktuelle Ressource", und die folgt der Leiste, die du siehst Einfach: Der Lebens- & Energiemonitor beobachtet genau eine Ressource, und die war fest eingestellt: Mana, Wut, Energie - oder "nichts". "Nichts" war aber kein Ausschalter, sondern ein Loch: es warf laufend Lua-Fehler, und was der Monitor stattdessen beobachtete, hatte niemand ausgewaehlt. Der Eintrag heisst jetzt "Aktuelle Ressource" und steht als erster in der Liste. Er folgt der Leiste, die das Spiel dir gerade zeigt: ein Druide bekommt in Normalgestalt Mana, im Baeren Wut und in der Katze Energie, ohne je wieder ins Menue zu muessen. Alle anderen Klassen haben nur eine Leiste - fuer sie ist es einfach ihre Ressource. Eine feste Ressource auszuwaehlen funktioniert unveraendert weiter. Zum Abschalten ist "Aktiviert: Nein" da, dafuer ist der Schalter gedacht. Wer bisher "nichts" eingestellt hatte, findet den Monitor jetzt abgeschaltet und die Ressource auf "Aktuelle Ressource" - wer ihn hoeren will, schaltet ihn wieder ein. Technisch: "NOTHING" gab den Energie-Index -1 (Enum.PowerType.None) direkt an UnitPower und UnitPowerMax weiter - einen Wert, nach dem der Monitor gar nicht fragen sollte. An seine Stelle tritt GetMonitoredPowerType(), das den gespeicherten Wert erst beim Lesen aufloest: eine feste Auswahl auf ihren Index, "Aktuelle Ressource" ueber UnitPowerType("player") auf die gerade angezeigte Leiste. Beide Lesepfade gehen darueber, auch der Token-Vergleich in UNIT_POWER_UPDATE - mit der automatischen Auswahl ist das Token, auf das reagiert werden muss, eben nicht das gespeicherte. Beide Pfade pruefen jetzt ausserdem auf nil und auf ein Maximum von 0, statt dadurch zu teilen; das war die eigentliche Fehlerquelle, und weil einer der beiden Pfade im OnUpdate-Treiber liegt, kam nicht ein Fehler, sondern einer pro Tick. Weil die beobachtete Ressource jetzt unter dem Monitor wechseln kann, wird der vorige Prozentwert beim Wechsel des Tokens zurueckgesetzt - sonst wuerde die erste Ansage nach einem Gestaltwechsel entweder verschluckt oder bekaeme die falsche Richtung (steigend/fallend). Zusaetzlich: der Handler steigt aus, wenn das Modul abgeschaltet ist. Er haengt an zwei Registrierungen (eigenes AceEvent-Objekt und der Dispatcher in Core.lua), OnDisable loeste aber nur die erste - ein im Funktionsmenue abgeschalteter Monitor sagte deshalb weiter an. Neue Pruefung "/skucheck power" haelt die Regel fest: die eingestellte Ressource muss sich immer zu etwas aufloesen, das der Client lesen kann; eine bewusst gewaehlte Ressource, die die eigene Klasse nicht hat, zaehlt als "ausstehend", nicht als Fehler. Der gespeicherte Wert "NOTHING" wird beim Anmelden einmalig auf "ACTIVE" umgestellt und der Monitor dabei abgeschaltet. Auren erkennen Zauber an ihrer Identitaet, nicht mehr am uebersetzten Namen Einfach: Eine Aura, die du angelegt hast, war bisher an deine Spielsprache gebunden. Der gespeicherte Wert war der uebersetzte Zaubername - "Frostblitz" - und ein englischer Client kennt nur "Frostbolt", also feuerte dieselbe Aura dort nie. Aus demselben Grund kam ein in der Gruppe geteiltes Aurenset bei einem Mitspieler mit anderer Sprache tot an, und die mitgelieferten Aurensets gab es ueberhaupt nur auf deutschen Clients. Sku merkt sich jetzt die sprachunabhaengige Identitaet des Zaubers. Zu sehen und zu hoeren bekommst du weiterhin genau den Namen, den dein Spiel benutzt - im Menue, im Namen der Aura und in der Ansage, wenn sie feuert. Deine bestehenden Auren werden beim ersten Anmelden einmalig umgestellt, ohne dass du etwas tun musst; ihre Namen aendern sich dabei nicht. Ein zweiter Gewinn nebenbei: alle Raenge eines Zaubers und auch die Varianten, die Gegner wirken, gehoeren zu einem Eintrag. "Sag mir, wenn mein Ziel Frostblitz wirkt" deckt damit alle 103 Frostblitz-Varianten ab, statt nur die eine, die zufaellig in der Liste stand. Ob DU oder ein Gegner den Zauber gewirkt hat, entscheidet weiterhin die eigene Bedingung "Ereignis Quelle", nicht der Zauber selbst. Wo ein deutscher Zaubername fuer mehrere verschiedene englische steht - "Verblassen" ist sowohl "Fade" als auch "Fade Out" - nennt die Liste den englischen Namen in Klammern dazu, damit die Eintraege unterscheidbar bleiben. Nur die Liste; die Ansage beim Feuern bleibt kurz. Waehlst du so einen Eintrag, gewinnt die aelteste Variante - bei "Verblassen" also der Priesterzauber und nicht "Fade Out". Bereits gespeicherte Auren mit so einem Namen bleiben unveraendert und reagieren weiter auf jede Variante, wie bisher. Technisch: Identitaet ist der enUS-Zaubername aus SkuDB.SpellDataTBC, das ohnehin ausgeliefert und gepflegt wird - keine neue Datei, keine generierte ID-Tabelle (eine solche muesste mit spells.lua synchron gehalten werden, und eine Neugenerierung wuerde gespeicherte Auren still verwaisen lassen). Gespeicherte Werte tragen die Marke "spellgroup:", angezeigt wird weiter SkuAuras.values[key].friendlyName. Die Live-Liste aus UnitAura wird ueber Rueckgabewert 10 (spellId) auf den Gruppennamen abgebildet; auf einem nicht-englischen Client steht der lokalisierte Name als Kompatibilitaets- Alias daneben, damit ein nicht umgestellter Altwert weiter matcht. Auf einem englischen Client sind Gruppen- und Live-Name identisch, der Alias entfaellt und die Kosten sind exakt null. Kennt SpellDataTBC eine ID nicht - die Population, die mit dem Anniversary-Zyklus am ehesten driftet -, faellt die Zuordnung auf den lokalisierten Namen zurueck, also auf das bisherige Verhalten. 838 der 26.603 deutschen Namen (3,15 Prozent) decken mehr als einen englischen ab. Zur Laufzeit gewinnt die Gruppe mit der niedrigsten Zauber-ID - die kollidierenden Varianten sind ausnahmslos spaeter hinzugekommen; geprueft an den Faellen mit bekannter Antwort (Verblassen 586 gegen 5543, Geschwaechte Seele 6788 gegen 36788, Schattenwort: Schmerz 589 gegen 37603, Erneuerung 139 gegen 37563, Gedankenkontrolle 605 gegen 7645). GESPEICHERTE Werte mit so einem Namen werden trotzdem NICHT umgestellt, weil sie heute auf jede Variante passen und eine Umstellung die anderen still wegnehmen wuerde; ihre Menueeintraege bekommen den englischen Namen angehaengt. Der Anzeigename einer Gruppe stammt immer von der niedrigsten ID darin, damit er sich zwischen Sitzungen nicht aendert. Neue Pruefungen unter "/skucheck auren": es gibt ueberhaupt Gruppeneintraege, alle IDs eines Zaubers loesen zu EINER Gruppe auf, und die einmalige Umstellung hat keinen Wert liegen lassen. Aurensets teilen: neues Format ohne Sprachkennzeichen Einfach: Ein geteiltes Aurenset traegt kein Sprachkennzeichen mehr und die Warnung "Set ist fuer eine andere Sprache" entfaellt - die Bedingungen sind jetzt sprachfrei. Beim Annehmen bekommt jede Aura ausserdem ihren Namen in DEINER Sprache, statt den Satz des Absenders zu behalten. Auren, denen du selbst einen Namen gegeben hast, behalten ihn. Technisch: SkuAuraSetV2 (Nutzlast "AURASET2", ohne loc-Feld) wird gesendet; V1 wird weiterhin empfangen, samt bisheriger Sprachwarnung, weil solche Pakete noch lokalisierte Werte tragen. Bewusst wird nur V2 gesendet: ein zusaetzliches V1-Paket wuerde bei aelteren Clients Auren mit Gruppenwerten ablegen, die sie nicht aufloesen koennen. Der Name wird beim Import ueber BuildAuraName neu abgeleitet (SkuAuras:RelocalizedAuraName); customName-Auren sind ausgenommen, und das sind genau die, auf die andere Auren verweisen koennen - die Querverweise bleiben also heil. Auren anlegen: das Menue zum Bauen einer Aura ist neu aufgebaut Einfach: Eine Aura besteht weiterhin aus Bedingungen, und alles, was du schon gebaut hast, rechnet unveraendert weiter - aber der Weg zu einer Bedingung ist an vielen Stellen kuerzer geworden, und die Listen, durch die man dabei laeuft, sind sortiert, kurz und schnell. Der Reihe nach, wie eine Aura jetzt entsteht: Die Attributliste ist durchgehend nach Namen sortiert - auch die Gruppeneintraege, die frueher immer oben standen. Ein Eintrag liegt also da, wo sein Name ihn hinstellt, und ist ueber die ersten Buchstaben erreichbar. Die 35 Ereignisse liegen hinter zwei Eintraegen, "Ereignisse allgemein" und "Ereignisse Zauber"; Gesundheit, Ressource, Mana, Wut, Energie, Runenmacht und Combopunkte liegen zusammen in "Eigene Gesundheit oder Ressource"; und alle Auren, denen du selbst einen Namen gegeben hast, stehen als Bedingung unter "Selbsterstellte Auren" statt einzeln zwischen den echten Attributen - frueher wuchs die oberste Liste mit jeder benannten Aura um einen Eintrag mehr, der sich in jeden Buchstaben des Alphabets einsortierte. Jeder Gruppeneintrag sagt beim Vorlesen selbst, was in ihm ausgewaehlt ist; hineingehen muss man dafuer nicht. Eine Bedingung mit nur zwei Werten - "wahr" und "falsch", oder "buff" und "debuff" - ist jetzt ein Schalter statt drei Ebenen. Der Wert steht am Eintrag, Enter schaltet um: "Im Kampf; wahr", Enter, "Im Kampf; falsch". Beim Anlegen geht Enter einen Schritt weiter auf "nicht festgelegt" und wieder zurueck, damit ein versehentlich gesetzter Schalter auch wieder wegzunehmen ist. Wichtig zum Verstaendnis: "nicht festgelegt" ist kein dritter Wert, sondern heisst, dass es die Bedingung gar nicht gibt - das ist der neutrale Zustand, nicht "falsch". "falsch" ist ein Vergleich wie jeder andere: "Im Kampf gleich falsch" loest NUR ausserhalb des Kampfes aus. Zauber waehlst du weiter aus einer Liste, kannst sie aber auch tippen: ganz oben in jeder Zauber-Werteliste steht "Zauber eingeben", Enter, Name oder Nummer, Enter, und Sku sagt an, welchen Zauber es daraus gemacht hat. Die beiden Bedingungen "zauber nr" und "gegenstand nr" stehen dafuer nicht mehr in der Attributliste: sie meinten einen EINZELNEN Zauberrang und bedeuteten damit direkt neben "zauber name" das Gegenteil von dem, was derselbe getippte Wert dort tut. Neu dazugekommen ist "Buff Debuff nur selbst gewirkte" - steht sie auf wahr, sehen die Buff- und Debufflisten dieser Aura nur noch Effekte, die DU gewirkt hast, sodass "mein Schattenwort: Schmerz laeuft ab" nicht mehr das eines anderen Priesters auf demselben Ziel meldet. Und weil "Quelle (L)" und "ziel (L)" regelmaessig fuer das eigene Ziel gehalten wurden, heissen sie jetzt "Ereignis Quelle (L)" und "Ereignis Ziel (L)": sie filtern das ausloesende EREIGNIS. Zuletzt das Verhalten der Listen selbst: alle Wertelisten oeffnen spuerbar schneller, "zauber benutzbar" friert das Spiel beim Aufklappen nicht mehr ein, ein Zauberwechsel in einer Dauer-Bedingung geht ohne Haenger und ohne den vorherigen Zauber weiter als ausgewaehlt vorzulesen, und "Loeschen" fragt jetzt nach, bevor eine Aura weg ist - es war der einzige Eintrag der Liste, der das nicht tat, direkt neben "Duplizieren", das immer gefragt hat. Technisch: Ein Attribut wird als Schalter gebaut, wenn sein Typ BINARY ist, es genau zwei Werte hat und der Typ genau einen Operator erlaubt (tBinaryValuesForAttribute in SkuAuras/Options.lua); geschrieben wird exakt das, was die alte Werteliste geschrieben hat, eine ueber den Schalter gebaute Aura ist von einer alt gebauten also nicht zu unterscheiden, und eine leere values-Liste faellt aus dem Entwurf - das ist "nicht festgelegt". Die Bedingungszeile paart actionInPlace mit actionOnEnter, das ist es, was Enter und Pfeil rechts auf demselben Knoten auseinanderhaelt. Die Attributliste sammelt Gruppen und Attribute mit ihrem Anzeigenamen ein und fuegt beides in Namensreihenfolge ein. Die zwei Ereignisfamilien sind EIN Attribut und EINE gespeicherte Bedingung: jede Familienliste bietet die andere als einen Eintrag an, und beide zeigen auf die Bedingung, die der Entwurf schon haelt - sonst hinterliesse ein Gang durch beide zwei Bedingungen auf event, die der Speichern-Lauf zu einer immer wahren ODER-Gruppe verschmilzt. listsOwnOnly ist ein binaerer Modifikator: getAuraList faengt im selben Scan den Wirker (7. Rueckgabewert von UnitAura) ab und fuellt parallele own-Mengen, die EvaluateAllAuras pro markierter Aura eintauscht. Die Wertelisten sortieren mit einem Sortierschluessel pro Eintrag statt zweien pro Vergleich (27.057 statt rund 800.000 neue Zeichenketten pro Zauberliste), "zauber benutzbar" fragt die 132 Aktionsplaetze statt aller 49.000 Zauber der Datenbank, und die Dauer-Bedingung laesst jeden Eintrag beim Vorlesen selbst sagen, wie er steht (tValueToggleRefreshLiveName, EINE per Referenz geteilte Funktion), statt bei jedem Enter 27.000 Eintraege zurueckzusetzen. "zauber nr"/"gegenstand nr" werden weiter ausgewertet und sind nur ueber ein retired-Flag aus dem Builder ausgeblendet, damit eine importierte oder alte Aura nicht auf ein nil laeuft; mit ihnen entfallen ihre Wertelisten, rund 49.000 Zauber- und 25.000 Gegenstands-IDs, die bei jedem Laden aufgebaut wurden. Die Locale-SCHLUESSEL der umbenannten Bedingungen sind unveraendert, es verschiebt sich also keine gespeicherte Aura. Beim Loeschen musste zusaetzlich der aName-Zweig des Verwalten-Menues weichen: selectTarget wird erst umgehaengt, wenn die Ebene betreten ist, bis dahin waere die Rueckfrage kosmetisch gewesen. Loeschen frischt jetzt auch die Aura-Pseudoattribute auf - eine geloeschte Aura blieb vorher als Bedingung waehlbar. Franzoesische Clients: die Liste der Waffenverzauberungen fuer Auren war leer Einfach: Auf einem franzoesischen Client bot die Aura-Bedingung fuer Waffenverzauberungen keinen einzigen Eintrag an, sodass sich so eine Bedingung gar nicht anlegen liess. Technisch: SkuAuras:ResolveWeaponEnchantName las Spalte 1 der Enchant-Datenbank fuer enUS und Spalte 2 fuer deDE und liess den Namen sonst nil - fuer jede andere Sprache gab die Funktion damit fuer JEDE Verzauberung nil zurueck, und die Werteliste kam leer heraus. Sie nimmt jetzt die Spalte der eigenen Sprache, sonst die englische, wie der Rest des Namenssystems seit v42.09. Gefunden beim Umbau auf Gruppen- Identitaet, nicht aus einem Bericht. Menue: jeder Eintrag wird jetzt rund 13 mal guenstiger erzeugt Einfach: Lange Listen bauen sich deutlich schneller auf. Am staerksten faellt es bei den Zauberlisten einer Aura-Bedingung auf: die haben 27.057 Eintraege, und auf einem Hardcore-Realm liessen sie sich zuletzt gar nicht mehr oeffnen - der Server bricht dort zu lange laufende Addon-Skripte hart ab, und der Aufbau kam nur etwa bis zur Haelfte. Betroffen ist nicht nur die Aurenliste: jedes Menue in Sku baut sich aus denselben Eintraegen auf. Technisch: Ein Menueeintrag war eine tiefe Kopie der Vorlage SkuGenericMenuItem - pro Eintrag eine Hilfstabelle, ein pairs()-Durchlauf ueber alle 28 Felder mit je einem type()-Aufruf und drei Schluesselvergleichen, 28 Schreibzugriffe und eine rekursive Kopie der children-Tabelle. Jetzt ist ein Eintrag eine fast leere Tabelle, deren Metatabelle per __index auf die Vorlage zeigt: zwei Tabellen und ein Schreibzugriff. Gemessen an 27.057 Eintraegen: das Erzeugen der Knoten faellt von 78 auf 6 ms (13x), der komplette Listenaufbau von 100 auf 31 ms (3,2x, und 2,7x schneller als vor dem Aurenumbau). Ein Schreibzugriff auf einen Eintrag ueberdeckt die Vorlage wie bisher; children bleibt bewusst eine eigene Tabelle pro Eintrag, sonst teilten sich alle Menuepunkte des Addons EINE Kinderliste. Einzige Stelle, die einen Eintrag kopiert (der Filtereintrag in SkuOptions:ApplyFilter), haengt die Metatabelle wieder an. /skucheck menu prueft beides an Wegwerf-Eintraegen. Zum Vergleich nachgemessen: der Aurenumbau selbst hat diese Listen kaum verlangsamt. Die Umstellung auf Gruppen hat die Zauberliste um 460 von 26.597 Eintraegen wachsen lassen (+1,7 %), und Umschalter statt einfacher Eintraege kosten rund 19 % mehr Aufbauzeit. Teuer war der Aufbau schon vorher; auf einem Hardcore-Realm ist eine Skriptgrenze aber eine Kante und keine Schraege, und dafuer reichten die 19 %. Menue: eine abgebrochene Liste blieb still unvollstaendig Einfach: Auf einem Hardcore-Realm bricht der Server ein zu lang laufendes Addon-Skript ab. Traf das den Aufbau einer langen Liste, dann liess sich die Liste beim ZWEITEN Pfeil-rechts zwar oeffnen - aber es war nicht etwa ein neuer Versuch, sondern der halb fertige Rest vom ersten. Bei den Zauberlisten hiess das rund 6.900 von 27.000 Zaubern, ohne jeden Hinweis: wer seinen Zauber nicht fand, musste glauben, es gebe ihn nicht. Jetzt wird der Aufbau im naechsten Frame dort fortgesetzt, wo er abgebrochen wurde, und die Liste ist nach wenigen Frames vollstaendig, ohne dass man etwas druecken muss. Technisch: Das Skript-Budget gilt pro Ausfuehrung, der naechste Frame hat also wieder eines - genau wie beim Aufbau der Routendaten, der aus demselben Grund in Scheiben laeuft. SkuOptions:ContinueInterruptedBuild ruft BuildChildren auf einem Null-Timer erneut auf, solange die Ebene unvollstaendig ist. Fortgesetzt wird nur ein Builder, der sich ueber `resumableBuild` dazu bekennt und einen eigenen Cursor fuehrt: ein gewoehnliches BuildChildren HAENGT AN, ein zweiter Aufruf wuerde also jeden Eintrag doppelt erzeugen - deshalb gab es die alte Sperre ueberhaupt. Der Cursor wird erst NACH einem Eintrag gesetzt, nicht davor, sonst gilt ein Eintrag als gebaut, den der Abbruch verhindert hat. Macht ein Durchlauf keinen Fortschritt, wird aufgegeben statt endlos zu wiederholen. /skucheck menu prueft an einer Wegwerf-Ebene, dass ein abgebrochener Aufbau fortgesetzt und nicht neu begonnen wird. Einstellungen mit zwei Werten sind jetzt Schalter statt Untermenues Einfach: Eine Einstellung, die nur zwei Zustaende kennt - "Ein" und "Aus", "Ja" und "Nein" -, sagt ihren Wert jetzt gleich beim Vorlesen mit: du hoerst zum Beispiel "Sku Menue im Kampf; ein". Enter schaltet um, der Fokus bleibt stehen, und du hoerst den Eintrag sofort im neuen Zustand. Pfeil rechts brauchst du dafuer nicht mehr, denn das Untermenue mit den beiden Werten gibt es nicht mehr. Vorher waren es drei Tasten - rechts, Pfeil, Enter -, und man musste ueberhaupt erst hineingehen, um zu erfahren, wie die Einstellung gerade steht. Das betrifft die gesamten Einstellungen, den Gesundheits- und Kampfmonitor, die Filter von Chat- und Kampfprotokoll, das Funktionsmenue, das Kameramenue und die Einstellungen fremder Addons: rund 150 Eintraege. Einstellungen mit MEHR als zwei Werten behalten ihre Liste, dort gibt es ja etwas auszuwaehlen. Technisch: Neues gemeinsames Menue-Element SkuOptions:MakeToggleNode in SkuZOptions/templates.lua; SkuOptions:MakeInPlaceToggle stellt eine vorhandene isSelect-Stelle mit EINER Zeile darauf um und benutzt deren eigenes GetCurrentValue und OnAction weiter, damit jede Besonderheit einer Einstellung bleibt, wie sie war. Welcher der beiden Werte dabei als "ein" uebergeben wird, ist egal, und genau das machte die Umstellung der rund 50 vorhandenen Ja/Nein-Stellen mechanisch. Ein Schalter ist ein Blatt (actionInPlace, kein dynamic, keine Kinder) - deshalb tut Pfeil rechts nichts mehr -, und ein RefreshLiveName liest den Zustand unmittelbar vor jeder Ansage neu; das alte Untermenue bekam das umsonst, weil es bei jedem Abstieg GetCurrentValue aufrief. Drei Fallen dabei: der Pfadlauf von SkuOptions:SlashFunc und die Einstellungssuche waehlen mit aEnterFlag = true aus und haetten einen so benannten Schalter UMGELEGT, statt ihn anzusteuern - beide setzen jetzt nur den Fokus, und die Suche vergleicht gegen toggleLabel, weil der Name den Zustand traegt. Auf den Filtereintrag einer Liste wird RefreshLiveName nicht angewandt: SkuOptions:ApplyFilter baut ihn als Kopie des ersten Kindes, und die Kopie wuerde sonst den getippten Text ueberschreiben. Und ein Schalter, dessen Leser einen Fehler wirft, wird in /skucheck menu gezaehlt - er klaenge sonst wie eine Einstellung ohne Wert statt wie ein Defekt. Bereitschaftscheck: das Fenster landete nicht auf der Antwort, wie es jedes andere Popup tut Einfach: Startet jemand in der Gruppe einen Bereitschaftscheck, oeffnet Sku wie bei jedem Popup das Menue und springt hinein. Bei diesem einen Fenster kam der Cursor aber nicht auf "Bereit" an, sondern eine Ebene darueber, sodass es zwei weitere Tastendruecke bis zur Antwort waren. Jetzt stehst du sofort auf "Bereit", darunter liegt "Nicht bereit", und Pfeil links fuehrt zurueck auf "Bereitschaft check". Wer den Check gestartet hat, steht an beiden Eintraegen als Volltext. Technisch: ReadyCheckFrame ist nur eine Huelle um ReadyCheckListenerFrame, das die Meldung und die beiden Knoepfe traegt; generisch abgelaufen wurde diese Huelle eine eigene Menueebene, und der Absprung von SkuCore:CheckFrames landete auf ihr. Es gibt jetzt einen eigenen Bauplan (SkuCore:Build_ReadyCheckFrame in SkuCore/LocalMenu.lua, eingetragen in interactFramesListManual), der die beiden Antworten flach als directAction-Eintraege baut - dasselbe Muster wie Build_RolePollPopup fuer die Rollenabfrage. Die Beschriftungen kommen von den Knoepfen selbst, die Blizzard in ReadyCheckFrame_OnLoad uebersetzt, es braucht also keinen neuen Locale-Eintrag. Gelistet werden nur sichtbare Knoepfe: hast du den Check selbst gestartet, blendet Blizzard die Antwortseite aus und es gibt nichts zu beantworten. Spiel-Lautstaerken: ein gesetzter Wert kam auf einem anderen Charakter wieder laut zurueck Einfach: Wer die Gesamtlautstaerke im Sku-Menue leiser stellte, fand sie auf einem anderen Charakter wieder auf dem alten Wert. Sku hatte die fuenf Lautstaerken und die fuenf Sound-Schalter naemlich zusaetzlich selbst gespeichert und bei jedem Anmelden wieder ins Spiel zurueckgeschrieben. Diese Kopie haengt am Sku-Profil, die Spieleinstellung aber am Konto: zwei Charaktere in verschiedenen Profilen hoerten deshalb zwei verschiedene Lautstaerken, und eine Aenderung in Blizzards eigenen Soundoptionen war beim naechsten Anmelden stillschweigend wieder weg. Sku stellt die Werte jetzt nur noch ein, merken tut sie sich das Spiel selbst - wie bei jedem anderen Spieler auch. Die Regler im Menue zeigen ab sofort den echten Wert des Spiels, auch wenn du ihn woanders geaendert hast. Was wegfaellt: Lautstaerken folgen keinem Sku-Profil mehr. Technisch: SkuOptions:OnEnable schrieb soundChannels und soundSettings bei jedem Anmelden aus dem Profil in die CVars zurueck, davor eine Sonderregel, die einen gespeicherten Wert von 0 oder -1 als defektes Profil ansah und dann alle fuenf Kanaele neu aus den CVars uebernahm. Der ganze Block ist raus. Die Menueknoten in SkuZOptions/Options.lua lesen und schreiben die CVars direkt (tGetSoundCVarPercent, tSetSoundCVarPercent, tGetSoundCVarBool); die zehn Schluessel sind aus SkuOptions.defaults und aus dem Schema entfernt, und ein einmaliger Durchlauf in OnInitialize raeumt sie aus jedem gespeicherten Profil - nicht nur aus dem aktiven, denn ohne Defaults-Eintrag wuerde AceDB sie nie wieder abraeumen. soundChannels selbst bleibt: SkuChannel, der Kanal fuer Skus eigene Ausgabe, ist eine echte Sku-Einstellung. Beim Lesen wird jetzt gerundet statt abgeschnitten - tonumber("0.35") * 100 ergibt 34,999... und waere als 34 zurueckgekommen. Neue Profile bringen keine Lautstaerke-Vorgaben mehr mit; es gelten die Standardwerte des Spiels. Die vier Standardprofile werden angelegt, ohne dazwischen das Profil zu wechseln Einfach: Beim ersten Anmelden legt Sku die vier Standardprofile an, falls sie fehlen. Das geschah bisher, indem Sku der Reihe nach in jedes fehlende Profil wechselte und danach in deines zurueck. Auf einem Hardcore-Realm bricht der Server lange Addon-Skripte ab, und traf das diesen Ablauf, blieb der Charakter in einem fremden Profil stehen - mit allen Einstellungen dieses Profils statt deinen. Ein Profil entsteht aber schon dadurch, dass es seinen Namen bekommt; gewechselt werden muss dafuer gar nichts. Aus zehn schweren Schritten sind vier kurze geworden, die mittendrin nicht schiefgehen koennen. Technisch: Die vier SetProfile-Aufrufe plus der Rueckwechsel in SkuCore/Core.lua sind durch vier Zuweisungen in SkuOptions.db.sv.profiles ersetzt. AceDBs GetProfiles zaehlt genau diese Tabelle auf, und ein Profil wird ohnehin erst beim ersten Hineinwechseln per copyDefaults gefuellt - der gespeicherte Endzustand ist derselbe wie vorher, vier leere Tabellen. Jeder SetProfile-Aufruf dagegen feuerte OnProfileShutdown und lief mit removeDefaults und copyDefaults ueber den kompletten Defaults-Baum aller acht Module, rund zehn Durchlaeufe in einem einzigen Frame. Mit dem Wechseln entfaellt auch das Flag SkuCore.AutoChange, das OnProfileChanged solange stummschaltete und bei einem Abbruch auf true stehen blieb - danach kam fuer den Rest der Sitzung kein Profilwechsel mehr durch. Der Dispatcher pcallt diesen Handler, der Abbruch war also unsichtbar. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.13 Kampf: "Unterbrechungen bei deinem Ziel ansagen" ist jetzt standardmaessig aus Einfach: Auch der zweite der beiden Unterbrechungs-Schalter startet nun ausgeschaltet. Beide Haelften der Aufteilung - dein aktuelles Ziel und alle Gegner - sind ab sofort zuschaltbar statt vorgegeben, denn eine Unterbrechungs-Ansage draengt sich in alles andere, was Sku gerade sagt, und die meisten Spieler wollen sie nicht von allein laufen haben. An der Ansage selbst aendert sich nichts, nur daran, ob sie an ist, wenn du die Einstellung nie angefasst hast. Wieder einschalten unter Kampf, Gegner, "Unterbrechungen bei deinem Ziel ansagen". Wie beim Schalter fuer alle Gegner wird das einmalig auch auf bestehende Profile angewandt, damit ein aus dem alten Einzelschalter uebernommener Wert ihn nicht stillschweigend anlaesst. Technisch: Der Migrationsblock in aqCombat.lua belegt yourTargetInterrupts nicht mehr aus dem frueheren outputInterrupts-Schalter vor; der Standard ist false wie bei allEnemiesInterrupts, und eine einmalige Marke yourTargetInterruptsDefaultOff raeumt Profile auf, die fruehere 42.13-Builds bereits aus dem alten Wert gefuellt hatten. AceDB-Defaults fuellen nur nil, deshalb braucht es die Marke und nicht bloss einen geaenderten Standard. tOldOutputInterrupts faellt mit seinem letzten Leser weg. Auktionshaus: der Komplettscan meldete sich als "Auktion gestartet" Einfach: Der Start eines vollen Auktionshaus-Scans sagte "Auktion gestartet, bitte warten" - das verraet nicht, welche der beiden Scan-Arten laeuft, und eine Suche klingt damit viel zu aehnlich wie ein Komplettscan, der das Auktionshaus danach minutenlang belegt. Jetzt heisst es "Voller Auktionshaus Scan gestartet, bitte warten", passend zur Abschlussmeldung, die schon immer "Voller Auktionshaus Scan abgeschlossen" lautet. Technisch: Der Locale-Eintrag "Full scan started" wurde in deDE, enUS und frFR neu formuliert. Kein Codepfad hat sich geaendert; die Ansagestelle in auctionHouse.lua bleibt unberuehrt. Sku Fokus: der Aufruf eines Fokus kam verzoegert und stotterte Einfach: Wer eine Fokus-Taste drueckt, um den gespeicherten Fokus ins Ziel zu nehmen, hoerte den Namen mit einer spuerbaren Verzoegerung - haeufig kurz angerissen und dann noch einmal von vorn. Ein Tastendruck liefert zwei Ereignisse, eines beim Herunterdruecken und eines beim Loslassen, und Sku hat das hinterlegte Ziel-Makro auf beiden ausgefuehrt. Der zweite Durchlauf nahm dasselbe Ziel noch einmal, und weil jede Zielansage die laufende Sprachausgabe zuerst abraeumt, wurde die gerade begonnene Ansage gestoppt und neu gestartet - verzoegert um genau die Zeit, die die Taste gehalten wurde. Jetzt laeuft das Makro einmal pro Druck. Aufgefallen ist das gerade jetzt, weil die Fokus-Tasten seit v42.13 in der Voreinstellung auf dem Ziffernblock liegen und damit ueberhaupt erst benutzt werden. Technisch: Die acht Fokus-Knoepfe in skuFocus.lua meldeten sich mit RegisterForClicks("AnyUp", "AnyDown") an, fuehrten das Makro also auf beiden Flanken aus. Das Steuerungsfenster der SET-Tasten hatte denselben Fehler und war bereits auf eine Flanke umgestellt worden; die GET-Knoepfe waren dabei ausdruecklich ausgenommen worden. Sie melden sich jetzt ebenfalls nur noch mit "AnyDown" an. Im Log bleiben pro Druck zwei PLAYER_TARGET_CHANGED und genau eine Sprachausgabe uebrig; diese zwei Ereignisse stammen aus /target Name selbst, das erst das alte Ziel leert und dann das neue setzt - erkennbar daran, dass die Soft-Target-Sperre zwei verschiedene Werte schreibt (0, dann 2) und nicht zweimal denselben. Zielwechsel: doppelte Reichweitenpruefung und leerlaufende Gruppenschleifen Einfach: Bei jedem Zielwechsel hat Sku Gruppe und Schlachtzug vollstaendig abgefragt, um zu erkennen, ob das Ziel schon gegen jemanden aus der eigenen Gruppe kaempft - auch allein unterwegs, wo es weder das eine noch das andere gibt. Das waren 88 Abfragen ins Leere, und mit der Einstellung "Spielergesteuerte Einheiten mit allgemeinen Beschreibungen ansagen" wurden ueber zweitausend daraus. Ausserdem lief die Entfernungspruefung bei jedem Zielwechsel zweimal: der zweite Aufruf steckte in einem Programmteil, der sein Ergebnis nie bekommen konnte und deshalb nie etwas angesagt hat. Beides ist entfernt. An dem, was Sku sagt, aendert sich nichts, und die Kampfstatus-Erkennung bleibt vollstaendig - in Gruppe und Schlachtzug werden weiterhin alle Mitglieder geprueft, dazu immer Begleiter und man selbst, und die Frage "wen greift mein Ziel gerade an" wird unveraendert gestellt. Technisch: In SkuMob PLAYER_TARGET_CHANGED sind die Schleifen ueber party1-4 und raid1-40 jetzt mit IsInGroup() / IsInRaid() abgesichert, und der Schlachtzug laeuft nur bis GetNumGroupMembers() - dieselbe Schreibweise wie in SkuAuras und SkuQuest. Die Reihenfolge bleibt erhalten (Gruppe vor Schlachtzug), damit ein Mitglied der eigenen Untergruppe weiterhin als "party N" angesagt wird. In SkuNav ist der aForTarget-Zweig von GetNonAutoLevel entfallen: er begann mit DoRangeCheck, das gar keinen Wert zurueckgibt, womit seine erste Bedingung nie erfuellt war - geblieben war nur die Nebenwirkung, eine zweite erzwungene Reichweitenpruefung samt moeglichem zweitem Entfernungston pro Zielwechsel. Sein Aufrufer in SkuMob und die nur dort benutzte Hilfsfunktion GetCreatureIdFromCreatureGUID sind mit entfallen. Gegner im Kampf: die Anzeige war fuer einen Teil der Nutzer dauerhaft an Einfach: Betroffen ist nur, wer "Spielergesteuerte Einheiten mit allgemeinen Beschreibungen ansagen" eingeschaltet hat (Voreinstellung: aus). Dann meldete jedes angepeilte Ziel "im Kampf" - Ton oder Ansage -, auch ein voellig unbeteiligtes Tier auf der Wiese. Fuer eine Einheit, die Sku nicht einordnen kann, und dazu zaehlt auch eine, die gar nicht existiert, liefert die Namensfunktion eine leere Zeichenkette. Die landete als Eintrag in der Namensliste der eigenen Gruppe. Der Vergleich danach - "greift mein Ziel jemanden aus meiner Gruppe an?" - bekam fuer "mein Ziel greift niemanden an" ebenfalls eine leere Zeichenkette, und die passte auf genau diesen Eintrag. Die Antwort war damit immer ja. Leere Namen werden jetzt weder eingetragen noch verglichen. Fuer Betroffene heisst das: der Kampf-Ton kommt deutlich seltener, naemlich nur noch, wenn das Ziel wirklich gegen einen selbst, den Begleiter oder die Gruppe kaempft. Dieselbe Ursache traf "Private Sku-Schlachtzugszeichen automatisch auf Ziele im Kampf setzen": dort bekam praktisch jedes Ziel ein Zeichen. Technisch: GetTtsAwareUnitName liefert mit vocalizePlayerNamePlaceholdersSkuTts = true "" fuer jede Einheit, die weder man selbst noch Begleiter noch Gruppenmitglied ist. tRosterNames bekam diesen leeren Schluessel, und die Abfrage von targettarget traf ihn wieder. Beide Seiten pruefen jetzt zusaetzlich auf name ~= "". Auren: eine Messhilfe aus der Umbauphase lief im Auslieferungszustand mit Einfach: Der Zwischenspeicher fuer Aurenlisten hat jede Liste zusaetzlich ein zweites Mal komplett neu aufgebaut, um beide Ergebnisse gegeneinander zu pruefen. Das war eine Kontrolle aus der Umbauphase, die versehentlich eingeschaltet ausgeliefert wurde - und sie kostete genau die Arbeit, die der Zwischenspeicher einspart. Sie ist jetzt aus; mit /skuauracache verify on laesst sie sich fuer eine Fehlersuche wieder einschalten. Atlas Loot: Ruckler beim Anmelden und beim Oeffnen Einfach: Seit kurzem hing das Spiel ein paar Sekunden nach dem Ladebildschirm fuer vier bis fuenf Sekunden komplett, und danach dauerte es rund zwanzig statt acht Sekunden, bis alles ruhig lief. Schuld war die Atlas-Loot-Anbindung: Sku hat bei jeder Anmeldung und jedem Neuladen die komplette Atlas-Loot-Datenbank durchgearbeitet - rund 40.000 Eintraege in einem Stueck - auch dann, wenn man Atlas Loot in der ganzen Sitzung nie geoeffnet hat. Das passiert jetzt nicht mehr beim Anmelden, sondern erst, wenn man Atlas Loot tatsaechlich oeffnet, und es laeuft in kleinen Haeppchen im Hintergrund, statt das Bild anzuhalten. Wer Atlas Loot nicht benutzt, zahlt gar nichts mehr dafuer - auch die Datenpakete von Atlas Loot werden dann nicht mehr unnoetig geladen. Zweiter Teil: auch das Aufklappen der Suchliste in Atlas Loot hing spuerbar. Diese Liste hat rund 20.000 Eintraege, und fuer jeden einzelnen wurde beim Aufbauen der Name neu ermittelt und beim Server nach Gegenstandsdaten gefragt - fuer 20.000 Eintraege, die man noch gar nicht angesehen hat. Der Name ist an dieser Stelle laengst bekannt, und die Daten braucht nur der Eintrag, auf dem man gerade steht. Die Liste oeffnet sich jetzt entsprechend schneller. Technisch: alIntegrationQueryAll baut zwei Umkehr-Verzeichnisse ueber die Atlas-Loot- Daten auf: "welcher Boss laesst diesen Gegenstand fallen" und die Namensliste fuer die Suche. Der Lauf hing an einer PLAYER_LOGIN-Wiederholungsleiter (5/10/20/35/60 s) plus einem Netz an PLAYER_ENTERING_WORLD/ZONE_CHANGED_NEW_AREA und lief damit etwa drei Sekunden nach dem Betreten der Welt - ungeteilt, in einem einzigen Frame. Die Begruendung dafuer war ueberholt: sie sollte dem Strg+Shift+L-Sprung die kalte Wartezeit ersparen, doch dieser Sprung hat seine Kontexterkennung laengst verloren und oeffnet nur noch den Menuepunkt, was den Aufbau selbst anstoesst. Drei der vier Tabellen, die der Lauf fuellte, hatte ohnehin niemand gelesen: alLookupBosses und alLookupInstances wurden nur geschrieben und dienten allein als "schon gelaufen?"- Merker fuer genau die Leiter, die den Lauf ausloeste; alDropsByBoss und alDropsByInstance wurden nur hinter einer Bedingung gelesen, die nie wahr sein kann, seit das Kontext-Flag ausschliesslich auf nil gesetzt wird. Alle vier sind entfernt, zusammen mit dem Flag, seinem 120-Sekunden-Timer und BuildContextualWishlistEntry. Der verbliebene Lauf ist eine Koroutine mit 30-ms-Budget pro Frame: das Menue startet ihn im Hintergrund (QueryAllStart), und wer ein vollstaendiges Verzeichnis braucht - Suche, Wunschliste nach Dungeon, "Faellt bei" - wartet an seiner eigenen Stelle darauf (alIntegrationQueryAll, ein Nichts-Tun, sobald es steht). Pro Eintrag wurde es ausserdem billiger: die Namensaufloesung fragt jetzt zuerst Skus eigene Gegenstandstabelle statt GetItemInfo, was pro unbekannter ID eine Server-Anfrage ausgeloest hat, und spart die sechs Ersetzungslaeufe fuer Namen, die aus dieser Tabelle kommen und ohnehin keine Markup-Zeichen enthalten. Der Menueaufbau der Suchliste war der zweite Brennpunkt: alIntegrationItemMenuBuilder nimmt jetzt optional den bereits bekannten Namen entgegen (die Suchliste ist nach genau diesem Namen verschluesselt), und ueberspringt damit pro Eintrag die Namensaufloesung, den Unescape-Lauf und vor allem SkuCore:RequestItemData - also ein ItemMixin samt registriertem Lade-Rueckruf und eine Server-Abfrage je nicht zwischengespeicherter ID, rund 20.000 Mal in einem Frame. Die Beutelisten eines Bosses (ein paar Dutzend Zeilen) fordern die Daten weiterhin vorab an, damit sich unbekannte Namen dort weiter selbst nachtragen, und der Eintrag, auf dem der Cursor steht, fordert sie in seinem OnEnter ohnehin an - der gesprochene Text aendert sich also nicht. Kollisionswarnung: Toene ohne Hindernis Einfach: Der "du haengst fest"-Ton konnte auftauchen, waehrend man einfach von einem NPC zum naechsten lief, ohne dass irgendetwas im Weg stand. Der Zaehler hinter der Warnung wurde nie zurueckgesetzt, also sammelten sich harmlose Einzelmessungen ueber Minuten an, und jede sechste loeste einen Ton aus. Technisch: Die Warnung vergleicht die in einem 0,15-Sekunden-Takt zurueckgelegte Strecke mit der, die das aktuelle Tempo haette schaffen muessen, und gibt nach sechs zu langsamen Takten einen Ton. Nur hatte der Zaehler ausser beim Ausloesen keinerlei Ruecksetzung - nicht bei einem guten Takt, nicht wenn die Warnung gar nicht scharf war - er war also ein Lebenszeit-Sammler statt einer Sechserserie. Der erste Takt nach jedem PLAYER_STARTED_MOVING misst ein angeschnittenes Fenster, weil die vorige Messung noch im Stand erfolgte, und faellt damit zwangslaeufig als "zu langsam" aus: etwa jeder sechste Bewegungsstart ergab einen Ton, Minuten auseinander und ohne jeden Zusammenhang. Das steckt schon lange drin, zaehlte aber nur, solange man selbst eine Bewegungstaste hielt; seit in dieser Version auch motorgetriebene Wege mitwarnen, zaehlt jeder automatische Weg zum Ziel mit - deshalb faellt es beim Abarbeiten von NPCs auf. Der Zaehler wird jetzt bei jedem guten Takt und immer, wenn die Warnung nicht scharf ist, zurueckgesetzt, genau wie es die Folgen-Variante der Warnung schon tat. Diese Variante bleibt unveraendert: sie wird von AUTOFOLLOW_END entschaerft, und der Ton beim Ende des Folgens kommt aus genau diesem Weg - wer ihn hoert, hat den Beweis, dass der Status zurueckgesetzt wurde. Die Warnung hinterlaesst beim Ausloesen jetzt ausserdem eine Zeile im Debug-Log, damit sich "Toene aus dem Nichts" dem Weg zuordnen lassen, aus dem sie kamen. Taxiflug: zwei falsche Flugansagen Einfach: Zwei Dinge wurden angesagt, die nicht stimmten. Erstens sagte Sku kurz vor der Ankunft "Vorzeitige Landung moeglich bei X" - und X war das Ziel, das man ohnehin gerade anflog; dort vorzeitig zu landen heisst schlicht anzukommen. Zweitens kam "Flug beendet" (oder "Flug gestartet") gelegentlich lange nach dem Flug, typischerweise in dem Moment, in dem man das naechste Mal auf- oder abgesessen ist, mitunter Minuten spaeter und ohne jeden Bezug zu einem Flugpunkt. Die erste Ansage bleibt jetzt aus, die zweite kommt genau dann, wenn der Flug wirklich beginnt oder endet, und sonst nie. Technisch, das Ziel als Landepunkt: Den Ausschluss des letzten Punktes gab es bereits, nur rutschte der Routen-Zeiger im entscheidenden Moment darunter weg. Die Route wird beim Start abgegriffen, und ein Zwischenstopp gilt als passiert, sobald er naeher als 250 Yards ist. Das Taxi fliegt aber direkt in seinen letzten Punkt hinein, also wurde auch dieser "passiert": der Zeiger lief hinter das Routenende, der naechste Halt war nil, und die Zielbestimmung fiel still auf die Notloesung "naechstgelegener Flugpunkt" zurueck. Die kennt die Route nicht, damit wechselte die Quelle von "route" auf "nearest" - und genau daran haengt die Bedingung, die den letzten Punkt stummschaltet. Das Ziel war zu dem Zeitpunkt laengst innerhalb der 800-Yard-Schwelle, also kam die Ansage. Der Zeiger bleibt jetzt auf dem Ziel stehen, statt darueber hinauszulaufen: das Ziel ist kein Halt, den man passiert, sondern der Ort, an dem der Flug endet. Damit greift die Stummschaltung bis zur Landung, und die Taste kann das Ziel weiterhin benennen. Technisch, die verspaetete Ansage: Sie hing an zwei Merkern, die PLAYER_CONTROL_LOST bzw. PLAYER_CONTROL_GAINED auf 1 setzten und die AUSSCHLIESSLICH das naechste PLAYER_MOUNT_DISPLAY_CHANGED wieder abgeraeumt hat. Blieb dieses Ereignis aus - oder kam es an der Landung vor dem Kontroll-Ereignis - dann wartete die 1 einfach weiter, und der naechste Reittier-Wechsel loeste sie aus. PLAYER_CONTROL_GAINED feuert ausserdem fuer allerlei, was keine Landung ist (Gedankenkontrolle endet, Zwischensequenz, Rueckstoss, Fahrzeug), sodass der Merker auch voellig ohne Flug gesetzt werden konnte. Der Zustand wird jetzt aus UnitOnTaxi ABGELEITET statt gemerkt: gesprochen wird nur bei einem echten Wechsel falsch->wahr bzw. wahr->falsch, jedes beteiligte Ereignis fuehrt denselben idempotenten Test aus (Kontroll-Ereignisse zusaetzlich zeitversetzt, weil der Client-Merker dem Ereignis hinterherhinkt), und Login/Neuladen uebernimmt den laufenden Zustand stumm. Technisch, zur Sicherheit obendrauf: Im Taxi-Modul ("Vorzeitige Landung moeglich bei X") konnte dieselbe Klasse Fehler nicht auftreten - die Ansage haengt hinter UnitOnTaxi UND dem sichtbaren Abbruch-Knopf. Trotzdem abgesichert, weil beide Merkmale Client-Zustand sind: Kontrolle zurueckerhalten heisst jetzt "Flug vorbei, Punkt" - der Beobachter wird abgeraeumt und kein Ereignis darf ihn wieder starten, bis wirklich ein neuer Flug angetreten wird. Zusaetzlich loescht ein kurzzeitig unsichtbarer Abbruch-Knopf (z.B. bei einem Zonenwechsel im Flug) nicht mehr die Ansage-Merker, was denselben Flugpunkt sonst ein zweites Mal ansagen konnte. "/skutaxi" zeigt den neuen Zustand als "landed=". Gruppeneinladung und Beschwoerung: der Ablehnen-Knopf ist zurueck Einfach: Bei einer Gruppeneinladung oder einer Beschwoerung ("Port") bot das Menue nur noch "Annehmen" an - der Knopf zum Ablehnen fehlte, und er fehlte so lange, wie der Dialog offen war. Beide Knoepfe stehen wieder in der Liste. Technisch: Blizzard sperrt genau bei diesen Abfragen den Ablehnen-Knopf fuer einen Moment nach dem Erscheinen des Dialogs (SetupLockOnDeclineButtonAndEscape, dieselbe Hilfsfunktion, die dort auch Escape abschaltet) - als Schutz gegen versehentliches Wegklicken bei Einladungs- und Beschwoerungsspam. Skus generischer Fensterleser ueberspringt jedes ausgegraute Bedienelement, und er liest ein Popup genau EINMAL aus, 0.1 s nach dem Anzeigen (GENERIC_OnOpen) - mitten in dieser Sperrzeit. Der Ablehnen-Knopf fiel also heraus, und da nichts das Menue neu aufbaut, solange der Dialog einfach nur dasteht, kam er nie wieder. SkuCore:IterateChildren nimmt Knoepfe von StaticPopup-Dialogen jetzt von der Regel "nie ein deaktiviertes Element auflisten" aus: einen Menuepunkt anzusteuern und Enter zu druecken ist eine bewusste Handlung, kein Verklicken. Diese Knoepfe behalten ausserdem ihren OnClick-Handler, auch wenn das deaktivierte Element keine Mausklick-Eingabe meldet - sonst stuende der Eintrag zwar in der Liste, waere aber wirkungslos. Kampf: ein Popup liess sich lesen, aber nicht beantworten Einfach: Ging waehrend eines Kampfes ein Popup auf - eine Gruppeneinladung, eine Beschwoerung, die Frage nach dem Wiederbeleben -, dann konnte Sku es vorlesen und man konnte darin navigieren, aber die Eingabetaste tat nichts: Der Eintrag wurde nur noch einmal vorgelesen. Man musste warten, bis der Kampf vorbei war, und eine Einladung lief in der Zwischenzeit ab. Die Knoepfe eines Popups lassen sich jetzt auch im Kampf druecken, alle vier, nicht nur Annehmen und Ablehnen. Technisch: Im Kampf erreicht die Aktivierungstaste den sicheren Menue-Knopf gar nicht: PLAYER_REGEN_DISABLED blendet OnSkuOptionsMain aus, dessen OnHide loescht die Override-Bindings dieses Knopfes noch waehrend des Gnadenfensters, und die Taste laeuft stattdessen ueber das Snippet von SkuCombatMenuKey, das die Eingabetaste als "nur Route" behandelt und sie direkt an den unsicheren Verteiler gibt (SkuCore/combatMenuKeys.lua). Ergebnis: lesbar, navigierbar, tot bei Enter. Anders als bei den Taschen- und Handelspfaden braucht es dafuer keinen Spiegel und kein sicheres Vorbereiten: Ein StaticPopup-Knopf ist KEIN geschuetzter Frame, sein OnClick ist gewoehnliches Lua (StaticPopup_OnClick ruft OnAccept/OnCancel des Dialogs auf: AcceptGroup, DeclineGroup, ResurrectAccept, RepopMe, ConfirmSummon). Nichts davon haengt am Hardware-Ereignis, also wirkt der direkte Aufruf im Kampf genau wie ausserhalb. Bewusst auf die Popup-Knoepfe beschraenkt - jede andere Klick-Nutzlast in diesem Menue braucht das echte Hardware-Ereignis und gehoert in den Spiegel. Abgesichert: nur im Kampf, nur solange der Knopf da ist, und nur solange Blizzard ihn AKTIV hat (der Ablehnen-Knopf ist in seiner ersten Sekunde gesperrt, dort ist auch "/click" wirkungslos). Neu ist ausserdem, dass alle vier Knoepfe so behandelt werden; Knopf 3 und 4 fielen vorher auf den allgemeinen Klickpfad ohne jede unsichere Aktion zurueck. /skucheck menu zaehlt die Faelle mit, in denen im Kampf aktiviert wurde und gar kein Knopf mehr da war. Tippen in Eingabefeldern: kein Nachplappern mehr nach dem Schliessen Einfach: Beim Tippen in ein Sku-Eingabefeld (Brief schreiben, Suchfeld, Auktionshaus) hinkte die Ansage der Zeichen dem Tippen hinterher, ueberschlug sich, und Buchstaben kamen noch, wenn das Feld laengst geschlossen war - besonders deutlich mit SAPI-Stimmen, die ein Tastendruck bisher nicht abgebrochen hat. Sku tippt jetzt so, wie es ein Screenreader tut: Der naechste Anschlag bricht die Ansage des vorigen ab, statt sich dahinter zu stellen. Was waehrend einer laufenden Ansage getippt wurde, wird zu EINER Ansage zusammengefasst, sodass auch Einfuegen mit Strg+V oder eine gedrueckt gehaltene Pfeiltaste keinen Schwall mehr ausloest. Und beim Schliessen des Feldes - mit Enter, mit OK, mit Escape oder auf jedem anderen Weg - wird nicht mehr nur das Wartende verworfen, sondern auch die gerade laufende Ausgabe abgebrochen. Nebenbei behoben: die Zeichen ( und % wurden beim Tippen gar nicht angesagt. Technisch: Das Echo in SkuOptions:EditBoxShow haengte je getipptem Zeichen eine eigene Aeusserung an die BTTS-Queue. Der Rueckstau-Deckel aus v42.11 (GetBttsQueueDepth / TrimBttsQueue) griff dabei ins Leere: Die Pumpe in SkuVoice ueberspringt ihre 0.1-s-Taktung, sobald mehr als ein Eintrag wartet (`#mSkuVoiceQueueBTTS > 1`), und schiebt den ganzen Schwall binnen weniger Bilder per C_VoiceChat.SpeakText in die Queue des CLIENTS. Skus eigene Queue ist danach leer, die gemessene Tiefe praktisch immer 0, der Deckel loest nie aus, und beim Schliessen findet Trim nichts mehr zum Wegwerfen - der Rueckstau steht zu dem Zeitpunkt in der Client-/SAPI-Queue, an die nur ein echtes StopSpeakingText herankommt. Das Echo laeuft jetzt ueber genau einen Slot: Zeichen werden bis zum naechsten Flush gesammelt (hoechstens 6, die neuesten gewinnen), als EINE ueberschreibende Aeusserung gesprochen und auf 0.1 s Mindestabstand begrenzt; ein Generationszaehler verwirft Flush-Timer und verzoegerte Pfeil-Lesungen, sobald das Feld zu ist. Neu ist SkuVoice:CancelBttsOutput - leert die BTTS-Queue, ruft StopSpeakingText und setzt die Nachsperre der Pumpe auf 0.15 s, damit die unmittelbar folgende Bestaetigung nicht vom asynchron eintreffenden Stop erschlagen wird; es haengt an ENTER, OK, ESCAPE und am OnHide des Rahmens (also auch an einem fremden :Hide()). Ausserdem: SkuVoice:CheckIgnore vergleicht jetzt mit string.find(..., plain=true) - getippte Sonderzeichen wie ( oder % waren Lua-Muster und warfen "unfinished capture" bzw. "malformed pattern", was der pcall des Aufrufers verschluckte; und das Echo setzt ignoreLinks, denn bisher lief jeder Tastendruck durch die komplette Wiki-Link-Suche, deren Ergebnis hier ohnehin verworfen wird. Leistungsverbesserungen und Korrekturen beim Laden der Zauberdatenbank Einfach: Beim Anmelden meldeten einige Spieler einen gesprochenen "Sku Datenbank Fehler, Datensatz spells". Gemeldet wurde das von Era-Spielern, der gemeinsame Nenner ist aber die Rechenleistung und nicht der Client: auf einem schnellen Rechner passierte es nie, auf einem schwaecheren jedes Mal, und auf TBC waere es genauso moeglich gewesen. Die Datenbank selbst war dabei nie kaputt: Gescheitert ist nur die daraus abgeleitete Auswahlliste fuer die Auren, die in EINEM Durchgang ueber rund 90.000 Eintraege aufgebaut wurde. Auf einem langsameren Rechner brach der Client diesen Durchgang mit "script ran too long" ab - und weil die Liste beim Aufbau direkt beschrieben wurde, blieb sie danach halb gefuellt: In den Aura-Einstellungen fehlte ein Teil der Zauber, und Auren, die auf einen fehlenden Eintrag zeigten, sagten nichts mehr an oder liessen das Menue mit einem Fehler stehen. Der Aufbau laeuft jetzt in kleinen Haeppchen ueber mehrere Bilder verteilt, genau wie der uebrige Datenbankaufbau nach dem Anmelden, und wird erst ganz am Ende in einem Stueck uebernommen. Bricht er trotzdem einmal ab, bleiben die bisherigen Listen unveraendert stehen statt halb gefuellt, es wird kein Datenbankfehler mehr gesprochen, und der Rest der Zauberdaten gilt weiterhin als in Ordnung. Zusaetzlich wird die Liste nur noch einmal pro Sitzung gebaut statt bei jedem Ladebildschirm neu. Technisch: SkuAuras:BuildAttributeValueLists laeuft ueber itemLookup UND SpellDataTBC und legt pro Zeile eine Tabelle und ein bis zwei zusammengesetzte Zeichenketten an. Der Aufruf hing bisher an zwei Stellen, beide synchron: am Build-Step "auraValueLists" (nach items+spells) und an PLAYER_ENTERING_WORLD. Die Funktion nimmt jetzt einen optionalen Yield-Callback, den sie alle 1000 Zeilen abfragt, baut in lokale Tabellen und veroeffentlicht diese am Ende mit je einer Zuweisung (atomar - ein Abbruch aendert gar nichts mehr). Gefahren wird sie von einer eigenen Coroutine mit OnUpdate-Pumpe, die sich das gemeinsame Frame-Budget nach dem Anmelden teilt (Sku:BuildFrameBudgetMs, registriert als Build-Worker "skuAuraLists") - drei laufende Worker kosten weiterhin zusammen 150 ms pro Bild. Der Build-Step startet nur noch diesen Treiber und ruft ctx.fail nicht mehr auf: Ein Fehler der abgeleiteten Liste hatte zuvor die ganze Datenfamilie "spells" als gescheitert markiert und die Fehleransage ausgeloest, obwohl die Zauberdaten vollstaendig waren. Fehler landen jetzt in SkuErrorLog ("skuAuraLists") und im Debug-Log. PLAYER_ENTERING_WORLD startet denselben Treiber, der nach einem erfolgreichen Aufbau ein No-Op ist - der bisherige komplette Neuaufbau bei jedem Zonenwechsel und jedem Instanzbetritt entfaellt damit. Ausserdem ueberspringt der Aufbau eine Zauberzeile ohne Namen fuer die aktive Sprache, statt an ihr auszusteigen, und die drei ungeschuetzten friendlyName-Zugriffe im Aura-Menue fallen auf den Rohschluessel zurueck. Ein Gegner, der euch vor seinem Tod vergiftet hat, wird nicht mehr weitergezaehlt Einfach: Die Ansage der Gegnerzahl war seit v42.10 in normalen Kaempfen zuverlaessig, hatte aber einen Fall uebrig: Wenn ein Gegner euch kurz vor seinem Tod ein Gift oder einen anderen anhaltenden Effekt verpasst hat, fiel die Zahl bei seinem Tod korrekt, sprang kurz darauf wieder um eins hoch und fiel erst dann endgueltig, wenn das Gift ablief - der Gegner war da laengst tot. Das ist behoben, ohne dass an der Erkennung selbst etwas veraendert wurde: es wird nichts Neues gezaehlt, eine Sache hoert nur auf, faelschlich mitgezaehlt zu werden. Technisch: Ein gestorbener Gegner wird per GUID gemerkt, damit ihn eine nachlaufende Kampf-Log-Zeile nicht wiederbeleben kann. Diese Markierung wurde bisher in PLAYER_REGEN_ENABLED komplett geleert - also genau in dem Moment, in dem euch der Tod des letzten Gegners aus dem Kampf nimmt, und damit unmittelbar bevor der erste Gifttick eintrifft. Jeder Tick ist eine Kampf-Log-Zeile mit dem toten Gegner als Quelle und euch als Ziel; die Aufnahme-Logik liest das als "ein Gegner kaempft gegen uns" und nahm die Leiche ueber ihre GUID wieder auf. Die zweite Null kam danach nur noch ueber den 6-Sekunden-Leerlauf-Sweep nach dem letzten Tick zustande. Die Markierung traegt jetzt einen Zeitstempel und wird am Kampfende nicht mehr pauschal geloescht, sondern nur noch, wenn sie aelter als 60 Sekunden ist. Innerhalb eines Kampfes aendert sich damit gar nichts - dort galt die Markierung ohnehin bis zum Kampfende, weshalb der Fall "einer von zwei Gegnern stirbt vergiftet, der zweite lebt weiter" schon vorher richtig gezaehlt wurde. Es kommt kein neuer Zustand und keine neue Sonderregel dazu, nur eine Lebensdauer fuer eine Markierung, die es schon gab. Die vorhandene Ausnahme bleibt: taucht dieselbe GUID nachweislich lebend an einem Unit-Token auf, wird die Markierung sofort aufgehoben, ein echter Gegner kann also nie dauerhaft aus der Zaehlung verschwinden. Ein erfolgreich abgeschlossener Handel wurde als zurueckgezogene Bestaetigung gemeldet Einfach: Kam ein Handel wirklich zustande, endete er trotzdem mit " hat die Bestaetigung zurueckgezogen". Es war nichts schiefgegangen: der Server raeumt beim Abschluss erst beide Bestaetigungshaken ab und schliesst danach das Fenster, und dieses Abraeumen sah genauso aus wie ein echter Rueckzug. Die falsche Zeile entfaellt jetzt. Eine "Handel abgeschlossen"-Ansage gibt es dafuer bewusst nicht: der Client 2.5.6 liefert kein Signal, das Abschluss von Abbruch unterscheidet, und eine geratene Meldung waere schlechter als keine. Technisch: Mitgeschnitten fuer eine erfolgreiche Verzauberung im Handel, alles innerhalb einer Sekunde: TRADE_ACCEPT_UPDATE(1,1) -> (0,1) -> (0,0) -> TRADE_CLOSED. TRADE_ACCEPT_UPDATE las diese 1->0-Uebergaenge als echten Rueckzug. Unterscheiden laesst sich das nicht: TRADE_CLOSED traegt keine Nutzdaten, und ERR_TRADE_COMPLETE / ERR_TRADE_CANCELLED existieren auf 2.5.6 nicht (gegen die mitgelieferte TradeInfoDocumentation.lua geprueft). Die beiden Rueckzugs-Ansagen warten jetzt 0,5 s hinter einem Generationszaehler, den ResetTradeAcceptState() an jeder Handelsgrenze hochzaehlt, und entfallen, wenn der Handel beendet ist, das Fenster weg ist oder die Seite wieder auf bestaetigt steht. "Handel bestaetigt" wurde jedes Mal verschluckt Einfach: Wer den Handel aus dem Menue heraus bestaetigt hat, hat die eigene Bestaetigung nie gehoert. Und von mehreren Handelsansagen kurz hintereinander wurde ueberhaupt nur die letzte gesprochen - also ausgerechnet die falsche. Jetzt kommen sie alle, in der richtigen Reihenfolge. Technisch: OutputStringBTtts haengt mit aOverwrite=true einen "queuereset" an, und die Pumpe loescht alles, was VOR diesem Marker in der Warteschlange steht - in einem Schwung frass also jede Handelsansage ihre Vorgaengerin. Alle Handelsansagen uebergeben jetzt false. Das allein rettet die eigene Bestaetigung noch nicht: bestaetigt man aus dem Menue, steht die Serverantwort schon in der Schlange, bevor das Menue seine eigene Zeile fuer den Tastendruck anhaengt, deren Reset sie dann loescht. Die Bestaetigungsansagen laufen deshalb ueber tSayAccept mit 0,35 s Verzoegerung hinter die Menuezeile. Reine Reihenfolge, kein Zustandsraten - und bewusst ohne Generationspruefung, denn ein unmittelbar danach schliessender Handel ist genau der Fall, in dem diese Bestaetigung zaehlt. Enter entzaubert bzw. verzaubert einen Taschengegenstand wieder - in beiden Reihenfolgen Einfach: Wer Entzaubern wirkt (oder eine Verzauberung, einen Ruestungsflicken, ein Waffenoel aufnimmt), waehrend er in der Taschenliste bereits auf dem Zielobjekt steht, und dann Enter drueckt, bei dem passierte bisher gar nichts - nur Strg+Enter half. Die andere Reihenfolge ging: erst wirken, dann zum Gegenstand navigieren. Enter wendet jetzt in beiden Reihenfolgen an. Der Linksklick ist dafuer tatsaechlich der spieleigene Weg: im Taschen-Code von Blizzard benutzt ein Linksklick auf einen Gegenstand diesen fuer den Zauber, solange ein Zauber auf ein Gegenstandsziel wartet. In v41 lief das ueber den alten Eintrag "Linksklick"; der Menue-Umbau in v42.00 hat ihn verloren, und v42.04 hat das Anwenden nur fuer die Reihenfolge "erst wirken" zurueckgeholt. Technisch: Der sichere Linksklick-Knopf wird beim FOKUSSIEREN eines Eintrags bestueckt, und das Anwenden-Makro eines Taschengegenstands ("/use Tasche Slot") nur, solange in diesem Moment SpellIsTargeting() wahr ist. Wird danach gewirkt, trug der Knopf weiter die Bestueckung von vorher - bei einem Taschengegenstand also gar keine -, und der in PreClick genommene Targeting-Schnappschuss laesst zusaetzlich den insecure PickupContainerItem-Rueckfall aussetzen: der Tastendruck tat buchstaeblich nichts. Die Bestueckung ist aus dem generischen OnEnter nach SkuOptions:StageClickMacros gewandert (beide sicheren Knoepfe) und wird von zwei Stellen erneut ausgefuehrt: CURRENT_SPELL_CAST_CHANGED, dessen Handler leer war und dessen Dispatcher-Signatur um eine Stelle verschoben war, und dem PreClick des Linksklick-Knopfes selbst, der laeuft, bevor der sichere Handler die Attribute liest - der Tausch zaehlt also noch fuer genau diesen Tastendruck. Neu bestueckt werden nur Eintraege mit Anwenden-Makro, nur bei offenem Menue und nur ausserhalb des Kampfes. Strg+Enter auf einem Haendlergegenstand oeffnete die Anprobe, statt zu kaufen Einfach: Beim Haendler soll Strg+Enter (Rechtsklick) auf einem Gegenstand einen davon kaufen. Stattdessen ging die Anprobe auf. Der Kauf ueber das Untermenue des Gegenstands hat immer funktioniert und bleibt unveraendert; die Taste kauft jetzt ebenfalls, im Rueckkauf-Reiter auch. Technisch: Die Rechtsklick-Taste traegt standardmaessig STRG, ein Makro "/click RightButton" liest den LIVE-Tastaturzustand, und das XML jedes nativen Gegenstandsknopfes leitet JEDEN modifizierten Klick auf *_OnModifiedClick -> HandleModifiedItemClick -> DressUpLink um - der einfache Rechtsklick-Zweig wird nie erreicht. Das ist dieselbe Falle, die seinerzeit die Oele auf angelegten Waffen kaputtgemacht hat, dort mit "/use " geloest. Haendlergegenstaende rufen jetzt direkt Blizzards unverpacktes MerchantItemButton_OnClick auf, womit die Abfragen fuer Sonderwaehrung und hohen Preis erhalten bleiben. Taschen, Bank und Ausruestungsslots waren schon immun, weil sie ueber "/use" bzw. die Container-API laufen. Ueberall sonst, wo Sku einen nativen Knopf klickt (Beute, Handel, Post, Zauberbuch, Gildenbank), hat die Rechtsklick-Taste keine eigene Aktion zu verlieren - dort passiert bei Strg+Enter nichts oder es kommt die Anprobe, waehrend Enter die eigentliche Aktion ausloest. Der Linksklick darf jetzt auf eine Taste mit Umschalt, Strg oder Alt gelegt werden Einfach: Die Aktivieren-Taste laesst sich auf eine Kombination wie Strg+Enter umbelegen und funktioniert trotzdem. Vorher haette so eine Taste beim Haendler oder auf einem angelegten Gegenstand die Anprobe geoeffnet statt zu handeln - aus demselben Grund wie beim Rechtsklick auf einen Haendlergegenstand. Technisch: Eintraege, deren Klick von einem Modifikator verschluckt wuerde, tragen jetzt eine zweite, modifikatorfeste Bestueckung (plainMacrotext), die die Aktion direkt aufruft, statt den nativen Knopf zu klicken: Haendlergegenstaende ueber Blizzards unverpacktes MerchantItemButton_OnClick, Ausruestungsslots ueber PickupInventoryItem, Handelsplaetze ueber ClickTradeButton bzw. ClickTargetTradeButton. Gestaged wird sie nur, solange ein Modifikator tatsaechlich gedrueckt ist - entschieden im PreClick des sicheren Knopfes, weil nur dort der Tastaturzustand lesbar ist und er noch vor dem Lesen der Attribute laeuft. Mit dem modifikatorfreien Standard-Enter bleibt die Bestueckung byte-gleich wie bisher, dort kann also nichts kaputtgehen. Taschen, Bank, Questbelohnungen, Gildenbank, Popups und Reiter brauchten keinen Eintrag: sie laufen entweder ueber die Container-API oder haben gar keinen Modifikator-Zweig. Beute-Knoepfe, Postanhaenge und Zauberbuch-Knoepfe haben diesen Zweig zwar, werden von Sku aber nie geklickt - Beute hat eine eigene Behandlung, Anhaenge laufen ueber TakeInboxItem, und das Zauberbuch gehoert nicht zu den Fenstern, die Sku oeffnet. Kaeme es dazu, braucht es dort "/cast " statt dieses Verfahrens, denn Zaubern ist geschuetzt und kann von keinem Direktaufruf ausgeloest werden. Die Klick-Tasten des Menues liessen sich ueberhaupt nicht belegen Einfach: In der Tastenbelegung antworteten "Menue; Linksklick/aktivieren" und "Menue; Rechtsklick" auf jedes gedrueckte Enter mit "Ungueltig. Andere Taste druecken." - mit und ohne Modifikator - und liessen sich damit gar nicht setzen, nicht einmal auf ihren eigenen Standard zurueck. Beide sind jetzt belegbar. Technisch: Die Liste der gesperrten Tasten wird als TEILSTRING geprueft, "ENTER" trifft also auch NUMPADENTER und CTRL-ENTER. Sie schuetzt die Navigationstasten des Menues - genau auf dieser Familie leben aber diese beiden Belegungen: Enter ist der Standard der einen, Strg+Enter der der anderen. Sie sind jetzt von der Sperre ausgenommen, und zwar nur fuer Enter-Tasten; Pfeile, Rueckschritt und Tabulator bleiben auch dort gesperrt, weil sie die Navigation steuern, die nicht Teil dieser Belegung ist. Fuer die Kampfmenue-Tasten gab es so eine Ausnahme bereits. Umgesetzt an beiden Stellen, die eine Taste abfangen: im Tastenbelegungs-Menue und im Einzeleintrag-Helfer. Die Menue-Klicktaste loescht die Spielbelegung derselben Taste nicht mehr Einfach: Wer "Menue; Linksklick/aktivieren" wieder auf Enter legte, bekam die Warnung "bereits belegt mit Chat oeffnen" und, nach dem Bestaetigen, genau das: Enter oeffnete den Chat nicht mehr. Zurueck ging es auch nicht, denn fuer Spielbefehle lehnte die Tastenbelegung jedes Enter als ungueltig ab. Dabei haben sich diese beiden Belegungen nie gestoert - sie lagen jahrelang zusammen auf Enter: solange das Menue offen ist, aktiviert Enter den Eintrag, sonst oeffnet es den Chat. Genau so ist es wieder. Wird eine Taste auf diese Weise geteilt, sagt Sku es jetzt an ("Hinweis! Diese Taste wird auch benutzt von ... Beide Belegungen bleiben erhalten."), statt die andere Belegung zu entfernen. Wem der Chat schon abhanden gekommen ist: "Chat oeffnen" im Tastenbelegungs-Menue einfach wieder auf Enter legen, das geht jetzt. Am uebrigen Konfliktverhalten aendert sich nichts - zwei Sku-Tasten auf derselben Taste werden weiterhin gemeldet und die alte geloest. Technisch: Die Klicktasten des Menues sind nie eine echte Belegung, sondern eine Override-Bindung auf dem sicheren Menue-Knopf, die dessen OnShow aufzieht und dessen OnHide wieder abraeumt - sie existiert also nur, solange das Menue offen ist, und uebertoent den Spielbefehl genau in dieser Zeit. Dasselbe gilt fuer die Kampfmenue-Tasten, die nur waehrend eines Kampfes aufgezogen sind. Die Konfliktpruefung kannte diesen Unterschied nicht: sie vergleicht blanke Tastennamen, meldete deshalb einen Konflikt und rief beim Bestaetigen SetBinding(Taste) samt SaveBindings auf - was OPENCHAT dauerhaft von Enter entfernte. Erreichbar wurde das erst dadurch, dass diese Belegungen seit dem Fix darueber ueberhaupt auf Enter gesetzt werden koennen. Die betroffenen Eintraege tragen jetzt in skuDefaultKeyBindings ein Merkmal transientOverride, abgefragt ueber SkuOptions:SkuKeyBindsIsTransientOverride; fuer sie entfaellt die Konfliktbehandlung gegen SPIELBEFEHLE (keine Rueckfrage, kein Entbinden) und wird durch den gesprochenen Hinweis ersetzt. Gegen andere Sku-Belegungen bleibt sie vollstaendig erhalten, denn die sind gleichzeitig aufgezogen und verdraengen sich wirklich. Dieselbe Regel gilt in der Gegenrichtung, damit ein Spielbefehl die Menuetaste nicht loest, und die Enter-Familie ist beim Belegen von Spielbefehlen nicht mehr gesperrt - Pfeile, Rueckschritt und Tabulator bleiben es. Der Hinweis haengt an derselben Ansage wie die neue Taste, weil ein eigener Aufruf mit aOverwrite die Warteschlange leert und sich selbst wieder verschluckt haette. Gegenstaende in der Bank heissen wieder so, wie sie heissen Einfach: In der Bank - und gelegentlich auch anderswo - stand bei manchen Gegenstaenden statt des Namens der Satz "Frage Gegenstandsinformationen ab". Das ist keine Fehlermeldung des Addons, sondern ein Platzhalter des Spiels: der Client zeigt ihn, solange er die Daten eines Gegenstands noch vom Server holt. Betroffen waren vor allem Gegenstaende mit einem umfangreichen Tooltip - Rezepte, Setteile, gesockelte Ausruestung -, weil deren Anzeige erst dann vollstaendig ist, wenn ALLE darin erwaehnten Daten eingetroffen sind. Bisher uebernahm Sku diesen Platzhalter als NAMEN des Eintrags, und blieb dabei: er verschwand nicht mehr, auch nicht nach mehrfachem Anlaufen oder nach Verlassen und Wiederbetreten des Menues. Doppelt aergerlich, weil der Satz fuer jeden betroffenen Platz gleich lautet - mehrere wartende Gegenstaende klangen identisch, waren nicht auseinanderzuhalten und nicht gezielt anzusteuern, und beim Sortieren nach Namen wie beim Anspringen ueber die Anfangsbuchstaben zaehlte ebenfalls dieser Satz. Jetzt nimmt Sku den Namen aus der eigenen mitgelieferten Gegenstandsliste, wenn der Client ihn noch nicht hat, haengt nur ein kurzes "(laedt)" an, fordert die Daten beim Server aktiv an und liest den Eintrag neu vor, sobald sie da sind. Beim Oeffnen der Bank werden die Daten aller Bankplaetze ausserdem schon vorab angefordert, sodass der erste Durchgang meist gar nicht erst wartet. Technisch: Der Satz ist die Spielkonstante RETRIEVING_ITEM_INFO. Gegen sie gab es im Addon keine einzige Pruefung - die einzige Erwaehnung im Quelltext stand in einem Entwicklerwerkzeug und verglich einen fest verdrahteten deutschen Text. Dauerhaft blieb der Zustand aus drei Gruenden: es gab nirgends einen Empfaenger fuer GET_ITEM_INFO_RECEIVED, es wurde nie ein Ladeauftrag gestellt (das Beschreiben eines Tooltips ist keine Anforderung, die man verfolgen kann), und es gab keinen zweiten Weg zu einem Namen. Neu sind SkuUtil:IsRetrievingItemInfo (erkennt den Platzhalter ueber die Spielkonstante statt ueber deutschen Text), SkuCore:ResolveItemName (Client-Cache, dann SkuDB.itemLookup, dann der Name im Link), SkuCore:PendingItemLabel, SkuCore:RequestItemData und SkuCore:ContinueOnItemData ueber Item:CreateFromItemID():ContinueOnItemLoad. Ein eigener Ereignis-Rahmen sammelt GET_ITEM_INFO_RECEIVED und loest daraus einen einzigen, gebuendelten stillen Neuaufbau aus; BANKFRAME_OPENED fordert Fach -1 und die Bankbeutel 5 bis 11 vorab an. Dass ausgerechnet die Bank betroffen war, hat einen eigenen Grund: SetBagItem(-1, Platz) liefert auf 2.5.6 nichts, weshalb der Beutel-Umbau dort auf SetHyperlink(GetContainerItemLink(...)) auswich - ausgerechnet den Weg, der vom Gegenstands-Cache abhaengt. Bankplaetze sind echte Ausruestungsplaetze (Platz n = Ausruestungsplatz n + 39), also liest SetInventoryItem sie genauso oertlich, wie SetBagItem einen Beutel liest; das ist kein Rueckschritt zu den ausgelesenen Fensterelementen, die der Umbau abgeloest hat - kein Rahmen, kein OnEnter, kein Aufklappen der Beutel. Ein Ausweichweg dahinter wurde bewusst nicht stehen gelassen: er wuerde nur verdecken, ob der richtige Weg funktioniert. Gegenstaende verschwinden nicht mehr aus den Beutelisten von AtlasLoot Einfach: In den Beutelisten fehlten Eintraege - ohne Luecke, ohne Hinweis. Eine Liste mit zwoelf moeglichen Beutestuecken zeigte sieben und las sich wie eine vollstaendige Liste mit sieben. Die Ursache ist dieselbe wie beim Punkt davor: Gegenstaende, deren Daten der Client noch nicht vom Server hat, wurden nicht als Gegenstand erkannt und ganz weggelassen. Das traf ausgerechnet die Eintraege, um die es hier geht, denn eine Beuteliste besteht fast nur aus Gegenstaenden, die man noch nie erbeutet oder angesehen hat - je unbekannter der Gegner, desto mehr fehlte. Wiederholbar war es auch nicht: dieselbe Liste ein zweites Mal geoeffnet konnte laenger sein, und die Nummern der Eintraege verschoben sich. Jetzt sind alle Eintraege da, und die Suche nach einem Namen findet auch Gegenstaende, die man noch nie in der Hand hatte. Die Listen werden dadurch laenger als gewohnt, und die Nummern der Eintraege verschieben sich einmalig entsprechend. Technisch: An vier Stellen entschied ein Verteiler anhand von C_Item.GetItemNameByID(id), ob eine Beutezeile ein Gegenstand oder ein Zauber ist - eine Pruefung, die "kein Gegenstand" und "vom Server noch nicht geliefert" vermischt. Ein noch nicht geladener Gegenstand fiel in den Zauber-Zweig, GetSpellInfo lieferte fuer ihn nichts, und die Zeile wurde verworfen. Die Absicht der Pruefung ist richtig (keine unsinnigen Kennzahlen im Menue), nur war die Frage falsch gestellt: GetItemInfoInstant beantwortet sie oertlich aus der Gegenstandsdatenbank des Clients. Dafuer gibt es jetzt den Helfer tIsItemId; an einer der vier Stellen war das Problem schon einmal einzeln mit einem SkuDB-Zusatz umgangen worden, der damit entfaellt. Die Reihenfolge der Zweige bleibt unveraendert. Ausserdem entfaellt der fruehe Ausstieg im "item"-Zweig des Menuebauers; der Eintrag heisst SkuCore:ResolveItemName oder - stabil - "Gegenstand ", bewusst nicht die "(laedt)"-Form, die den Eintrag beim Nachladen unter dem Cursor verschieben wuerde. tItemNameTable fuer die Suche nach Namen wird ebenfalls ueber ResolveItemName gefuellt, und der beim Anmelden ins Leere laufende GetItemNameByID-Aufruf auf die Favoriten ist jetzt ein echter Ladeauftrag. Der Dungeonbrowser bot alle Dungeons an statt nur der passenden Einfach: Unter "Eintrag erstellen" stand die vollstaendige Liste aller Dungeons der Kategorie - auf jeder Stufe dieselbe. Ein Charakter der Stufe zwanzig bekam die heroischen Instanzen der Scherbenwelt genauso angeboten wie ein Siebziger die Todesminen, und beides liess sich anhaken und anmelden, obwohl man dort gar nicht hineinkommt. Im sichtbaren Fenster war das nie so: dort grenzt das Spiel die Liste auf das ein, was zur eigenen Stufe passt, und genau diese Eingrenzung fehlte bei uns - wir haben schlicht die ungefilterte Liste gelesen. Jetzt zeigt Sku dieselbe Auswahl wie das Fenster. Wer trotzdem die ganze Liste braucht, etwa um sich fuer einen Dungeon weit unter der eigenen Stufe anzubieten, schaltet den neuen Eintrag "Nur passende Dungeons" ab; er steht direkt ueber den Dungeon-Gruppen und nennt eingeschaltet, wie viele Eintraege er gerade ausblendet. Bereits angehakte Dungeons bleiben immer sichtbar, auch wenn die Eingrenzung sie sonst verstecken wuerde - sonst haettest du etwas angemeldet, das du im Menue nicht mehr wiederfindest. Technisch: tGetCategoryActivities rief C_LFGList.GetAvailableActivities(categoryID) ohne das filters-Argument auf und bekam damit den kompletten Kategorieinhalt; die Stufen aus GetActivityInfoTable wurden nur fuer die Beschriftung gelesen, nie zum Filtern. Gefiltert wird jetzt in zwei UND-verknuepften Lagen: einmal ueber den Satz des Spiels selbst (GetAvailableActivities(categoryID, nil, Enum.LFGListFilter.Recommended)) und einmal lokal gegen UnitLevel("player") anhand von minLevelSuggestion/maxLevelSuggestion - auf 2.5.x sind das die einzigen Felder mit echten Stufen. Der Satz des Spiels wird nur uebernommen, wenn er nicht leer und eine echte Teilmenge der ungefilterten Liste ist, damit eine abweichende Signatur das Menue niemals leer machen kann; fehlende Stufenangaben lassen einen Eintrag durch. Neu sind die Einstellung dungeonBrowser.showAllActivities (char), der Umschalter SkuCoreDungeonToggleShowAll (baut den Reiter neu auf, weil sich die Kinderliste aendert), die Zaehler in DungeonBrowser.tFilterStats und eine dprint-Zeile "activity filter" mit den Einzelzahlen beider Lagen. Schnellmenue: Lua-Fehler bei einigen Einstellungen Einfach: Im Schnellmenue warfen mehrere Einstellungen einen Lua-Fehler, sobald man sie mit Pfeil rechts aufklappte - besonders unter "Sprachausgabe", aber auch die Beacon-Lautstaerke unter "Lautstaerken" und die Ja/Nein-Schalter unter "Sonstiges". Dieselben Einstellungen ueber ihren normalen Weg im Einstellungsmenue funktionierten einwandfrei. Das Schnellmenue baut naemlich keine eigenen Einstellungen, es zeigt dieselben Eintraege noch einmal an einer zweiten Stelle - und bei dieser Zweitanzeige fehlte eine Angabe, ohne die Sku den gespeicherten Wert nicht finden konnte. Jetzt zeigen beide Wege denselben Wert und schreiben in dieselbe Einstellung. Ausserdem tauchen unter "Sonstiges" wieder alle vier vorgesehenen Eintraege auf: "Tooltip nicht ausblenden" und "NPC Begruessungen abspielen" waren dort still verschwunden, als sie an anderer Stelle im Einstellungsmenue einen neuen Platz bekamen. Technisch: SkuOptions:IterateOptionsArgs entscheidet an seinem vierten Argument (aModule), ob ein Knoten schema-verwaltet ist: skuManaged = (v.get == nil and v.set == nil and aModule ~= nil). Ist er das nicht, liest GetCurrentValue ueber self.optionsPath[self.profileIndex]:get(). Genau diese get/set-Closures haben die schema-verwalteten Knoten aber nicht - sie leben von aModule. Die sechs Spiegel-Aufrufe des Schnellmenues in SkuZOptions/Core.lua gaben aModule nicht mit, also lief jeder Aufklappvorgang eines solchen Knotens in "attempt to call method 'get' (a nil value)". Betroffen waren WowTtsVoice/-Speed/-Volume (SkuChat), beaconVolume (SkuNav), readAllTooltips/interactMove (SkuCore) und vocalizeMenuNumbers/vocalizeSubmenus (SkuOptions); die Audiokanaele und Soundeinstellungen blieben heil, weil sie eigene get/set mitbringen. Alle sechs Aufrufe geben jetzt Modul und keyPrefix genau so mit wie die Original-Menuestelle ("SkuOptions"/"soundChannels.", "SkuNav"/"", "SkuOptions"/"soundSettings.", "SkuChat"/"", "SkuCore"/"", "SkuOptions"/""), womit die gespeicherten Werte unveraendert bleiben. Der Sonstiges-Aufruf bekommt zusaetzlich aIncludeHidden = true, weil doNotHideTooltip und playNPCGreetings inzwischen forAudioMenu = false tragen und deshalb wortlos herausgefiltert wurden. Zusaetzlich lesen und schreiben alle von IterateOptionsArgs erzeugten Knoten jetzt ueber zwei zentrale Helfer (tOptGet/tOptSet) mit drei Stufen - SkuSettings, eigene get/set-Closure, direkter Tabellenzugriff -, sodass eine kuenftige Spiegelstelle ohne aModule hoechstens den Wert direkt liest statt einen Fehler zu werfen. Zwei Umzuege im Menue: Beacon Soundeinstellungen und "Sonstiges" Einfach: Die Beacon-Einstellungen (Beacon-Lautstaerke, Klick bei Beacons samt Winkel und Ton, sowie die Toene fuer schmale, breite und letzte Beacons) lagen bisher unter Monitor. Sie sind jetzt dort, wo auch alle uebrigen Navigationseinstellungen liegen: Einstellungen, Navigation, Beacon Soundeinstellungen. Der Punkt heisst also nicht mehr nur "Beacon", sondern sagt jetzt, worum es geht; unter Monitor gibt es ihn nicht mehr. Ausserdem ist "Sonstiges" im Schnellmenue wieder der letzte Eintrag - "Dial Targeting" und "Soft Targeting" stehen jetzt davor statt dahinter. Technisch: Der Beacon-Block wandert unveraendert aus Aq:MonitorMenuBuilder (SkuCore/aq.lua) in den Navigation-Zweig von SkuCore:MenuBuilder (SkuCore/Options.lua) und haengt dort als Unterpunkt "Beacon Soundeinstellungen" (englisch "Beacon sound settings", franzoesisch "Réglages de son des balises") unter den Navigationseinstellungen. Es sind dieselben Options-Knoten aus SkuNav.options.args, durchgereicht per IterateOptionsArgs gegen SkuSettings:Sub("SkuNav") mit gleichem Modul und keyPrefix - gespeicherte Werte bleiben also unveraendert, und die Ton-Knoten behalten ihr OnAction, das ein Beispiel-Beacon abspielt. Wie zuvor ist die Liste eine ausdrueckliche Auswahl, kein Durchreichen der ganzen args-Tabelle: ein neuer Beacon-Knoten muss dort mit eingetragen werden. Im Schnellmenue (SkuZOptions/Core.lua) sind Dial Targeting und Soft Targeting vor den 7.4-Block gezogen; die Kinderliste traegt kein sorting-Flag, die Einfuegereihenfolge ist also die Anzeigereihenfolge. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.12 Im Charakterfenster werden die Beschreibungen der Werte wieder vorgelesen Einfach: Unter "Eigenschaften" hatte jeder Wert - Zauberschaden, Zaubertrefferwertung, Ausdauer, Waffengeschwindigkeit und alle uebrigen - nur seinen Namen und seine Zahl. Die Beschreibung, die das Spiel dazu anzeigt, war leer: was der Wert bewirkt, die Aufschluesselung nach Zauberschulen, Haupt- und Nebenhand. Die Taste fuer den vollstaendigen Text sagte an diesen Eintraegen nichts. Nur die Widerstaende und die Ausruestung hatten eine Beschreibung. Jetzt hat jeder Wert seine, und sie wird bei jedem Anlaufen frisch gelesen, ist also auch nach einem Buff oder einem Ausruestungswechsel aktuell. Technisch: Der Tooltip-Abruf war an dieser Stelle auskommentiert, und jeder Eintrag wurde mit leerem textFull gebaut - unveraendert schon in v41.06, das ist also kein Rueckschritt aus dem Umbau, sondern hat nie funktioniert. Zwei Gruende, warum er so auch nicht funktionieren konnte: GetButtonTooltipLines wurde mit GameTooltip als zweitem Argument aufgerufen, was genau den Schritt ueberspringt, der den Tooltip erst fuellt; und ohne dieses Argument haette der Helfer trotzdem abgebrochen, weil er ein OnEnter nur fuer Objekte ausloest, die eine .type-Markierung tragen - die haben die Werte-Frames nicht, und genau deshalb setzt die Widerstands-Schleife sie vor ihrem Abruf. Dazu kam ein dritter Grund, an dem eine naive Reparatur falsch geworden waere: TBC schickt alle 29 Werte durch EIN gemeinsames Widget (PlayerStatFrameLeft1), und die Blizzard-Setter lassen ihren Zustand darauf liegen - .tooltip/.tooltip2 sowie .bonusDamage/.spellCrit/.damage fuer die vier Werte, die ein eigenes OnEnter setzen. Keiner raeumt hinter dem vorherigen auf, vier tauschen OnEnter aus und nie zurueck; Blizzards eigenes UpdatePaperdollStats macht vor jeder Gruppe genau deshalb einen Reset. Ohne den haette Wert N die Beschreibung von Wert N-1 vorgelesen. Der Abruf setzt das Widget jetzt vor jedem Setter zurueck und liest den Tooltip ueber NumLines/GameTooltipTextLeft|Right statt ueber GetRegions - letzteres liefert linke und rechte Spalte als zwei getrennte Bloecke, die Aufschluesselung nach Zauberschulen waere also als sechs Schulnamen gefolgt von sechs Zahlen vorgelesen worden. Der Live-Getter, der den Wert bei jedem Anlaufen neu bestimmt, gibt die Beschreibung jetzt als zweiten Rueckgabewert mit; danach wird das Widget ueber PaperDollFrame_UpdateStats in den Zustand zurueckversetzt, den Blizzard erwartet. Sku ist nicht mehr darauf angewiesen, dass interne Kennwoerter unuebersetzt bleiben Einfach: Auf einem franzoesischen Client tat die Taste fuer das Quest-Log gar nichts - kein Fokus, kein Ton, keine Fehlermeldung. Schuld war ein einziges uebersetztes Wort in der franzoesischen Sprachdatei. Manche Eintraege dort sind naemlich keine Beschriftung, sondern ein internes Kennwort, mit dem Sku seine eigenen Menuepfade bildet und wiedererkennt; wird so eines uebersetzt, findet das Addon seinen eigenen Pfad nicht mehr. Das ist behoben, und zwar so, dass es sich nicht wiederholen kann: das Kennwort ist gar kein uebersetzbarer Text mehr. Wer sich einen franzoesischen Pfad angewoehnt hat, kommt damit weiterhin ans Ziel. Ein zweiter Fund derselben Art haette jeden franzoesischen Client beim naechsten Sortieren der Sprachdatei lautlos auf englische Namen fuer Gegner, Objekte und Quests umgestellt - auch das ist beseitigt. Technisch: Gefunden, auf die Ursache zurueckverfolgt und behoben hat das ZenqFR (Games-Access) auf einem echten franzoesischen Client, als PR #2 in diesem Repo. Die weiteren Aenderungen bauen darauf auf. L["short"] trug zwei unabhaengige Bedeutungen: an rund 25 Stellen war es das erste Feld eines SkuOptions:SlashFunc-Pfads, also ein Protokoll-Kennwort, das der Code gegen sich selbst vergleicht, an genau einer Stelle (SkuCore/aq.lua) echter Anzeigetext. Ein Uebersetzer sieht immer nur die zweite Bedeutung. Beide sind jetzt getrennt: Sku.MENU_ROOT ist das Kennwort und wird von allen 23 pfadbildenden Stellen benutzt, dazu von den sechs, die das Literal "short," fest verdrahtet hatten - eine davon war die Quest-Log-Taste. Der Vergleich akzeptiert weiterhin auch L["short"], damit gelernte lokalisierte Pfade weiterlaufen. Nebenbei behoben: der Ersatzwert in SkuCore/dungeonBrowser.lua war "sku" und damit ueberhaupt kein gueltiges Kennwort. Zweitens definierte frFR.lua L["locale"] doppelt - "enUS" im sortierten Rumpf und "frFR" am Ende angehaengt. Richtig aufgeloest wurde das nur durch AceLocales Reihenfolge: eine Nicht-Standardsprache wird ueber einen Proxy registriert, der bedingungslos rawsetzt, also gewinnt die LETZTE Zuweisung. Aus diesem Schluessel liest Sku Sku.Loc, und daran haengt, welche SkuDB-Namenstabellen der gesamte Client benutzt: ein Neuerzeugen oder Sortieren der Datei haette jeden franzoesischen Client stumm auf englische DATEN umgestellt - kein Fehler, keine Logzeile, nur ueberall die falschen Namen. Die verlierende Zeile ist geloescht, die ueberlebende dokumentiert, und dev/rework-docs/_locale_dupes.py meldet ab jetzt doppelte Schluessel je Sprachdatei. Der Linter macht nebenbei sichtbar, dass enUS als AceLocale-Standardsprache umgekehrt ERSTE-gewinnt: derselbe doppelte Schluessel kann pro Sprache auf verschiedene Eintraege zeigen. 64 solcher Konflikte gibt es heute, fast alles alter Uebersetzungsstaub; sie sind bewusst stehen geblieben und jetzt wenigstens sichtbar. Drittens haelt SkuDBEnsureActiveLocaleTables sein Versprechen nun auch wirklich - es laeuft zusaetzlich bei ADDON_LOADED (vorher erst einen OnUpdate nach PLAYER_LOGIN, wer also in seinem eigenen PLAYER_LOGIN-Handler auf [Sku.Loc] zugriff, sah fuer einen Moment nil) und steigt bei unbrauchbarem Sku.Loc nicht mehr wortlos aus, sondern prueft, meldet den wahrscheinlichen Verursacher ins Log und baut die Tabellen trotzdem. Die Sprache verstummt nicht mehr, wenn du schnell durch eine Liste gehst Einfach: Schnelles Blaettern durch ein Menue, durch die Liste der Objekte in der Naehe oder durch die Taschen konnte die Sprachausgabe ganz zum Schweigen bringen - uebrig blieben nur die Klick- und Bakengeraeusche - bis du ein paar Sekunden gewartet oder einen anderen Teil der Oberflaeche angesteuert hast. Jeder Eintrag, an dem du vorbeigelaufen bist, wurde verschluckt, oft auch der, auf dem du stehen geblieben bist. Jetzt geht jeder Eintrag, ueber den du laeufst, an die Stimme, und der Eintrag, auf dem du stehen bleibst, wird gesprochen. An der Frage, welche Ansage gewinnt, wurde nichts geaendert: eine neue ersetzt weiterhin die vorherige, schnelles Blaettern liest also nach wie vor nur das vor, wo du landest, und das Abbrechen der Sprache im Kampf bleibt unveraendert. Technisch: Die Blizzard-TTS-Pumpe hat sich mit einem Countdown getaktet, der je Durchlauf nur die Dauer EINES Bildes abgezogen hat - ihr Rumpf laeuft aber nur alle 0,01 s. Oberhalb von rund 100 fps zog sie damit deutlich weniger ab als tatsaechlich vergangen war, und die beabsichtigte Pause von 0,1 s vor der naechsten Ausgabe wurde real zu 0,2-0,3 s. Da ein Queue-Reset die noch wartende Zeile loescht, bedeutet eine laengere Pause mehr verlorene Ansagen: der Fehler wurde schlimmer, je hoeher die Bildrate war. Die Pause ist jetzt eine GetTime-Frist - bei 60 fps identisch, darueber korrekt. Gemessen an einer Aufzeichnung mit 6-7 Tastendruecken pro Sekunde: vorher ergaben 7 Resets 2 gesprochene Zeilen, nachher ergeben 7 Resets 7. Eine zweite Absicherung unterdrueckt ein StopSpeakingText, wenn nichts unterwegs ist und innerhalb der letzten 0,15 s bereits eines gesendet wurde - der Client verarbeitet Stopps asynchron, ein nachlaufender konnte die naechste Ausgabe abbrechen, bevor sie begonnen hatte. Beim Navigieren greift diese Absicherung jetzt nicht mehr; sie bleibt fuer ereignisgetriebene Schuebe (Post, Chat), die in einer Sekunde 17 Stopps und gar keine Sprache erzeugt haben. Weniger Arbeit je gesprochener Zeile Einfach: Sku leistet fuer jede gesprochene Zeile und jeden abgespielten Ton spuerbar weniger Arbeit, was sich als fluessigeres Blaettern bemerkbar macht. Technisch: Zwei voruebergehende [SOUND-PROBE]-Diagnosen wurden entfernt. Beide haben debugstack(...) als Argument an dprint uebergeben, und dprint prueft das Debug-Flag erst in sich selbst - ein vollstaendiger Stack-Walk lief also bei jedem Ton, auch bei ausgeschaltetem Log, und die Variante in Sku/Core.lua hing am globalen PlaySound, sodass auch Blizzards eigene Aufrufe dafuer bezahlt haben. Sie machten ein Viertel aller aufgezeichneten Log-Zeilen aus. Die Queue-Pumpe ueberspringt ihre Durchlaeufe jetzt vollstaendig, solange beide Warteschlangen leer sind, statt sie rund hundertmal pro Sekunde auszufuehren, und die Wiki-Linksuche steigt vor dem Normalisieren der Zeichenkette aus statt danach: sie wird aus OutputStringBTtts fuer jede gesprochene Zeile aufgerufen, ihr Ergebnis wird dort ohnehin verworfen, und ohne Wiki-Index liefen rund 19 string.gsub-Durchgaenge, nur um eine Abfrage zu erreichen, die nichts tat. Der Installer und die Downloadseite sprechen jetzt auch Franzoesisch Einfach: Sku selbst spricht seit v42.11 Franzoesisch, alles drumherum aber nicht. Der Sku-Installer laeuft jetzt auf Franzoesisch - er nimmt seine Sprache von Windows, und umstellen laesst er sich jederzeit in der Liste "Sprache dieses Installers" - und die Downloadseite gibt es in einer franzoesischen Fassung, erreichbar ueber die Sprachlinks oben auf beiden Seiten. Auch diese Patchnotes gibt es auf Franzoesisch, beginnend mit v42.11. Ein franzoesisches Sprachpaket gibt es weiterhin nicht: auf einem franzoesischen Client spricht Sku ueber den Screenreader, weshalb der Installer dort das englische Paket anbietet. Der Installer traegt damit die Version 4.1. Technisch: Eine franzoesische Tabelle in Loc.cs des Installers (Lang.Fr, derselbe Schluesselsatz wie Englisch und Deutsch, "fr" aus der UI-Kultur des Systems; die Sprachauswahl wird aus ComponentsForm._langOrder aufgebaut, sodass kein Index-Literal mehr nachgezogen werden muss), docs/index-fr.html und "Patch Notes Sku FR.txt", das release.ps1 auf die Webseite spiegelt. Die Docs-Ersetzungen in release.ps1 laufen jetzt ueber eine LISTE von Seiten und greifen auf sprachneutrale Fragmente, damit eine uebersetzte Seite keine veraltete Versionsnummer behalten kann - genau der Fehler, um den es beim Ueberschriften-Fix in v42.11 ging, eine Seite weiter; dabei faellt auch die SkuMapper-Ueberschrift mit ab, die unbemerkt veraltet war. Die Discord-Ankuendigung geht jetzt pro Kanal: eine Webhook-Zeile darf die Sprachen dieses Kanals nennen, ein rein deutscher Server bekommt also eine deutsche Zeile mit deutschen Links statt drei Sprachen, die er nicht wollte. Zwei Menues, die nur ein Zwischenschritt waren, sind weg Einfach: Unter "Einstellungen" stand der Punkt "Kampf", und darin genau ein Eintrag: "Sku Menue im Kampf". Dieser Eintrag steht jetzt direkt in "Einstellungen, Allgemein", das leere "Kampf" darueber gibt es nicht mehr. Dasselbe im Hauptmenue: "Werkzeuge" enthielt nur "Dial Targeting" und "Soft Targeting"; beide stehen jetzt im "Schnellmenue", und "Werkzeuge" ist aus dem Hauptmenue verschwunden. An den Einstellungen selbst aendert sich nichts, alle bisher gespeicherten Werte bleiben erhalten. Technisch: Die drei Eintraege behalten ihre bisherigen Builder, ihre db und ihr keyPrefix, es aendert sich nur, wo sie eingehaengt werden - gespeicherte Werte sind damit unberuehrt. "Werkzeuge" ist als SkuMenu-Modul und aus SkuMenu:SetRootLayout entfernt (SkuZOptions/SkuMenu.lua); DialTargetingMenuBuilder und die softTargeting-Gruppe (weiter ueber IterateOptionsArgs mit aIncludeHidden=true, da forAudioMenu=false) haengen jetzt in den BuildChildren des Schnellmenues (SkuZOptions/Core.lua). Die "Kampf"-Spezifikation faellt aus tSpecs in SkuCore/Options.lua weg; CombatMenuOpenMenuBuilder wird jetzt am Ende des Allgemein-Builders aufgerufen, mit derselben Einstellung combatMenuOpen. Kein SlashFunc-Pfad zeigte auf eines der beiden Menues, es musste also nichts weiter nachgezogen werden. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.11 Taxi: Sku nennt den naechsten Flugpunkt und laesst dich dort landen Einfach: Auf einem Flug beim Flugmeister sagt Sku jetzt an, welcher Flugpunkt als naechstes kommt, und du kannst dort aussteigen, statt bis zum eigentlichen Ziel weiterzufliegen. Die Taste dafuer ist ab Werk Strg-Umschalt-E; sie steht wie jede andere Sku-Taste unter "Navigation und Wegpunkte" zum Umbelegen bereit. Es gibt zwei Ansagen je Teilstrecke, weil sie verschiedene Fragen beantworten: den naechsten Halt beim Abflug und nach jedem Zwischenstopp, und "vorzeitige Landung moeglich" rund 800 Meter davor. Vor dem letzten Halt bleibt Sku still - dort vorzeitig zu landen waere schlicht Ankommen. Abschalten laesst sich das Ganze unter "Taxiflug". Nur Flugmeister-Taxis, niemals Fahrzeuge. Technisch: Neues Modul SkuCore/taxi.lua. Die Route wird mitgeschrieben, nicht geraten: hooksecurefunc auf TakeTaxiNode greift, solange die Taxikarte noch offen ist - das einzige Zeitfenster, in dem GetNumRoutes, TaxiGetNodeSlot und TaxiNodeName ueberhaupt noch antworten. Damit ist die Haltestellenliste exakt, und jeder Halt darauf ist fuer diesen Charakter auch wirklich anfliegbar. Ein Naeherungszeiger schiebt sie weiter, waehrend das Taxi ueber die Knoten fliegt; die Suche nach dem naechstgelegenen Knoten bleibt nur als gekennzeichneter Rueckfall fuer einen /reload mitten im Flug, gefiltert nach Fraktion und Entdeckungsstand. Drei Eigenheiten des Clients stehen im Dateikopf, damit sie nicht neu erarbeitet werden muessen: die Anforderung landet immer am NAECHSTEN Flugpunkt (so steht es auch in TAXI_CANCEL_DESCRIPTION), weshalb der Routenzeiger die richtige Antwort ist; IsPossessBarVisible meldet false, waehrend PossessButton2 sichtbar ist - verlaesslich ist allein MainMenuBarVehicleLeaveButton, gelesen mit IsVisible, und der steht den ganzen Flug ueber; PLAYER_CONTROL_LOST feuert, waehrend UnitOnTaxi noch false ist, weshalb jedes daran haengende Aufraeumen frisch erfasste Daten geloescht haette. Jeder Einstiegspunkt prueft UnitOnTaxi erneut - dieselbe Weiche, mit der Blizzard TaxiRequestEarlyLanding von VehicleExit trennt. Diagnose: "taxi:"-Zeilen im SkuDebugLog und /skutaxi. Gruppeneinladungen werden nicht mehr stillschweigend abgelehnt Einfach: Das Schliessen des Sku-Menues - aus welchem Grund auch immer: Escape aus den Taschen, ein anderes Fenster, ein Wechsel in den Kampf - hat eine offene Gruppeneinladung abgelehnt, und der Einladende bekam eine Absage zu sehen. Fuer einen sehenden Spieler passiert an dieser Stelle gar nichts, der Dialog steht einfach seine 60 Sekunden lang da. Das war also ein Verlust, den es nur mit Sku gab. Die Einladung wird beim Schliessen jetzt nicht mehr beantwortet; sie verschwindet nur vom Bildschirm und ist unter "Local" wieder erreichbar. Technisch: StaticPopupDialogs["PARTY_INVITE"].OnHide ruft DeclineGroup auf, sofern dialog.inviteAccepted nicht gesetzt ist - und OnHide feuert auch bei einem schlichten frame:Hide() (XML-OnHide -> GameDialogMixin:OnHide -> StaticPopup_OnHide -> dialogInfo.OnHide). Das OnHide des Sku-Menues ruft genau dieses StaticPopup1:Hide(). Neu ist SkuCore:NeutralizePopupHide(frame), direkt davor aufgerufen: fuer PARTY_INVITE setzt es inviteAccepted, so dass Blizzards OnHide das Ablehnen ueberspringt, und markiert den Frame, damit der eigene Hook ein neutralisiertes Verstecken von einer echten Antwort unterscheiden kann - schlichte Felder auf einem unsicheren Frame, kein Taint; OnShow setzt inviteAccepted zurueck, ein spaeteres echtes Anzeigen bleibt also unberuehrt. Eine Abfrage-API fuer offene Einladungen gibt es auf diesem Client nicht, der Merker ist also unserer: gesetzt bei PARTY_INVITE_REQUEST, verworfen bei PARTY_INVITE_CANCEL, bei jedem nicht neutralisierten Verstecken (echtes Annehmen, Ablehnen, Zeitablauf) und durch die eigene Frist. Fuer das Protokoll wurden alle Dialoge mit zerstoerendem OnHide geprueft: PARTY_INVITE (hier behoben), LEVEL_GRANT_PROPOSED (DeclineLevelGrant), EQUIP_BIND und Verwandte (CancelPendingEquip - ohne Ueberspring-Flag, braucht eine andere Loesung) und QUIT (CancelLogout, harmlos). Ausstehende Aufforderungen bleiben im Local-Menue erreichbar Einfach: Wenn du mit Escape aus dem Sku-Menue gehst, verschwindet ein offener Dialog vom Bildschirm - eine Beschwoerung, die Frage nach dem Geist, eine Wiederbelebung, eine Bereitschaftspruefung. Bisher war er damit bis zum naechsten /reload weg, obwohl er auf dem Server die ganze Zeit gueltig blieb. Solche Aufforderungen stehen jetzt als eigener Punkt direkt unter "Local", nach der Aufforderung benannt; RECHTS oder EINGABE zeigt das echte Fenster wieder an, und Sku steigt hinein, so dass du die gewohnten Schaltflaechen bedienst. Technisch: Neues Modul SkuCore/pendingPrompts.lua. Die Aufforderungen werden aus dem ZUSTAND wiederhergestellt, nicht aus dem Frame: Beschwoerung ueber C_SummonInfo, Wiederbelebung ueber ResurrectGetOfferer, Geist-Freigabe ueber GetReleaseTimeRemaining plus die Selbstwiederbelebungs-Optionen aus C_DeathInfo, Bereitschaftspruefung ueber GetReadyCheckTimeLeft/Status. Ein rohes :Hide() erreicht nur StaticPopup_OnHide und nie OnCancel, es wurde also nie etwas abgelehnt oder freigegeben - nur PLAYER_ENTERING_WORLD zeigt DEATH und CONFIRM_SUMMON von sich aus wieder an, daher "weg bis zum /reload". Solange der zugehoerige Dialog auf dem Bildschirm steht, wird der Punkt unterdrueckt, es gibt ihn also nie doppelt neben dem Popup-Eintrag. Wichtig ist, dass diese Punkte PASSIV sind: das "ist ueberhaupt etwas offen"-Kriterium in CheckFrames haelt einerseits ein offenes Menue am Leben und reisst andererseits ueber SlashFunc das Menue auf. Ausstehende Aufforderungen speisen nur das Erste (tPendingOnly), sonst wuerde eine dauerhaft erreichbare Aufforderung bei jedem Taschen-Update das Menue aufziehen; aus demselben Grund bleiben sie aus combatMenuHasWindow heraus. Zuerst gab es eine verschachtelte Form mit eigenen Aktionspunkten - funktionsfaehig, aber zu viel Navigation. Jetzt ist es ein einziger flacher Punkt je Aufforderung: kind="action" mit dynamic=true, damit RECHTS ueberhaupt auf OnSelect geht, plus eine OnSelect-Umleitung, die die uebliche Abstiegsmechanik umgeht; die echten Schaltflaechen kommen ueber das normale Auslesen des wieder angezeigten Fensters. Handel: was im Handelsfenster liegt, wird jetzt live angesagt Einfach: Einen Gegenstand per Rechtsklick in das Handelsfenster zu legen war voellig still, und sein Eintrag im Taschenmenue blieb unveraendert stehen. Jetzt sagt Sku " in Handelsplatz N" beziehungsweise "Handelsplatz N geleert", und das auch fuer die Seite deines Handelspartners, die vorher weder sicht- noch hoerbar war. Die Listen "Deine Gegenstaende" und "Gegenstaende des Partners" aktualisieren sich von selbst, der Punkt "Aktualisieren" wird dafuer nicht mehr gebraucht. Solange ein Gegenstand im Handel liegt, steht "im Handel" VOR seinem Taschen-Eintrag, wird also vor dem Gegenstandsnamen gesprochen; und sobald der Zusatz an dem Eintrag auftaucht, auf dem du gerade stehst, sagt Sku nur "im Handel" - der ganze Gegenstandsname wird dir nicht noch einmal vorgelesen. Und nach einem abgeschlossenen Handel verschwindet der weggegebene Gegenstand jetzt zuverlaessig aus der Taschenliste statt nur manchmal. Technisch: Die vorhandene Verkaufs- und Bank-Mechanik konnte hier nicht greifen: einen Gegenstand ins Handelsfenster zu legen entfernt ihn nicht aus der Tasche. Der Client setzt lediglich isLocked auf den Platz (Blizzards eigenes ContainerFrame reagiert auf ITEM_LOCK_CHANGED nur mit einem blassen Symbol), es feuert also kein BAG_UPDATE, auf das die bestehenden Handler haetten reagieren koennen. Aus den Taschen verschwinden die Gegenstaende erst, wenn der Handel ABGESCHLOSSEN ist - und dieses BAG_UPDATE liefert sich ein Rennen mit dem CheckFrames aus TRADE_CLOSED, waehrend Sku.tBagPostAction schon 2,5 Sekunden nach dem Rechtsklick abgelaufen war. Dieses verlorene Rennen war das "manchmal bleibt es stehen". Neu ist Sku.tBagSettleWindow, ein zweites, engeres Fenster in SkuCore:BAG_UPDATE_DELAYED, von TRADE_CLOSED fuer 3 Sekunden scharfgestellt, das den STILLEN SkuBagIdleRefresh ausloest - nicht die sprechende Bestaetigung, denn am getauschten Gegenstand haengt kein Cursor -, plus 1 Sekunde Rueckfall fuer das umgekehrte Rennen. TRADE_PLAYER_ITEM_CHANGED und TRADE_TARGET_ITEM_CHANGED werden erstmals registriert, pro Platz nach Gegenstand und Anzahl entdoppelt und auf TradeFrame:IsVisible begrenzt, damit die Salven am Handelsende still bleiben. Beide teilen sich SkuCore:TradeMenuRefresh, einen entprellten stillen Neuaufbau. Der Zusatz "im Handel" steht vorn: in einer Taschenliste direkt hinter der Positionsnummer, in "alle Gegenstaende" erst NACH dem Sortieren davorgesetzt (wie der "neu"-Zusatz), damit der voruebergehende Zusatz keinen Gegenstand aus seiner alphabetischen Position schiebt. Die Ansage haengt am stillen Neu-Anheften in SkuBagIdleRefresh: es vergleicht den Zusatz am fokussierten Eintrag vor und nach dem Neuaufbau und spricht nur, wenn er neu dazugekommen ist - das entdoppelt sich von selbst, weil die nachfolgenden Refreshes ihn auf beiden Seiten sehen. SkuCore:TradePartnerName ist jetzt die einzige Quelle fuer den Partnernamen, auch fuer die bestehende Goldansage. Kampf: Sku sagt an, wenn ein Zauber unterbrochen wurde Einfach: Unter Feindlich -> Zauber gibt es "Unterbrechungen ansagen" jetzt getrennt fuer dein aktuelles Ziel und fuer alle Gegner - genau wie die Zauberansagen selbst. So kannst du Unterbrechungen auf deinem eigenen Ziel hoeren, ohne jede Unterbrechung im ganzen Schlachtzug mitzubekommen. Unterbrichst du selbst oder dein Begleiter, heisst es "Du hast den Zauber unterbrochen" mit dem Zaubernamen; unterbricht jemand aus deiner Gruppe, heisst es "Zauber unterbrochen". Ab Werk ist nur die Ansage fuer dein aktuelles Ziel an, alle Gegner schaltest du bei Bedarf selbst dazu; wer die Ansage schon einmal ausgeschaltet hatte, bleibt still. Technisch: SPELL_INTERRUPT aus dem Kampflog ueber das neue Dispatcher-Ereignis SKU_SPELL_INTERRUPT. Der frueher einzelne Schalter outputInterrupts ist durch yourTargetInterrupts und allEnemiesInterrupts ersetzt; nur yourTargetInterrupts wird aus dem alten Wert vorbelegt, allEnemiesInterrupts startet aus. Steht der globale Schalter aus, wird nur angesagt, wenn die destGUID des unterbrochenen Zaubers dein aktuelles Ziel ist; stehen beide an, gibt es trotzdem nur eine Ansage. Als "du" gilt die Quellzugehoerigkeit MINE, was den eigenen Begleiter einschliesst (Teufelsjaeger-Zauberblockade und Aehnliches). Kampf: Zauberansagen lassen sich auf unterbrechbare Zauber beschraenken Einfach: Neue Einstellung "Nur unterbrechbare Zauber ansagen" (ab Werk aus) unter Feindlich -> Zauber. Ist sie an, meldet Sku Zauber nicht mehr, gegen die ein Unterbrechen ohnehin nichts ausrichtet. Technisch: Der Rueckgabewert notInterruptible von UnitCastingInfo und UnitChannelInfo ist auf dem Anniversary-Client 2.5.6 tote Datenlage - er kam bei jedem Zauber als nil zurueck, waehrend Rueckgabe 9 die richtige spellId lieferte; Blizzards eigene Zauberleiste setzt das Flag fuer BC und aelter fest auf false. Die Unterbrechbarkeit stammt daher aus einer statischen Liste, neu unter SkuDB/uninterruptibleCasts.lua, uebernommen aus ClassicCastbars (MIT-Lizenz). Sie deckt die alte Welt ab; fuer eigene TBC-Funde stehen leere SkuTbcAdditions-Tabellen zum Nachtragen bereit. Abgeglichen wird ueber spellID, lokalisierten Namen oder npcID plus Name. Weiches Zielen: "wenn kein hartes Ziel gewaehlt ist" wirkt jetzt wirklich Einfach: Die Einstellung, ob weiches Zielen fuer das Interagieren verwendet werden soll, hat nie etwas bewirkt. Der Interagieren-Taste war es egal, ob du ein Ziel hart angewaehlt hattest - eine Leiche oder ein Stuhl daneben hat den Tastendruck trotzdem abgefangen. Das ist behoben, und zwar im Client statt in einer Nachbildung. Zu beachten: Diese Client-Einstellungen sind im Kampf gesperrt. Sku haelt sie deshalb im Ruhezustand so, dass die Unterdrueckung schon steht, wenn dich etwas anspringt und du erst im Kampf anvisierst. Zwei Ecken bleiben: Toetest du dein Ziel, bleibt der Zustand bis zum naechsten Zielwechsel bestehen - in diesem Moment sind Objekte in der Naehe nicht ansprechbar (die anvisierte Leiche selbst pluenderst du normal). Und geraetst du mit einem nicht angreifbaren Ziel in den Kampf, bleibt es fuer diesen Kampf beim weichen Zielen. Das braucht einen Schreibzugriff im Kampf und ist aus einem Addon heraus nicht zu schliessen. Technisch: Alle 32 SoftTarget-CVars sind in 2.5.6 weiterhin registriert (in WowClassic.exe nachgeschlagen) - am Client liegt es also nicht. Beide Zweige des alten if/else schrieben SoftTargetMatchLocked = 0, identisch toter Code in v32.31 wie in v41.04; die Einstellung verliess Lua nie. 41.05 schrieb dann 1, legte aber Option 2 mit Option 1 zusammen, und SoftTargetWithLocked - die CVar, die das tatsaechlich steuert - hat nie eine Sku-Version geschrieben. Gemessen auf 2.5.6.68575, ausserhalb des Kampfes, Leiche und lebender Gegner in Reichweite, Interagieren-Taste bei hart angewaehltem Gegner: WithLocked 0 wirkt auf den Gegner und ignoriert die Leiche, 1 und 2 pluendern beide die Leiche. Nur 0 unterdrueckt weiches Zielen bei gewaehltem Ziel, und einen "nur wenn angreifbar"-Zwischenwert gibt es nicht. Die Option bildet das jetzt direkt ab: 0 (immer) -> WithLocked 2, MatchLocked 0; 1 (wenn kein hartes Ziel) -> WithLocked 0, MatchLocked 1; 2 (kein angreifbares Ziel) -> MatchLocked 2, und WithLocked wird bei PLAYER_TARGET_CHANGED zwischen 0 und 2 umgelegt. Der Ruhezustand ist 0, weil WithLocked ohnehin nur wirkt, solange ein Ziel gewaehlt ist - dort zu ruhen kostet nichts und deckt den Fall ab, den die CVars sonst nie erreichen. 2 wird nur noch fuer den einen Zustand geschrieben, der weiches Zielen MIT gewaehltem Ziel wirklich braucht: ein Ziel, das du nicht angreifen kannst - eine Leiche beim Pluendern, ein NPC im Gespraech, ein Spieler, dem du folgst. Entfernt: der SkuMob-Ticker, der SoftTargetInteract viermal pro Sekunde neu schrieb, sein Duplikat in PLAYER_TARGET_CHANGED und der Schattenzustand interactTempDisabled - diese Nachbildung konnte gar nicht funktionieren, weil die CVars im Kampf geschuetzt sind. tSetSoftTargetCVar liest jeden Schreibvorgang jetzt zurueck (numerischer Vergleich, damit ein normalisiertes "15.000000" kein Fehlalarm ist) und stellt bei Ablehnung die Wiederholung auf PLAYER_REGEN_ENABLED scharf, statt sich einen Wert zu merken, der nie ankam. Ein Schreibversuch im Kampf protokolliert "softTarget refused ... {want=3, got=0}" und loest ADDON_ACTION_BLOCKED aus. Menue: die Eingabetaste wirkte nach dem Schliessen ins unsichtbare Menue weiter Einfach: Nach dem Auswaehlen eines Wegpunkts - und in aehnlichen Faellen - schloss sich das Menue korrekt, aber jede weitere Eingabetaste klickte noch im unsichtbaren Menue weiter: Es ertoente das Navigationsgeraeusch, die Auswahl wurde erneut ausgefuehrt ("neue Navigation"), und das Chatfenster liess sich mit der Eingabetaste nicht mehr oeffnen. Ausserdem konnte das Menue beim Schliessen haengenbleiben, wenn im selben Moment eine Bewegungstaste gedrueckt wurde: Der Wegpunkt wurde gesetzt, das Menue blieb aber offen und blockierte die Tasten. Beides ist behoben. Technisch: Zwei getrennte Ursachen. Erstens laeuft OnPostSelect nach der Aktion weiter, die das Menue geschlossen hat: Es richtete currentMenuPosition wieder auf das selectTarget aus - und ueberschrieb damit die Wurzel-Ruecksetzung des Schliessens - und feuerte dessen OnEnter; das allgemeine OnEnter legte die SKU_KEY_MENULEFTCLICK-Override-Bindings auf dem sicheren Button bedingungslos neu auf. Override-Bindings auf einem VERSTECKTEN Frame sind voll aktiv, die Eingabetaste wurde also unmittelbar nach dem Aufraeumen im OnHide wiederbelebt. Jetzt legt das allgemeine OnEnter die Klick-Tasten nur auf, solange der sichere Button sichtbar ist, und OnPostSelect bricht vor dem abschliessenden Neu-Fokus ab, wenn das Menue nicht mehr offen ist (das kopflose Kampfmenue ist ueber combatMenuActive ausgenommen). Zweitens laeuft CloseMenu ueber denselben Umschalt-Handler wie das Oeffnen, dessen zwei Bewegungs-Sperren das Schliessen stillschweigend abbrachen - die eine liest die LIVE-Bewegungsflags, die andere das zwischengespeicherte SkuCore.isMoving, weshalb der eine Weg durchkam und der andere abbrach. Schliess-Anforderungen umgehen diese Sperren jetzt; Hide und ClearOverrideBindings sind waehrend der Bewegung unbedenklich, und ein erfolgreiches Schliessen erreicht wieder die openMenuAfter-Ruecksetzungen. Zusaetzlich entschaerft der Wiederoeffnen-Ticker Flags, die ohnehin nicht mehr feuern koennen, und stellt die Navigationstasten nur dann neu her, wenn das Menue sichtbar offen, aber tastentot ist (neu: SkuOptions.menuNavKeysBound). Kollisionswarnung auch beim automatischen Hinlaufen zum Ziel Einfach: Die Warnung, dass du gegen etwas laeufst, kam nur, wenn du selbst eine Bewegungstaste gedrueckt hieltest. Beim "Mit Ziel interagieren" der Spielsteuerung laeuft die Spielengine dich hin, ohne dass eine Taste gehalten wird - dort konntest du unbemerkt an einem Hindernis haengenbleiben. Diese Laeufe sind jetzt mit abgedeckt. Technisch: Neues EngineMoving-Flag aus PLAYER_STARTED_MOVING und PLAYER_STOPPED_MOVING, das die koordinatenbasierte Warnung auch fuer engine-getriebene Laeufe scharfstellt. PLAYER_STOPPED_MOVING feuert nicht, waehrend man gegen eine Wand drueckt - genau der Fall, den die Warnung braucht (nachgewiesen ueber das Aufraeumen des stehengebliebenen AutoRun-Flags). Reines Drehen, Fallen und Autofolgen sind ausgenommen; fuer das Folgen gibt es die eigene Folge-Kollisionswarnung. Weniger Fehler in Instanzen und Schlachtzuegen Einfach: Zwei Fehlerquellen, die in Instanzen laufend Lua-Fehler erzeugt haben, sind behoben - spuerbar an ausbleibenden Fehlermeldungen und ruhigeren Bosskaempfen. Technisch: Erstens liefert UnitPosition("player") in Instanzen, Schlachtzuegen und Schlachtfeldern nil, weshalb SkuNav:Distance nil zurueckgab und GetUnsortedAvailableQuestsTable bei jedem QUEST_LOG_UPDATE beim Verketten abstuerzte (24-mal in einer einzigen Schlachtzugssitzung). Es gilt jetzt die bestehende 99999-Meter-Konvention: Die Quest bleibt gelistet und sortiert zuletzt. Zweitens sind ClearOverrideBindings und SetOverrideBindingClick im Kampf geschuetzt, und das umgebende pcall unterdrueckt das ADDON_ACTION_BLOCKED-Ereignis nicht (84-mal in einem einzigen Kampf, dazu BugGrabber-Warnungen wegen Ausfuehrungslimits). Das Setzen der AtlasLoot-Tastenbelegung wird im Kampf jetzt uebersprungen und einmalig ueber PLAYER_REGEN_ENABLED nachgeholt. "Folgen beim Zaubern temporaer beenden" ist zu Testzwecken wieder aktiv Einfach: Diese Einstellung stand im Menue, ihre Funktion war aber seit dem Upstream-Stand v41.06 abgeschaltet. Sie ist wieder eingeschaltet, ab Werk aus, damit sich klaeren laesst, ob dieser Client das automatische Wiederaufnehmen des Folgens ueberhaupt zulaesst. Wer sie einschaltet, sollte damit rechnen, dass das Folgen nach einem Zauber nicht von selbst zurueckkommt. Technisch: Die Ruempfe von UnfollowOnCast und FollowOnCast waren auskommentiert, der Grund ist nicht ueberliefert. Sie beantworten jetzt eine Frage: Fuehrt dieser Client FollowUnit aus einem Server-Ereignis heraus aus, also ohne Hardware-Ereignis, oder wird das still unterbunden? Beweiskanal sind die Sprachausgaben zu AUTOFOLLOW_END/BEGIN und "followcast"-Zeilen im SkuDebugLog samt einer Zustandspruefung 0,5 Sekunden nach dem Aufruf. Nebenbei behoben: In den Handlern fuer CHANNEL_START/STOP passten unitTarget und aUnitTarget nicht zusammen, weshalb Beenden und Wiederaufnehmen bei Kanalzaubern nie ausgeloest wurden. Post: Sku las nach dem Absenden eines Briefes das Getippte noch einmal vor Einfach: Eine Weile nachdem ein Brief abgeschickt war, fing Sku an, die eingegebenen Buchstaben zu wiederholen - teilweise lange nachdem der Briefkasten schon geschlossen war. Dahinter steckten zwei voneinander unabhaengige Fehler. Erstens galt der Briefkasten intern bis zum naechsten /reload als offen, sobald man ihn einmal geoeffnet hatte; jede spaeter eintreffende Post baute daraufhin das Menue neu auf und sagte den aktuellen Eintrag erneut an - egal, wo im Menue man gerade war. Stand man dabei auf einem Brieffeld, war dieser Eintrag der gerade eingegebene Text. Zweitens haengte das zeichenweise Vorlesen beim Tippen jedes Zeichen hinten an die Sprachschlange an: Wer schneller tippt, als die Stimme spricht, baute damit einen Rueckstau auf, den das Schliessen des Eingabefelds nicht beendete - er wurde einfach weiter abgearbeitet. Jetzt folgt die Ansage dem Tippen: Faellt sie zu weit zurueck, wird das noch nicht Gesprochene verworfen, statt hinterherzulaufen. "Gesendet" und die Bestaetigung eines Feldes kommen sofort, nicht mehr hinter allem Getippten. Und eine Posteingangs-Aktualisierung wirkt nur noch, solange der Briefkasten wirklich offen ist und man sich im Post-Zweig des Menues befindet. Zwei Kleinigkeiten am selben Ort: Das Einfuegefeld fuehrte seine OK-Aktion beim n-ten Oeffnen n-mal aus, und beide Sku-Eingabefelder geben beim Schliessen jetzt zuverlaessig die Tastatur wieder frei. Technisch: MailboxOpenFlag wurde in MAIL_SHOW gesetzt, aber nirgends zurueckgesetzt; MAIL_CLOSED loescht es jetzt. MAIL_INBOX_UPDATE kommt nicht nur am geoeffneten Briefkasten - der Server schickt es auch, wenn spaeter Post eintrifft - und lief ungebremst in den generischen OnUpdate (SkuZOptions/templates.lua). Der ist kein stiller Refresh: Er verwirft die Kinder der aktuellen Ebene, baut sie neu auf und ruft VocalizeCurrentMenuName. Zusaetzlich zur Flagge pruefen wir jetzt MailFrame:IsVisible() und laufen die Elternkette bis zum Local-Beitragsknoten L["Mail"] hoch - nur dort ist ein Neuaufbau ein Refresh und kein Fremdeingriff. Der SlashFunc-Zwangsaufruf ohne Menue-Position bleibt allein fuer den echten Fall am offenen Briefkasten; ein Hintergrundereignis darf das Menue nie aufzwingen. Das Tipp-Vorlesen aus v42.08 haengt bewusst an, statt zu ueberschreiben, sonst verschluckt schnelles Tippen Zeichen - aber es hatte keine Obergrenze. Bei rund 0,4 Sekunden je Zeichen gegen vier bis fuenf Anschlaege pro Sekunde waechst die Schlange unbegrenzt, und die Abarbeitung schiebt einen Rueckstau mit etwa 100 Eintraegen je Sekunde in C_VoiceChat.SpeakText, wo Sku ihn nicht mehr einholt. Neu in SkuVoice-1.0 sind deshalb GetBttsQueueDepth und TrimBttsQueue(aKeep): Verworfen wird ausschliesslich, was noch in Skus eigener Schlange WARTET, nie etwas bereits Uebergebenes - deshalb kann dabei kein Wort zerschnitten werden, und deshalb ist das auch mit "Warteschlangen nie zuruecksetzen" zulaessig, denn diese Einstellung meint das Abwuergen laufender Sprache. Der Deckel liegt bei drei wartenden Zeichen. Vor dem OK-Rueckruf wird der Rueckstau verworfen, und MAIL_SEND_SUCCESS wie die Feldbestaetigung in MailEditor sprechen jetzt ueberschreibend statt anhaengend. EditBoxPasteShow haengte sein OnEnterPressed bei JEDEM Aufruf per HookScript an - HookScript ersetzt nicht, es kettet -, weshalb der OK-Rueckruf beim n-ten Oeffnen n-mal lief; er steht jetzt im Einmal-Zweig. Beide Eingabefelder rufen beim Ausblenden ClearFocus, da das Feld ein Enkel des versteckten Rahmens ist und der Tastaturfokus sonst an einem unsichtbaren Eingabefeld haengen bleibt. Gegenstandslevel: bei jedem Gegenstand kam dieselbe Zahl Einfach: Das Gegenstandslevel in den Gegenstandsbeschreibungen war falsch, solange es das gibt. Es gehoerte gar nicht zu dem Gegenstand, den du gerade gelesen hast, sondern zu irgendeinem, der irgendwann vorher in Sku nachgeschlagen wurde - meist Stunden frueher -, und dabei blieb es die ganze Sitzung lang. Deshalb kam bei jedem Gegenstand dieselbe Zahl, und deshalb war es so oft eine 1: ein Schluessel oder ein Questgegenstand, also genau das, was frueh nachgeschlagen wird und tatsaechlich Gegenstandslevel 1 hat. Ein /reload half nicht, denn die falsche Zahl war kein veralteter Wert, der sich auffrischen laesst - es wurde schlicht der falsche Gegenstand gefragt. Derselbe falsche Gegenstand bestimmte auch die Qualitaet, die an Gegenstandsnamen angehaengt wird. Beides stimmt jetzt. Angesagt wird das Gegenstandslevel ausserdem nur noch bei Ausruestung, die du wirklich anlegen kannst: Schluessel, Questgegenstaende, Reagenzien und Verbrauchbares haben grundsaetzlich Gegenstandslevel 1, die Zeile sagte darueber also nichts aus und faellt weg. Auch dort, wo sie nie hingehoerte, ist sie verschwunden - etwa in Buff-Beschreibungen und bei den Widerstaenden im Charakterfenster. Technisch: Das GetItem() eines Tooltips ist ein haftender Zwischenspeicher und keine Auskunft darueber, was der Rahmen gerade anzeigt: ClearLines() setzt es nicht zurueck, und ein SetX(), das nichts fuellt, ebenso wenig - ein nicht zwischengespeicherter Gegenstand, Bankbehaelter -1, oder jeder Zauber-, Aura- und Wertetooltip, hinter dem gar kein Gegenstand steht. SkuScanningTooltip wird einmal bei PLAYER_LOGIN erzeugt und nie neu vergeben, sein GetItem() antwortet also weiter mit dem letzten Gegenstand, der jemals darueber aufgeloest wurde. Dazu kam, dass TooltipLines_helper den Link aus SkuScanningTooltip las, gleichgueltig wessen Regionen ihm uebergeben worden waren - und die meisten Aufrufer uebergeben die des GameTooltip. Zwei kleinere Fehler kamen hinzu: der zweite Rueckgabewert von GetSpell(), der kein Link ist, wurde nach ItemLink geschrieben und an GetDetailedItemLevelInfo gereicht; und ein nicht zwischengespeicherter Gegenstand liefert einen LEEREN Link, der in Lua wahr ist und die Pruefung "if ItemLink then" damit ungehindert passierte. Die Aufloesung liegt jetzt in SkuUtil - TooltipFirstLine, TooltipItemLink, ItemQualityString, ItemLevel - und traut GetItem() nur dann, wenn der gemeldete Name zur tatsaechlich angezeigten ersten Tooltipzeile passt; das ist der einzige verlaessliche Anhaltspunkt. Die drei doppelten Bloecke in LocalMenu und utilities gehen darin auf; tScanTooltipRegions ermittelt Link, Qualitaet und Gegenstandslevel selbst und gibt den geprueften Link zurueck, damit nachgelagerte Aufrufer genau den bekommen, den der Text beschreibt. Die Ausruestungspruefung liest equipLoc aus GetItemInfo und faellt auf C_Item.GetItemInventoryTypeByID zurueck, solange der Gegenstandsspeicher noch kalt ist. Franzoesisch: Sku gibt es jetzt auf Franzoesisch Einfach: Sku laesst sich jetzt auf Franzoesisch benutzen - getestet auf einem franzoesischen Client. Rund 95 Prozent der Menue- und Ansagetexte sind uebersetzt (3063 von 3220 Eintraegen), alles Uebrige faellt automatisch auf Englisch zurueck, so dass nie eine Luecke oder ein leerer Eintrag entsteht. Dazu kommen zwei Dinge, die frueher noch fehlten: Die Routen- und Wegpunktnamen der Uebersetzungsstrecke haben eine eigene franzoesische Tabelle mit 153 Eintraegen, deren Ortsnamen aus einer echten Aufnahme eines franzoesischen Clients importiert und nicht geraten sind, und alle 158 zweisprachig im Code stehenden Texte fuehren jetzt auch eine franzoesische Fassung. Die SPIELnamen - Kreaturen, Quests, Gegenstaende, Objekte - sind vollstaendig aus Questie uebernommen, also Blizzards eigene franzoesische Zeichenketten und nicht maschinell uebersetzt; sie stimmen mit dem ueberein, was ein franzoesischer Client anzeigt, was fuer die Suche nach Routen- und Wegpunktnamen entscheidend ist. Zonennamen kommen direkt vom Client. Sprachausgabe gibt es weiterhin nur auf Deutsch und Englisch; jede andere Clientsprache benutzt die englischen Audiodateien. Fuer deutsche und englische Spieler aendert sich am Text nichts, wohl aber am Speicherbedarf: Sku baut jetzt nur noch die Namenstabellen der eigenen Sprache auf, plus Englisch als Rueckfall, statt wie bisher immer alle. Technisch: Sku.Locs ist jetzt eine GEORDNETE Liste von drei Sprachen, und die gepackten Routennamen in SkuNav:LoadDefaultMapData werden positionsweise dagegen aufgeteilt statt ueber ein string.match mit dem Muster "(.+)" links und rechts vom Trennzeichen. Dieser alte Ausdruck war nicht nur zweisprachig gedacht: ".+" ist gierig, bei drei Feldern "a", "b", "c" waeren die ersten beiden als ein einziges englisches Feld angekommen und nur das letzte als deutsches. Dateien mit weniger Feldern als Sprachen bleiben gueltig und fallen auf enUS zurueck. Sku.LocAudio trennt die AUDIO-Sprache von der Datensprache; dabei sind zwei alte Fehler mit aufgefallen und behoben: SkuAudioFileIndexIntegrated[Sku.Loc] war ungeschuetzt und lief bei jeder Clientsprache ohne eigene Untertabelle in einen nil-Zugriff, und GetAudiodata hatte keinen Gross-/Kleinschreibungs-Rueckfall, waehrend der enUS-Index seine Bezeichner kleingeschrieben ablegt und die Aufrufer sie gross uebergeben - das ist der Grund, warum die Drinnen/Draussen-Ansage auf englischen Clients bisher still war. Der ChunkLoader hat jetzt eine Sprachschranke: Er baute bisher JEDEN registrierten Chunk unabhaengig von der Clientsprache, ein deutscher Client materialisierte also auch die vollstaendigen englischen Namenstabellen und umgekehrt. Die Regel ist nun "aktive Sprache plus enUS", mit objectLookup.deDE als struktureller Ausnahme, weil das englische objectLookup aus dessen Schluesselmenge ABGELEITET wird - eine naive Schranke haette englische Clients ganz ohne Objektnamen zurueckgelassen. Die vier fest verdrahteten .deDE-Merges sind zu SkuDBMergeLocales geworden, was einen latenten Fehler mit erledigt: Ein franzoesischer Client haette Basis-TBC-Namen bekommen, aber stillschweigend keine WotLK-Namen. Nach dem Zusammenfuehren werden Luecken der aktiven Sprache aus enUS aufgefuellt (Questie kennt fuer rund 2700 Sku-IDs keinen franzoesischen Namen); bewusst als Build-Schritt und nicht als __index-Metatabelle, weil pairs() ein __index nicht durchlaeuft und mehrere Verbraucher diese Tabellen AUFZAEHLEN statt zu indizieren - eine Metatabelle haette die Nachschlagevorgaenge repariert und die Menues still verkuerzt. deDE und enUS sind vom Auffuellen ausgenommen, damit der deutsche Aufbau byteweise identisch bleibt (nachgewiesen, 37 von 37 Datensaetzen). Die Sprachdatei selbst ist Sku/locales/frFR.lua, erzeugt aus Teil-Dateien: Nicht uebersetzte Eintraege behalten ihren englischen Wert, die Tabelle ist also immer vollstaendig und gueltiges Lua, und AceLocale liefert fuer de/en ohnehin nil zurueck - die Datei kostet dort nur einen Parse. Fuehrende und abschliessende Leerzeichen sind in dieser Tabelle bedeutungstragend, ueberleben aber keine TSV-Runde: Sie werden beim Zusammenbauen aus dem englischen Original neu angesetzt, und die Pruefung kontrolliert am FERTIGEN String Platzhalterzahl, Randleerzeichen und Semikolonzahl. Zum Testen ohne zweiten Client gibt es /skudebug locale , das die DATEN-Sprache erzwingt und dauerhaft merkt; es greift auf ADDON_LOADED, nicht auf PLAYER_LOGIN, weil der verzoegerte Routenaufbau (Messung: 1,87 s gegen 2,01 s bis PLAYER_LOGIN) bereits entscheidet, welche Namensfelder ueberhaupt aufgebaut werden. Drei harte Fehler auf einem erzwungen franzoesischen Client sind behoben: maps.lua ist eine einfache, nicht gechunkte Tabelle und trug AreaName_lang/Name_lang nur fuer deDE und enUS - die fehlende Sprache wird jetzt einmalig auf ADDON_LOADED aus C_Map gefuellt (GetAreaInfo und GetMapInfo; 2819 Eintraege, davon 1672 vom Client), also mit den echten Blizzard-Namen und ohne eigene Zonennamensdaten; SkuDB.SpellDataTBC legt seine Sprachen INNERHALB jedes Eintrags ab, weshalb sie nie lokalisiert wurden und elf Fundstellen auf frFR abstuerzten - die aktive Sprache zeigt dort jetzt als Referenz auf die englische Untertabelle (kein Kopieren, keine zusaetzlichen Zeichenketten), was fuer diese ueberwiegend als Aura-Schluessel genutzten Namen genuegt; SkuDB.objectResourceNames ist nach Objektnamen je Sprache verschluesselt und wurde beim Aufbau des Wegpunkt-Caches ungeschuetzt gelesen - hier waere ein englischer Rueckfall falsch gewesen (er haette nie gepasst und jedes Erz und Kraut still zu einem gewoehnlichen Wegpunkt gemacht), die Menge wird deshalb ueber die Objekt-IDs abgeleitet. Der gesamte franzoesische Zweig ist inzwischen auf einem franzoesischen Client durchgespielt worden und laeuft: Menues, Namen und Routen erscheinen franzoesisch, und wo keine Uebersetzung vorliegt, greift der englische Rueckfall ohne Luecke. Die Routentabelle routeOverrides_frFR.lua und das dritte Argument an allen Sku.deEn-Stellen sind Teil davon. Da zhCN und ruRU auf Sku.Loc = enUS laufen, deckt derselbe Durchlauf sie mit ab. Downloadseite: die Ueberschrift nannte eine veraltete Version Einfach: Auf der Downloadseite stand in der Ueberschrift zum Haupt-Addon noch "Version 42.06", waehrend der Link darunter korrekt auf 42.10 zeigte. Da man mit dem Screenreader ueber Ueberschriften navigiert, war das Erste, was in diesem Abschnitt angesagt wurde, die falsche Version - es klang, als liefere die Seite ein veraltetes Sku aus. Ueberschrift und Link stimmen jetzt ueberein. Technisch: release.ps1 hat bei jedem Release href und Linktext neu geschrieben, aber nie die Ueberschrift; sie stand seit 42.06 (17.07.2026) ueber vier Releases hinweg still. Die Ueberschrift ist jetzt Teil von Set-DocsSkuLink und kann nicht mehr auseinanderlaufen. Die verlinkte Zip war die ganze Zeit korrekt (geprueft: Sku-42.10.zip enthaelt "## Version: 42.10"). Beacons: ein eigener Ton fuer den letzten Wegpunkt einer Route Einfach: Neben den Toenen fuer kleine und grosse Beacons gibt es jetzt einen dritten: den Ton fuer den letzten Beacon einer Route. Er erklingt nur beim letzten Wegpunkt einer Metaroute, so dass hoerbar ist, ob der Punkt, auf den du zulaeufst, das Ziel ist oder nur eine weitere Etappe. Die Einstellung steht unter Monitor -> Beacon direkt unter den Toenen fuer kleine und grosse Beacons und ist ab Werk Beacon 3. Beim Verfolgen eines einzelnen Wegpunkts aendert sich nichts - dort gilt weiterhin der kleine oder grosse Ton je nach Groesse des Wegpunkts. Technisch: Neue Profil-Einstellung SkuNav beaconSoundSetLast (Vorgabe "Beacon 3"), im SkuNav-Schema deklariert und in die ausdrueckliche Knotenliste des Beacon-Untermenues in SkuCore/aq.lua aufgenommen - diese Liste ist nicht die gesamte args-Tabelle, ein neuer Optionsknoten muss also auch dort stehen, sonst taucht er im Menue nie auf. GetBeaconSoundSetName nimmt ein zweites Argument und liefert damit den Ton fuer den letzten Beacon; das Verhalten fuer schmal/breit und die einarmigen Aufrufer (Panikbeacon, TomTom-Hook) bleiben unberuehrt. Das neue SkuNav:IsLastMetaRouteWp vergleicht den NAMEN des Wegpunkts mit dem letzten Eintrag von metapathFollowingMetapaths[target].pathWps, statt metapathFollowingCurrentWp zu lesen: SelectWP laeuft, bevor dieser Index weitergesetzt wird - eine Indexpruefung waere um eins daneben. Ueber den Namen sind auch das Vorwaertsspringen per MoveToWp und der Start einer Rueckwaertsroute abgedeckt, die alle den Metapfad-Zustand vor dem SelectWP-Aufruf setzen. Bessere Vorgaben fuer neue Spieler Einfach: Wer Sku neu einrichtet, faengt jetzt mit einer brauchbaren Grundeinstellung an, statt sich das Wichtigste erst zusammensuchen zu muessen. Ein paar Tasten sind ab Werk belegt, der Chat ist sinnvoll aufgeteilt und einzelne Ansagen sind von Anfang an eingeschaltet - im Wesentlichen so, wie erfahrene Spieler es sich sowieso einstellen. Jede dieser Vorgaben steht weiterhin an ihrem gewohnten Platz im Menue und laesst sich wie immer aendern. An bestehenden Profilen und Charakteren aendert sich dabei nichts: eine Vorgabe greift nur dort, wo noch nie etwas gespeichert wurde. Die neuen Tasten holt man sich unter Sku Tastenbelegung -> Alles zuruecksetzen; das setzt allerdings wirklich ALLE Tasten zurueck, auch die selbst belegten. Technisch: Reine Vorgabenaenderungen in SkuZOptions/SkuKeyBinds.lua (skuDefaultKeyBindings), SkuChat/Core.lua und Options.lua (ChatFrameDefaultTabs plus die Standard-Registerkarten), SkuCore/Options.lua (SkuCore.defaults) und SkuCore/aqCombat.lua (aqCombatOnLogin). Bestehende Werte bleiben unberuehrt, weil jede Stelle nur bei nil schreibt bzw. AceDB Vorgaben nur in Luecken fuellt. Zwei echte Verhaltensaenderungen haengen daran: der Binder in SkuNav:CreateSkuNavMain hat immer nur .key gesetzt, eine vom Benutzer vergebene ZWEITE Taste blieb fuer alle Navigationsaktionen also wirkungslos (SkuKeyBindsMatchKey kannte sie laengst) - er laeuft jetzt ueber SkuKeyBindsGetKeys und belegt beide. Und weil SkuChat eine Nachricht je Registerkarte ausgibt, die den Typ aktiviert hat, muss ein Nachrichtentyp mit eigener Registerkarte in allen anderen stumm sein, sonst wird er doppelt vorgelesen. Auktionshaus: Mehrfachkauf desselben Gegenstands geht wieder Einfach: Wer mehrere Auktionen desselben Gegenstands kaufte, bekam den ersten Stapel und danach "Interner Auktionsfehler"; der zweite Kauf wurde nie mehr angeboten. Beides ist behoben - die Folgekaeufe laufen durch, und die grundlose Fehlermeldung des Servers wird waehrend einer Suche nicht mehr vorgelesen. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.10 Navigation: Wegpunkte in Gebieten ohne eigene Karte funktionieren wieder Einfach: In der Tiefenbahn meldeten Shift+F9 und Shift+F10 keine Wegpunkte, obwohl das Gebiet vollstaendig kartiert und verknuepft ist. Dieselbe Ursachenfamilie traf Orte am Rand von Instanzen - den Eingangsbereich von Uldaman, den Vorplatz von Karazhan und aehnliche Stellen in Hoehlen und Tunneln: auch dort blieben beide Listen einfach leer, ohne Fehlermeldung. Das ist behoben, Wegpunktliste und Routenfuehrung arbeiten an diesen Orten wieder. Zu beachten: an solchen Stellen kann die Liste auch Wegpunkte des Gebiets enthalten, das ueber oder neben dir liegt. Wenn du in einer Hoehle unter einem anderen Gebiet stehst, pruefe vor dem Auswaehlen kurz, ob der Wegpunkt wirklich zu deiner Umgebung gehoert - sonst laeuft die Fuehrung gegen die Decke. In den Instanzen selbst (Uldaman innen, Karazhan innen) gibt es weiterhin keine Wegpunkte. Dort ist nichts kartiert, und das bleibt auch so. Technisch: Zwei getrennte Ursachen, beide in SkuNav/Geo.lua. Erstens hat areaId 2257 (Die Tiefenbahn) keine ExternalMapID-Zeile, GetUiMapIdFromAreaId liefert dafuer also nil, und die strenge Namens-plus-uiMap-Schleife in GetCurrentAreaId kann solche Gebiete nie treffen. Bis v41 verglich diese Schleife gegen eine nie deklarierte globale Variable und traf genau sie zufaellig; seit der Deklaration lieferte GetCurrentAreaId dort nil, und mit nil als Kontinent brechen ListWaypoints2 und GetAllLinkedWPsInRangeToCoords wortlos ab. Der Namensabgleich wird jetzt bewusst als zweiter Durchgang wiederholt, beschraenkt auf Gebiete ohne uiMap - genau die Menge, die die strenge Schleife ohnehin nie treffen konnte, weshalb kein normales Gebiet anders ausgewertet werden kann. Zweitens gibt der Client in Hoehlen, Tunneln und vor Instanztueren oft die Kontinent-uiMap (1415/1414) zurueck. Die Rettung dafuer in GetBestMapForUnit glich den Namen der UNTERzone gegen InternalAreaTable ab - dort sind aber alle 285 Instanzzeilen auskommentiert, ein Unterzonenname wie "Uldaman" trifft also nichts, die Kontinent-ID ueberlebt, GetAreaIdFromUiMapId macht daraus AreaId -1, und GetCurrentAreaId bleibt ohne Ausweg (eine Zeile namens "Oestliche Koenigreiche" gibt es nicht). Es gibt jetzt einen Rueckfall auf GetRealZoneText, den Zonennamen, der immer eine Zeile hat; er greift nur, wenn die bisherigen Wege nichts Brauchbares geliefert haben. Ausserdem meldet /skuzoneprobe (/szp) jetzt beide Gebiets-Aufloeser nebeneinander, die Cache-Aufteilung nach Wegpunkttyp, die Groesse des Kontinent-Eimers und was die beiden Schnelllisten an Ort und Stelle zurueckgeben. Ein Fehler darin ist mitbehoben: die Sonde las WaypointCache als globale Tabelle, obwohl sie eine Dateilokale von SkuNav/Core.lua ist - die Zahl "im Cache ueberlebt" war deshalb immer 0 und meldete faelschlich, alles sei weggeraeumt worden. Kampf: Die Zaehlung der Gegner im Kampf ist deutlich ruhiger und genauer Einfach: Die Ansage der Gegnerzahl sprang staendig hoch und runter, obwohl sich an der Lage nichts geaendert hatte - in einem Bosskampf mit drei Gegnern kamen so in gut einer Minute vierzehn Ansagen zusammen, von denen die meisten falsch waren. Vier Ursachen sind behoben: Erstens wurde ein Gegner, der sechs Sekunden lang nichts tat - waehrend einer Furcht, in einer Zauberphase, wenn ihn gerade niemand angriff -, aus der Zaehlung geworfen und beim naechsten Schlag wieder aufgenommen. Sku erkennt jetzt an viel mehr Anzeichen, dass ein Gegner noch mitkaempft. Gegner, die wirklich zurueckkehren oder verschwinden, verschwinden weiterhin aus der Zahl. Zweitens hoertest du nach einem Kill richtig "0", kurz darauf faelschlich "1" und dann wieder "0". Tote Gegner koennen nicht mehr zurueckkommen. Drittens fiel die Zahl mitten im Kampf auf 0 und kletterte danach wieder hoch, wenn du selbst kurz aus dem Kampf warst - etwa weil du gefuerchtet weggelaufen bist oder dein letzter Angreifer starb. In den Gruppen-Modi ("Gegner, die die Gruppe oder dich angreifen") zaehlt jetzt, ob noch jemand in der Gruppe kaempft. Viertens wurden freundliche NPCs mitgezaehlt, sobald ein Gruppenmitglied sie geheilt oder gestaerkt hat - etwa Begleit-NPCs in Instanzen. Sie zaehlen nicht mehr mit. Technisch: Alles in SkuCore/aqCombat.lua. (1) lastUpdate wird jetzt von jeder Kampflog-Zeile aufgefrischt, die einen erfassten Gegner als Quelle ODER Ziel nennt, und zusaetzlich von blosser Sichtbarkeit in einem abgefragten Unit-Slot - letzteres nur, solange UnitAffectingCombat fuer den Slot wahr ist. Genau diese Bedingung erhaelt den Zweck der 6-Sekunden-Bereinigung: ein zurueckkehrender Gegner bleibt zwar sichtbar, verliert aber die Kampfmarkierung, wird also nicht aufgefrischt und faellt weiterhin heraus. (2) Ein Todesfall wird in tDeadGuids vermerkt, der Eintrag aus dem Sammelfenster tPendingAdds entfernt, und aqCombat_CREATURE_ADDED_TO_COMBAT weist tote GUIDs ab - vorher machte "false or {}" aus der Totenmarkierung wieder einen lebenden Eintrag. Aufgehoben wird die Markierung nur, wenn ein Unit-Token den Gegner wieder als lebend meldet. (3) PLAYER_REGEN_ENABLED (= "DU hast den Kampf verlassen") leerte die ganze threatTable; in den Modi 2 und 3 wird das jetzt aufgeschoben, solange ein Gruppenmitglied noch UnitAffectingCombat ist, mit einer 2-Sekunden-Nachfrage. Modus 4 ("greifen dich an") raeumt weiterhin sofort auf. (4) Die Feindlichkeit wird aus den Reaktions-Flags der Kampflog-Zeile (COMBATLOG_OBJECT_REACTION_*) und aus UnitReaction <= 4 bestimmt, einmal pro Gegner und danach nie neu - bewusst NICHT ueber UnitCanAttack, denn Bosse werden mitten im Kampf unangreifbar oder immun gesetzt und wuerden genau dann aus der Zahl fallen. Auktionshaus: Auktionen lassen sich wieder einstellen, ohne vorher die Taschen zu oeffnen Einfach: Beim Einstellen einer Auktion passierte manchmal schlicht nichts - der Verkaufsslot blieb leer und die Auktion ging still nicht raus. Wer vorher am Briefkasten, beim Haendler oder an der Bank war, bei dem ging es, denn diese Fenster oeffnen alle Taschen automatisch. Deshalb wirkte der Fehler zufaellig und traf nur manche Sitzungen. Das Einstellen braucht die Taschen jetzt nie mehr geoeffnet. Nebenbei wird das Item im Moment des Einstellens frisch in den Taschen gesucht: hat sich der Stapel seit dem Aufbau des Menues verschoben, wird trotzdem das richtige Item eingestellt. Gerade gesperrte und seelengebundene Kopien derselben Item-ID werden uebersprungen, statt das Einstellen still scheitern zu lassen. Technisch: SkuCore/auctionHouse.lua. Der Verkaufspfad zog das Item ueber das Skript des Taschen-FENSTERS in den Slot: _G["ContainerFrame(bag+1)Item(numSlots-slot+1)"]:GetScript("OnDragStart"). Diese Buttons entstehen erst, wenn eine Tasche wirklich einmal dargestellt wurde, und die Zuordnung ContainerFrame[N] <-> Taschen-ID wird beim OEFFNEN vergeben - die feste Annahme N = bag + 1 stimmt nur, wenn alle Taschen der Reihe nach geoeffnet wurden. Ohne das griff der Zug ins Leere und PostAuction lief ohne Wirkung durch. Das war ein Rueckfall in den Stand vor dem 25.06.2026: die v42-Ueberarbeitung des Verkaufens hat den "originalen v41.06-Pfad" wiederhergestellt und den Fensterzug damit zurueckgeholt. Gelesen und aufgenommen wird jetzt ueber die Container-API - denselben Weg, den Taschensortierung und Sockeln schon nehmen: neue Helfer _ASBagNumSlots, _ASBagSlotInfo, _ASFindBagSlot und _ASPickupBagItem, jeweils zweigleisig ueber C_Container und die klassischen Globalen. Tasche und Platz werden beim Klick neu ueber die Item-ID aufgeloest (der beim Menueaufbau gemerkte Platz ist nur noch ein Hinweis und wird nachgeprueft), dann PickupContainerItem gefolgt von ClickAuctionSellItemButton; im Abbruchzweig raeumt ClearCursor auf, damit ein fehlgeschlagenes Aufnehmen das Item nicht am Cursor liegen laesst. Auch die Verfeinerung ueber _G[containerFrameName].info.id in der Preisvorgabe entfaellt: sie lieferte ohne dargestellte Taschen nichts, und die Item-ID aus dem Container-Durchlauf ist ohnehin die verlaessliche Quelle. Auktionshaus: Der niedrigste Preis wird nicht mehr faelschlich als 0 Kupfer gemeldet Einfach: Bei manchen Items nannte Sku als niedrigsten Sofortkaufpreis "0 Kupfer", obwohl mehrere Auktionen mit ganz gewoehnlichen Preisen im Haus lagen - eine Suche von Hand nach demselben Item fand die richtigen Preise sofort. Aus derselben Ursache war der angesagte Durchschnitt zu niedrig, die Zahl der Datenpunkte zu hoch, und der beim Verkaufen vorgeschlagene Preis konnte auf 0 stehen. Bei anderen Items hiess es umgekehrt "Keine Sofortkaufdaten vorhanden", obwohl es Sofortkaeufe gab. Beides ist behoben. Die aktuellen Preisdaten sind nach dem naechsten vollstaendigen Scan wieder richtig; gespeicherte historische Daten heilen pro Item, sobald es erneut gescannt wurde, und bis dahin werden alte Null-Preise als "keine Daten" behandelt statt vorgelesen. Technisch: SkuCore/auctionHouse.lua. Zwei Fehler, die zusammenwirkten. Erstens steuerte in AuctionBuildPriceData jede Auktionszeile immer ZWEI Datenpunkte bei, einen Gebots- und einen Sofortkaufpreis. Auktionen ohne Sofortkauf (buyoutPrice == 0, im TBC-Auktionshaus der Normalfall) wurden dabei als glatte 0 in die Sofortkaufliste geschrieben. Zweitens band die Bedingung in AuctionUpdateAuctionDBHistory - "not tLow or (tPrice > 0 and tPrice < tLow)" - den Schutz tPrice > 0 nur an den ZWEITEN Zweig. Der zuerst gesehene Preis besetzte das Minimum also unabhaengig von seinem Wert, auch mit 0; danach war kein Preis mehr kleiner als 0, das Minimum blieb also 0. Deshalb schlug es nur manchmal zu - naemlich wenn die erste Auktion dieses Items im Scan keinen Sofortkauf hatte. Die Nullen zogen ausserdem den Median nach unten, und lag mehr als die Haelfte der Auktionen ohne Sofortkauf, wurde der Median 0, worauf der Ausreisserfilter tPrice < Median * 10 samt aller echten Preise alles verwarf - das war der Fall "keine Daten trotz vorhandener Sofortkaeufe". Jetzt werden nur echte Preise > 0 ueberhaupt zu Datenpunkten (eine Auktion ohne Sofortkauf liefert schlicht keinen Sofortkauf-Datenpunkt), tPrice > 0 gilt fuer beide Zweige, und ein Median <= 0 umgeht den Ausreisserfilter, statt alles wegzufiltern. Beim Auslesen in AuctionHouseGetAuctionPriceHistoryData gilt ein gespeichertes Minimum <= 0 als "keine Daten" - noetig, weil in bereits gespeicherter AuctionDBHistory noch Null-Minima aus der alten Rechnung stehen koennen, bis das Item wieder gescannt wird. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.09 Classic Era: Spiel-Tastenbelegungen lassen sich wieder setzen Einfach: Auf dem Classic-Era-Client liess sich eine Spiel-Tastenbelegung zwar loeschen, aber nie eine neue vergeben - das Menue meldete die Taste danach einfach als "nichts". Das Belegen funktioniert jetzt genauso wie auf dem Anniversary-Client, fuer die erste wie fuer die zweite Taste eines Befehls. Technisch: Die Binding-Hilfsfunktionen in SkuCore riefen im Nicht-TBC-Zweig SetBinding(key, command, 1) auf. Das dritte Argument bindingMode wird von Era 1.15 abgelehnt, der Aufruf lieferte false und belegte nichts, waehrend die einargumentige Loesch-Form weiter funktionierte - daher "Loeschen geht, Belegen nicht". Sku.isTBC ist fuer jeden Client ab Interface 20505 wahr, dieser Zweig wurde also ausschliesslich auf Era erreicht. Alle fuenf Aufrufstellen (SetBinding, SetBinding2, DeleteBinding2 und beide Tasten in ResetBindings) nutzen jetzt die zweiargumentige Form, die auf beiden Clients korrekt ist. Classic Era: Beitritt zum Sku-Chat-Kanal schlaegt nicht mehr fehl Einfach: "Sku Chat Channel beitreten" funktionierte auf Classic Era nicht richtig - der Kanal wurde dem Chatfenster nie hinzugefuegt. Der Beitritt klappt jetzt. Technisch: SkuChat:JoinOrLeaveSkuChatChannel verzweigte ueber Sku.isTBC und rief ein globales ChatFrame_AddChannel auf, das es im Anniversary-Interface-Code gar nicht gibt. Die echte API ist ChatFrameMixin:AddChannel, die auf jeder Variante inklusive Era geladen wird - der Zweig entfaellt. "Sku Chat Channel beitreten" ist wieder auffindbar Einfach: Die Einstellung war nach Einstellungen -> Sprachausgabe verschoben worden, direkt neben die Sprachausgabe-Optionen. Weil ein zweites Menue gleichen Namens (unter Audio) nur die drei TTS-Regler zeigt, wirkte die Einstellung, als gaebe es sie gar nicht. Sie steht wieder dort, wo sie hingehoert: unter Sku Chat -> Optionen. Technisch: Gerendert mit keyPrefix "" - demselben Praefix, den das Sprachausgabe-Menue verwendet hat - damit gespeicherte Werte unveraendert uebernommen werden. Die uebrigen verschobenen SkuChat-Optionen (TTS-Stimme, -Tempo und -Lautstaerke, Audiowarteschlangen niemals zuruecksetzen, alle Sprachausgabe ueber Blizzard-TTS, Emojis nicht vorlesen) bleiben unter Sprachausgabe. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.08 Mit Dank an Naxedim Fast jede Verbesserung dieser Version wurde von den Begleit-Addons angeregt, die Naxedim unter https://naxedim.github.io/sku-addons/ entwickelt und geteilt hat - SkuMoneyReplacement, SkuMailboxReplacement, SkuAuctionHouseReplacement und SkuMinimapScannerFR. Sie wurden hier nativ in Sku uebernommen, mit Skus eigenem Menuesystem. Die Ideen und die funktionierenden Loesungen stammen von Naxedim. Post: Anhaenge, Versand und grosse Betraege Einfach: Einen Gegenstand an einen Brief anzuhaengen klappt jetzt zuverlaessig - der Gegenstand landet wirklich am Brief und bleibt nie am Cursor haengen. Ein neuer Punkt "Angehaengte Gegenstaende" zeigt, was angehaengt ist; mit ENTER schickst du einen Gegenstand in die Taschen zurueck. Kann ein Brief nicht gesendet werden (z. B. unbekannter Empfaenger), hoerst du jetzt "Senden fehlgeschlagen" mit Grund, und Empfaenger, Betreff und Text bleiben erhalten, damit du nur den Namen korrigieren und erneut senden musst. Du kannst jetzt auch mehr als 999 Gold anhaengen: jede Muenzliste hat oben einen neuen Punkt "Betrag eingeben". Technisch: Der Anhang-Pfad sucht einen freien Sende-Slot und verifiziert mit GetSendMailItem (ClearCursor bei Fehlschlag); der alte OnDropAny-Pfad ist auf Anniversary wirkungslos. MAIL_FAILED wird nun behandelt (Ansage + Entwurf bleibt), der Entwurf wird erst bei MAIL_SEND_SUCCESS geleert. Muenzlisten erhielten einen Editbox-Eintrag; die Anhang-Liste nutzt GetSendMailItem und ClickSendMailItemButton. Textfelder: jedes Zeichen wird beim Tippen und Bearbeiten vorgelesen Einfach: Wenn du in ein Sku-Textfeld tippst (Post, Auktionssuche, Betraege, Ausruestungsset-Namen usw.), hoerst du jetzt jedes getippte und jedes geloeschte Zeichen. Die Pfeiltasten lesen das Zeichen am Cursor (Strg + Pfeil das ganze Wort), Hoch/Runter den ganzen Text, und Escape sagt "Abgebrochen". Technisch: SkuOptions:EditBoxShow liest jetzt ueber OnChar/OnKeyDown (UTF-8-sicher). Getippte Zeichen werden in die Queue gehaengt, damit schnelles Tippen auf langsamen Stimmen jedes Zeichen spricht; Cursor-Lesen ueberschreibt. Schlichte Pfeile sind frei (Menue-Navigation liegt auf Umschalt-Pfeilen). Auktionshaus: Addon-Tooltip-Infos, keine haengenden Tasten, Item-Namen in jeder Sprache Einfach: Item-Tooltips im Auktionshaus zeigen jetzt auch Infos, die andere Addons hinzufuegen (z. B. Pawn-Wertungen), als zusaetzliche Sektion "Addon-Infos" am Ende - ohne Skus eigenen Tooltip zu veraendern. Das Schliessen des Auktionshauses laesst Enter und Escape nicht mehr haengen (Escape oeffnet wieder das Spielmenue). Im Strategiekauf kannst du den Item-Namen jetzt in deiner eigenen Sprache tippen. Technisch: AuctionBuildItemTooltip bespielt einmal unsichtbar den echten GameTooltip, liest die Zeilen fremder OnTooltipSetItem-Hooks und haengt die Nicht-Basiszeilen als Sektion an (der SkuScanningTooltip wird nicht umgehaengt). Beim Menue-Schliessen werden die Override-Bindings des Kauf-Binders und beider Menue-Buttons mehrfach geleert (nur bei geschlossenem Menue / ausser Kampf). Der Strategiekauf erhielt eine Freitext-Eingabe (Sku liefert nur deutsche/englische Namenstabellen). Komplettscan 250 -> 400 Zeilen pro Frame. Gildenbank: Gold lesen und bewegen Einfach: Das Gildenbank-Menue hat einen neuen Punkt "Gildenbank-Geld": lies, wie viel Gold in der Bank ist, wie viel du heute noch abheben kannst und wie viel du bei dir traegst, und zahle Gold ein oder hebe es ab, indem du einen Betrag eingibst. Ein- und Auszahlungen werden vorher geprueft (genug Gold, Tageslimit) und per Stimme bestaetigt. Technisch: Das Geld-TODO in Build_GuildBankFrame ist mit rohen Gossip-Eintraegen gefuellt; Ein-/Auszahlung nutzt die GetGuildBankWithdrawMoney-Limitpruefung und sagt die Vorher/Nachher-Differenz an. Handel: das Handelsfenster-Geld wird vorgelesen Einfach: Beim Handeln sagt Sku jetzt an, wenn der andere Spieler Gold in den Handel legt, es aendert oder zurueckzieht, und liest dein eigenes Angebot vor, waehrend du es einstellst. (Gold aus einem Addon in einen Handel zu LEGEN ist von Blizzard gesperrt, daher nur die Lese-Seite.) Technisch: TRADE_MONEY_CHANGED wird ueber den Dispatcher behandelt; eigenes und Partner-Geld werden gegen die letzten Werte verglichen und mit Partnernamen angesagt. Ressourcen-Scanner: native franzoesische Knotennamen Einfach: Der Minimap- und Boden-Ressourcenscanner kennt jetzt die franzoesischen Namen von Erzadern, Kraeutern, Gaswolken und Truhen und funktioniert damit nativ auf einem franzoesischen Spielclient. Technisch: frFR-Ressourcennamen wurden zu SkuCore.RessourceTypes ergaenzt und frFR zu Sku.LocsPartly, damit Sku.LocP auf einem frFR-Client frFR bleibt, mit enUS-Fallback. Navigation: ein Flugmeister-Flug bricht eine aktive Route ab Einfach: Wenn du bei einem Flugmeister einen Flug nimmst, waehrend gerade eine Route verfolgt wird, wird die Route jetzt automatisch abgebrochen - sie beizubehalten ergibt keinen Sinn, waehrend der Taxiflug dich woandershin bringt. Selbst auf einem Reittier zu fliegen oder ein Flugfahrzeug zu steuern bricht die Route nicht ab. Technisch: Der Taxi-Start-Zweig (PLAYER_CONTROL_LOST gefolgt von PLAYER_MOUNT_DISPLAY_CHANGED) ruft jetzt SkuNav:CancelNavigationSilent auf, abgesichert mit UnitOnTaxi("player"), damit es nur bei Flugmeister-Fluegen ausloest - Selbstfliegen loest nie PLAYER_CONTROL_LOST aus, und in einem Flugfahrzeug bleibt UnitOnTaxi false. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.07 AddOn-Einstellungen: Einstellungen anderer Addons lesen und aendern Einfach: Ein neuer Punkt "AddOn-Einstellungen" im Addons-Menue (und ueber den Knopf "AddOns" im Escape-Spielmenue) macht die Einstellungen anderer Addons mit dem Screenreader lesbar und aenderbar - Questie, Deadly Boss Mods, AtlasLoot, Extended Character Stats und weitere. Ihre Optionen erscheinen als normale Sku-Menues: Ein/Aus-Schalter, Auswahllisten, Schieberegler und Textfelder. Laesst sich im Features-Menue abschalten. Technisch: SkuCore/addonOptions.lua liest die AceConfig-Optionstabelle eines beliebigen Addons ueber die prozessweite AceConfigRegistry (IterateOptionsTables / GetOptionsTable) mit AceConfig-Vererbungssemantik und stellt sie mit denselben Menueformen wie gameOptions.lua dar. Kuratierte oberste Liste; Konfig-Addons, die nur bei Bedarf laden, werden beim Oeffnen geladen. Fuer Deadly Boss Mods eigene Adapter: Optionen je Boss-Mod aus DBM.Mods sowie die Kernoptionen ueber einen DBM-GUI-Widget-Durchlauf. Entfernungspruefung: Baender bleiben erhalten und sind schnell verfuegbar Einfach: Bei den Entfernungsansagen (den "Entfernung"-Pruefungen) gab es einen Fehler, durch den eingestellte Entfernungsbaender sich selbst abschalten konnten und die Liste leer erscheinen konnte. Behoben: eingestellte Baender bleiben erhalten, die Liste fuellt sich zuverlaessig, und neu verfuegbare Baender werden angesagt. Nach einem frischen Login sind die Baender ausserdem deutlich schneller bereit, und das 100-Yard-Band funktioniert auf TBC wieder. Hinweis: Sie hoeren jetzt deutlich mehr Entfernungsansagen als gewohnt, weil jedes verfuegbar werdende Band angesagt wird - unerwuenschte koennen Sie unter Monitor -> Entfernung abschalten. Technisch: RangeCheck entfernt gespeicherte Baender nicht mehr anhand voruebergehender LibRangeCheck-Verfuegbarkeit; das Menue fuellt sich synchron beim Aktivieren mit zeitlich gestaffelten stillen Wiederholungen und aktualisiert aus der laufenden Bibliothek. LibRangeCheck-3.0 wurde von v31 auf v35 aktualisiert (Zauber-Baender aktualisieren sich beim Leveln via LEARNED_SPELL_IN_TAB). Ein paralleles Vorwaermen der Item-Daten beim Aktivieren fuellt Item-Baender im Schwung statt seriell. Fuenf permanente DM-Elixiere wurden in die TBC-100er-Tabellen ergaenzt, damit sich das 100-Band bildet. Ein Kampf-Schutz ueberspringt nicht angreifbare Ziele, deren Interaktionsdistanz-Pruefer im Kampf falsche Werte liefern. Fokus: Aenderungen des Spiel-Fokus werden vorgelesen Einfach: Das Festlegen oder Entfernen des Spiel-Fokus wird jetzt per Stimme angesagt ("Fokus festgelegt auf " / "Fokus entfernt"). Die acht Sku-Fokus-Tastenbelegungen und ihre Menuegruppe heissen jetzt "Sku Fokus", damit sie klar vom Spiel-eigenen Fokus zu unterscheiden sind. Das Festlegen eines Sku-Fokus sagt die Bestaetigung nicht mehr doppelt. Technisch: PLAYER_FOCUS_CHANGED laeuft ueber die Blizzard-TTS (Engine 2, globale Stimme des Nutzers) und ist mit dem SkuFocus-Modulschalter registriert. Die "Set"-Taste reagiert nur noch auf AnyDown (vorher AnyUp+AnyDown, wodurch sie auf beiden Tastenflanken ausloeste). Menue: ueberfluessiger Ton beim Oeffnen/Schliessen entfernt Einfach: Beim Oeffnen oder Schliessen des Menues wurde manchmal ein zusaetzlicher "Aus"-Ton aus einer internen Aufraeumung abgespielt. Jetzt ertoent nur noch das Menue-Wisch-Geraeusch; alle anderen Aktionen behalten ihren gewohnten Ton. Technisch: SkuTTS:Hide bekam einen Still-Schalter, den der Menue-Auf/Zu- Umschalter nutzt, um den sound-off2-Ping aus dem defensiven Ausblenden eines uebrig gebliebenen Lese-Frames zu unterdruecken. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.06 Verzauberkunst: Absturz beim Oeffnen des Fensters behoben Einfach: Das Verzauberkunst-Fenster konnte beim Oeffnen einen Fehler ausloesen. Das ist behoben. Technisch: Die in 42.05 ergaenzten Craft-Menuepunkte (Filter und Tooltip) sind jetzt vollstaendig pcall-geschuetzt, sodass unerwartetes API-Verhalten auf diesem Backport das Menue nicht mehr crasht. Auktionshaus: klarere Ansage beim Scan-Start Einfach: Beim Starten des Auktionshaus-Scans wird jetzt "Auktion gestartet, bitte warten" gesagt. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.05 Berufe: Rezept-Tooltip mit Shift+Pfeil-runter (alle Berufe) Einfach: Steht der Fokus in der Rezeptliste auf einem Rezept, liest Shift+Pfeil-runter jetzt einen Tooltip vor: Name des Ergebnisses, die Materialien je Zeile als "vorhanden Schraegstrich benoetigt", und den Tooltip des fertigen Gegenstands. Er zeigt das FOKUSSIERTE Rezept, auch wenn gerade ein anderes ausgewaehlt ist. Gilt fuer alle normalen Berufe und fuer Verzauberkunst. Der bisherige Tooltip auf dem ausgewaehlten Rezept bleibt erhalten. Technisch: Jede Rezeptzeile traegt ihren echten Index (Knopf-GetID). Der Tooltip wird ueber diesen Index aus GetTradeSkillReagentInfo bzw. GetCraftReagentInfo (vorhanden/benoetigt) und dem Ergebnis-Item-Link gebaut, ohne die Auswahl zu veraendern. Berufe: Filter "Ressourcen vorhanden" (alle Berufe) Einfach: Ganz oben im Berufefenster ein Umschalter. Enter schaltet Ein/Aus und sagt den neuen Zustand. Bei Ein bleiben nur herstellbare Rezepte in der Liste. Standard Aus, gemerkt pro Beruf und Charakter. Die Tierausbildung bekommt keinen Filter (dort gibt es keine Materialien). Technisch: Normale Berufe ueber Blizzards TradeSkillOnlyShowMakeable; Verzauberkunst filtert selbst ueber GetCraftInfo.numAvailable. Auren-Sets: accountweit verfuegbar Einfach: Angelegte und empfangene Auren-Sets stehen jetzt auf allen Charakteren des Accounts zur Verfuegung, nicht mehr nur auf einem. Technisch: Speicher von char- auf global-Scope umgestellt; der Login-Reset der globalen SkuAuras-Tabelle leert jetzt nur noch das Debug-Log und erhaelt die Sets und empfangenen Sets. Auren-Sets: Umbenennen und Aktivieren Einfach: Im Untermenue eines Sets gibt es jetzt zusaetzlich Umbenennen und Aktivieren. Aktivieren ersetzt die aktuellen Auren durch die des Sets und fragt vorher nach (Enter bestaetigt, Escape bricht ab). Auren-Menue aufgeraeumt Einfach: Der tote Punkt "Auren Sets importieren" ist entfernt. Die alte Set-Verwaltung mit den drei Test-Sets ist raus. Der Teilen-Punkt heisst jetzt "Set Verwaltung". Auren: Absturz beim Anlegen einer neuen Aura behoben Einfach: Beim Anlegen einer neuen Aura (neue Aura, wenn, dann, nach rechts auf Aktion) kam ein Fehler. Er ist behoben. Duale Talentspezialisierung: Umskillen ohne Reload Einfach: Nach dem Wechsel der aktiven Spezialisierung wird der Talentbaum sofort korrekt angezeigt; ein /reload ist nicht mehr noetig. Technisch: Beim ACTIVE_TALENT_GROUP_CHANGED wird der Blizzard-Talentrahmen auf die neue aktive Gruppe gezogen und neu gezeichnet, bevor Sku sein Menue baut. Talent: richtige Namen der Registerkarten in der inaktiven Spezialisierung Einfach: In der nicht aktiven Spezialisierung hiessen die Talentbaeume bei manchen Klassen "Registerkarte 201", "281" und aehnlich statt richtig. Jetzt stehen die echten Baumnamen. Technisch: Name vom Blizzard-Reiterknopf PlayerTalentFrameTab statt vom gruppen-parametrisierten API-Wert, mit Zahl-Fallback. Trainer: Preis im Bestaetigungsdialog Einfach: Beim Zuruecksetzen der Talentpunkte, beim Kauf der dualen Talentspezialisierung und bei anderen Gold-Bestaetigungen steht jetzt oben ein Eintrag "Kosten" mit dem Goldbetrag. Technisch: Der StaticPopup-Leser nimmt jetzt StaticPopup1MoneyFrame.staticMoney als ersten Kind-Eintrag mit auf (ueber SkuGetCoinText). Questie: Chatmitteilungen fernbedienen Einfach: Unter Addons gibt es jetzt Questie (wenn Questie geladen ist). Dort laesst sich der Kanal der Chatmitteilungen einstellen (Aus / Gruppe / Schlachtzug / Beides) und einzeln an- und ausschalten: Quest angenommen, abgebrochen, Fortschritt, abgeschlossen, Quest-Gegenstand. Technisch: Setzt Questie.db.profile.questAnnounce* direkt; Questie persistiert selbst. Begleiter: nicht verwendete Trainingspunkte werden angezeigt Einfach: Auf der Uebersichtsseite stand bei den Trainingspunkten des Begleiters immer 0. Jetzt steht dort die echte Zahl. Technisch: GetPetTrainingPoints statt UnitCharacterPoints("pet") (TBC hat keine Pet-Talentpunkte). Freundesliste: "Entfernen" ganz nach unten Einfach: Im Untermenue eines Freundes steht "Entfernen" jetzt als letzter Eintrag statt weit oben. Monitor: "Tier Hunger ansagen" richtig einsortiert Einfach: Der Punkt lag eine Ebene zu tief. Er liegt jetzt unter Monitor, Gesundheit und Status, Tier, als Geschwister von Gesundheit. Post: Schluesselbund-Gegenstaende anhaengbar Einfach: Beim Brief verfassen zeigt "Gegenstand hinzufuegen" jetzt auch Gegenstaende aus dem Schluesselbund (z.B. einen nicht seelengebundenen Silberdietrich) und laesst sie versenden. Seelengebundene Schluessel bleiben ausgeblendet. Die Schluesselbund-Eintraege stehen am Ende der Liste, die Tascheninhalte davor. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.04 Taschen: Verzauberungen und Ruestungssets per Linksklick anwenden geht wieder Einfach: Wartete eine Verzauberung oder ein Ruestungsset auf ein Ziel-Item, passierte beim Druck auf Enter (Linksklick) auf dem Ziel-Item in den Taschen nichts - nur Strg+Enter (Rechtsklick) wendete an. Enter wendet jetzt an, wie in der Standard-UI. Auf angelegten Gegenstaenden funktionierten beide Tasten bereits. Technisch: Die Enter-Aktion eines Taschen-Items war ein blankes insecure PickupContainerItem; der native Linksklick laeuft bei SpellCanTargetItem() ueber das Hardware-Event-gegatete UseContainerItem. Taschen-Items und Ausruestungs-Slots tragen jetzt ein applyMacrotext ("/use Tasche Slot" bzw. "/use Slot"), das das Menue beim Fokussieren waehrend SpellIsTargeting() auf den sicheren Linksklick-Button staged; ein Targeting-only-PreClick-Schnappschuss laesst den insecure Fallback sein Aufheben ueberspringen, wenn das Makro schon angewendet hat, ohne das Ablegen/Tauschen eines gehaltenen Cursor-Items zu brechen. Die /use-Form ist zudem Modifier-unabhaengig - ein synthetisierter "/click ... LeftButton" liest den Live-Tastaturzustand, eine umbelegte Linksklick-Taste mit Modifier wuerde also als modifizierter Klick zaehlen (Anprobe/Chat-Link) und nie anwenden. Startgebiete: Strg+Shift+Tab wechselt wieder durch geschuetzte NPCs Einfach: Seit dem WoW-Client-Update vom 9. Juli wechselte die Spezialtaste Strg+Shift+Tab nicht mehr durch die geschuetzten (sonst nicht anvisierbaren) NPCs in den Startgebieten - der Druck hob nur noch das Ziel auf. Sie funktioniert wieder. Technisch: Client-Build 2.5.6.68575 hat die CVar nameplateShowFriends entfernt (aufgeteilt in nameplateShowFriendlyPlayers + nameplateShowFriendlyNpcs). GetCVar auf den entfallenen Namen liefert nil ohne Fehler, Skus Zwangs-Einschalten lief also stumm ins Leere, freundliche Plaketten erschienen nie und das Namens-Repo hinter SkuCoreSecureTabButton blieb leer. Ein neuer gecachter Resolver SkuCore.FriendlyNameplateCVars() waehlt den CVar-Satz je Client (der Era-Client behaelt den alten Sammelnamen) und wird vom Zwangs-Einschalten des Wechslers, der Login-CVar-Basis und dem Kamera-Menue genutzt (der Umschalter fuer freundliche Plaketten setzt jetzt eine CVar-Liste). Navigations-Menue: verflacht, Shift+F9/F10-Schnelllisten ueberarbeitet Einfach: Die Eintraege liegen jetzt direkt unter Navigation (Einheiten Route oben, dann Direkter Wegpunkt - umbenannt von "Auswaehlen" -, Besuchte loeschen, Schnellwegpunkt setzen); die alten Huellen "Wegpunkt" / "Route folgen" und die doppelten Eintraege "Alles abwaehlen" / "Abwaehlen" sind weg (Shift+F12 bricht die Navigation bereits lautlos ab). Die Navigations-Einstellungen sind aus dem Nav-Menue ausgezogen: allgemeine Einstellungen nach Einstellungen -> Navigation, Beacon-Einstellungen nach Monitor -> Beacon. Shift+F9 / Shift+F10 oeffnen die Listen der nahen Wegpunkte / nahen Routenziele direkt, und LINKS aus so einer Schnellliste wechselt in das vollstaendigere Menue, das sie abkuerzt. Technisch: Die Schnelltasten nutzen einen eigenen Handler plus transienten Root-Eintrag (wie der Shift+F11-Aktionsleisten-Handler) statt des fragilen lokalisierten SlashFunc-Label-Laufs; gemeinsame Listen-Builder auf SkuNav-Modulebene gehoben; die veralteten MenuQuickSelect1-4-Pfad-Defaults sind stillgelegt und die funktionslose "Schnellwahl"-Einstellungsgruppe ist versteckt. Gleiche args/db, gespeicherte Werte bleiben erhalten. AtlasLoot-Berufe: Classic- und TBC-Rezepte in einer Liste Einfach: Im AtlasLoot-Berufemenue erschien jeder Beruf doppelt (z.B. "Verzauberkunst" fuer Classic und noch einmal fuer TBC), und eine Kategorie wie Armschienen-Verzauberungen zeigte nur die Rezepte einer Aera. Jeder Beruf ist jetzt ein einzelner Eintrag, und jede Kategorie listet die Rezepte beider Aeren, sortiert nach benoetigtem Skill. Technisch: Der Berufe-Zweig fuehrt auf zwei Ebenen zusammen: Crafting-Module werden nach lokalisiertem Berufsnamen gruppiert (Enchanting + EnchantingBC -> ein Eintrag), dann werden gleichnamige Kategorien ueber die Module hinweg vereinigt und das Blatt rendert die Rezepte beider Module nach Skill sortiert. WotLK-Module sperren sich selbst auf den WotLK-Client, die TBC-Phase ergibt also genau Classic + BC. Briefkasten: getippte Feldinhalte werden zuverlaessig vorgelesen Einfach: Nach dem Eintippen von Empfaenger, Betreff oder Text in ein Brieffeld wurde die Bestaetigung (z.B. "Empfaenger: Spielername") mit der Sku-Audio-Stimme gesprochen, die freien Text wie Spielernamen nicht sprechen kann - die Zeile blieb stumm oder unvollstaendig. Die Bestaetigung nutzt jetzt immer die Blizzard-TTS-Stimme. Technisch: Die MailEditor-Bestaetigungen uebergeben engine 2 (Blizzard-TTS) an OutputStringBTtts statt des Standard-Audiodatenbank-Pfads. Klassenlehrer: Fokus bleibt auf "Ausbilden" Einfach: Ein Druck auf "Ausbilden" beim Klassenlehrer sprang mit dem Fokus an den oberen Rand des Fensters. Er bleibt jetzt auf dem Ausbilden-Knopf, nachdem sich die Liste beruhigt hat - mehrere Faehigkeiten hintereinander lernen ist damit je ein Tastendruck. Technisch: Das Re-Pinnen nach dem Ausbilden suchte den Knopf in den KINDERN des fokussierten Eintrags statt in dessen Geschwistern; der Fenster-Neuaufbau verankert per Index, daher traf es nie. Es durchsucht jetzt die Ebene, auf der der Cursor steht (parent.children, dann children), und das zwischenzeitliche CheckFrames laeuft stumm, sodass nur die Endposition angesagt wird. Flugmeister: "Schliessen" wird nicht mehr gelistet Einfach: Das Flugmeister-Fenster listete einen Eintrag "Schliessen". Sku listet Schliessen-Knoepfe nirgends (Escape schliesst jedes Fenster), daher ist er weg. Technisch: Das "Schliessen"-Label haengte der Fallback fuer Knoepfe ohne Schriftzug automatisch an den namenlosen TaxiCloseButton. "Schliessen" steht jetzt in blockedWidgetStrings, generisch gespiegelte Fenster lassen Schliessen-Knoepfe damit aus wie die handgebauten Fensterspiegel schon immer. Menues umsortiert Einfach: "Sku Menue im Kampf" ist von Monitor -> Kampf in ein wieder eingefuehrtes Untermenue Einstellungen -> Kampf gezogen. "Tier Hunger ansagen" liegt jetzt unter Monitor -> Tier -> Gesundheit. Das Auren-Menue hat seine doppelte Ebene verloren: einmal RECHTS vom Auren-Eintrag landet direkt auf "Neue Aura" (der funktionslose Eintrag "Optionen" ist weg). Technisch: Gleiche Einstellungen und Speicherung (combatMenuOpen, classes.hunter.petHappyness) - nur die Menueposition hat sich geaendert. SkuAuras:MenuBuilder baut die Liste direkt in den Modul-Root-Eintrag; die SlashFunc-Ankerpfade haben das aurenList-Segment verloren. Dokumentation: Hinweise zur Standard-Tastenbelegung korrigiert Einfach: Die Hilfedateien "Standard-Tastenbelegung fuer blinde Spieler" (Deutsch, Englisch, Franzoesisch) nannten mehrere veraltete Standardtasten. Korrigiert: Kraeuter-/Erz-Scan ist Strg+Shift+F / Strg+Shift+R, einen Beacon vor/zurueck ist Strg+Shift+W / Strg+Shift+S, Schnellwegpunkte sind Shift+F5 bis Shift+F8, zum Beacon drehen ist I. Die README verweist jetzt auf die aktuelle Download-Seite, die diese Hilfedateien und die Patch Notes auch direkt verlinkt. Technisch: Gegen skuDefaultKeyBindings in SkuZOptions/SkuKeyBinds.lua geprueft; die Website-Kopien unter docs/ tragen dieselben Korrekturen. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v42.03 Bankfenster: Item-Namen und Rechtsklick wiederhergestellt Einfach: Bankplaetze zeigten "Leer", obwohl ein Gegenstand drin lag, und ein Rechtsklick auf einen Bankplatz tat nichts. Bankplaetze lesen jetzt wieder ihren Item-Namen vor, und Rechtsklick (Strg+Enter) legt den Gegenstand in die Taschen. Technisch: Die Container-API-Umstellung las Namen ueber GameTooltip:SetBagItem, das fuer den Bank-Hauptcontainer (id -1) auf 2.5.6 nichts liefert; ein Hyperlink-Fallback (SetHyperlink via GetContainerItemLink) stellt den Namen wieder her. Der Bank-Rechtsklick nutzt jetzt ein unsicheres UseContainerItem (Bank-Bewegungen sind nicht hardware-gated) mit Event-basiertem Refresh auf BAG_UPDATE_DELAYED. Taschen sortieren und aufraeumen: neu gebaut, keine Fehlerschleifen mehr Einfach: Sortieren oder Aufraeumen konnte interne Taschenfehler ausloesen, Gegenstaende verlegen oder sich endlos aufhaengen. Das Sortieren ist neu geschrieben und zuverlaessig, braucht die Taschen nicht mehr offen, und "alle Taschen sortieren" funktioniert. Technisch: Der Klick-Simulations-Bubblesort (Coroutine auf 0.01s-Ticker) ist durch eine C_Container-Engine ersetzt: PickupContainerItem-Tausch, Selectionsort (garantiertes Ende), ein Tausch pro BAG_UPDATE_DELAYED mit Watchdog und Schrittlimit je Tasche, alles pcall-geschuetzt und getract. Behebt zusaetzlich einen Talentfenster-Absturz ("table index is nil"). Fehler-Feedback: pro Fehler waehlen, wie er gemeldet wird Einfach: Jeder Fehlertyp (nicht in Reichweite, betaeubt, falsche Richtung, unterbrochen, keine Sichtlinie, ...) hat jetzt ein eigenes Untermenue, in dem du waehlst, wie er angesagt wird: eine TTS-Stimme, ein gesprochener Sprachhinweis (Marlene oder Hans, deutsch oder englisch), ein kurzer Ton oder Stille. Die alten gesprochenen Hinweis-Clips sind wieder waehlbar. Technisch: SkuCore\UIErrors.lua bekommt einen verschachtelten Menuebauer (analog zu den Chat-Stimmen pro Kanal); der Wert bleibt ein einzelner String ("voice" / "voice#" / Clip-Pfad / Ton-Pfad / silent), bestehende Einstellungen bleiben erhalten. OutputError decodiert "voice#" und gibt den Stimmindex an OutputStringBTtts; die Fokus-Vorschau spielt die Auswahl an. Menues umsortiert Einfach: Neues Menue "Werkzeuge" mit Dial Targeting und Soft Targeting. Der Monitor enthaelt jetzt zusaetzlich Entfernung, Fallerkennung, Fehler-Feedback, Ziel-Optionen und Quest-Benachrichtigungen. Das Audio-Menue ist verschlankt. Das alte Menue "Barrierefreiheit" heisst jetzt "Schnellmenue". Technisch: Verschiebungen in SkuZOptions/SkuMenu und SkuCore\aq.lua MonitorMenuBuilder; RangecheckMenuBuilder fuer Wiederverwendung freigelegt; das nun leere Kampf-Untermenue entfernt; gleiche db/keyPrefix, daher bleiben gespeicherte Werte erhalten. Gruppenmitglieder-Quests: kein Absturz mehr bei Fortschritt Einfach: Das Oeffnen einer Quest eines Gruppenmitglieds mit Zielfortschritt fuehrte manchmal zu einem Fehler und brach das Vorlesen ab. Sie oeffnet jetzt zuverlaessig. Technisch: Der Gruppenmitglieder-OnEnter haengte an die Sektionen-TABELLE aus GetQuestDataStringFromDB an; er baut jetzt eine echte Sektionentabelle (Live-Fortschritt zuerst) wie der eigene Questpfad. Installer: funktioniert hinter geteilten / VPN-Verbindungen Einfach: Der Installer konnte mit "rate limit exceeded" scheitern, bevor ueberhaupt ein Download begann, bei geteilten oder VPN-Verbindungen. Das passiert jetzt nicht mehr. Technisch: Die api.github.com-Release-Abfrage (Limit 60/h/IP) entfaellt; die (Tag, Dateiname)-Paare sind in Config gepinnt und direkte github.com/.../releases/download-URLs werden gebaut. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.06 Freundesliste: "Einladen" funktioniert wieder Einfach: Im Fenster Freunde liess sich ein Freund nicht einladen (Fehlerton). Jetzt klappt die Einladung wieder, auch fuer Battle.net-Freunde. Technisch: InviteUnit ist in 2.5.5 keine globale Funktion mehr; der normale Freund-Zweig (SkuCore\friends.lua) nutzt jetzt C_PartyInfo.InviteUnit mit Fallback, wie der Battle.net-Zweig. Auren-Sets teilen: besser bedienbar Einfach: "Sets (teilen)" steht jetzt an 3. Stelle (unter Neue Aura und Auren verwalten). "Set aus aktuellen Auren anlegen" heisst jetzt "Neues Set aus aktuellen Auren erstellen". Beim Anlegen kann der Name jetzt direkt getippt werden (vorher ging nur Einfuegen). Die Ansage ist auf "Set angelegt" vereinfacht, da der frei gewaehlte Name nicht vertonbar ist. Technisch: SkuAuras\sharing.lua nutzt jetzt SkuOptions:EditBoxShow (mit Tastatur-Fokus) statt EditBoxPasteShow; Menue-Reihenfolge in SkuAuras\Options.lua angepasst; Ansage nur einmal. Auren-Sets teilen: "Set loeschen" funktioniert jetzt zuverlaessig Einfach: Beim Loeschen eines Sets blieb der Eintrag manchmal stehen und das naechste Enter machte nur einen Fehlerton. Jetzt wird das Set geloescht, das Menue springt zurueck zur Set-Liste und baut sie neu auf. Technisch: Nach SetsDelete navigiert das Menue zurueck auf "Sets (teilen)" und ruft OnSelect / VocalizeCurrentMenuName (SkuAuras\sharing.lua); Ansage auf "Set geloescht" vereinfacht. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.05 Gegnerstatus Kampf: Kampf/passiv beim Anvisieren (Aus / Beep / Ansage) Einfach: Neuer Punkt unter Barrierefreiheit, Sonstiges: "Gegnerstatus Kampf". "Beep" (Standard) ist das bisherige Verhalten - ein Ton vor dem Gegnernamen, wenn der Gegner mit dir oder deiner Gruppe kaempft. "Ansage" behaelt den Ton und sagt zusaetzlich "im Kampf" bzw. "passiv" vor dem Namen. "Aus" schaltet Ton und Statusansage ab. Der Durchschalt-Knopf bleibt unveraendert. Technisch: In SkuMob\Core.lua (PLAYER_TARGET_CHANGED) wird der vorhandene InCombatSound nur noch gespielt, wenn der Modus nicht "aus" ist; im Modus "Ansage" wird "im kampf" analog zum vorhandenen "passiv" vor den Namen gehaengt. Neuer DB-Wert profile.SkuMob.enemyCombatStatusMode (off/beep/announce, Standard beep -> bestehende Charaktere unveraendert). Menue in SkuZOptions\Core.lua, Locale "im kampf" in deDE/enUS. Reiner Ansage-Code, kein Taint. Stabilitaet: Absturz beim freundlichen Lebens-/Heil-Monitor behoben Einfach: Der Fehler "fatality", der auftreten konnte, wenn man im Kampf auf sich selbst oder einen Begleiter wechselte (bei aktiver Option "eingehende Heilung einrechnen"), ist behoben. Die Lebensansagen laufen normal weiter. Technisch: In SkuCore\aq.lua holte UNIT_HEALTH den Wert UnitGetIncomingHeals(unit, "player") ohne nil-Absicherung; bei fehlender eingehender Spielerheilung (Normalfall) ergab die Subtraktion "Zahl minus nil" einen Lua-Fehler. An vier Stellen "or 0" ergaenzt. Stabilitaet: seltener Menue-Fehler (Core.lua:4021) behoben Einfach: Ein Fehlerton, der ganz selten beim Navigieren in bestimmten Menue- Zustaenden (z.B. offene Chatzeile per Strg+Enter, dann Pfeil) auftrat, ist weg. Technisch: In SkuOptions:VocalizeMultipartString lief eine Debug-Brotkrumen-Schleife "while tTable.parent.name do" ohne nil-Schutz; an einem Wurzelknoten ohne parent -> "attempt to index field 'parent'". Guard ergaenzt (tTable und tTable.parent geprueft). Reiner Debug-Pfad, keine Funktionsaenderung. Folgen-Warnung: kein faelschliches "Folgen beendet" beim erneuten Folgen-Druck Einfach: Wenn du beim Folgen die Folgen-Taste erneut druckst (um es zu pruefen), unterbricht WoW das Folgen kurz und baut es sofort neu auf. Vorher kam dabei faelschlich "Folgen beendet". Jetzt bleibt es in diesem Fall beim normalen Bling; "Folgen beendet" kommt nur noch bei einem ECHTEN Abbruch. Technisch: Die Ansage bei AUTOFOLLOW_END wird um 0,4 s verzoegert und unterdrueckt, wenn in der Zwischenzeit ein AUTOFOLLOW_BEGIN kommt (Wieder-Folgen). Generation- Zaehler gegen veraltete Timer. In SkuCore\visualAids.lua. Fix: "Ton fuer Klick bei Beacons" - Menue war manchmal leer (Navigation, Optionen) Einfach: Die Auswahl des Klick-Tons (Beep/Click) war manchmal leer und nicht umstellbar (der An/Aus-Schalter ging trotzdem). Grund war ein Ladereihenfolge- Rennen: die Klick-Toene kommen aus dem Zusatz-Addon SkuBeaconSoundsets und werden erst beim Betreten der Welt registriert - Sku baute die Liste aber manchmal schon vorher (leer) auf. Jetzt wird die Liste kurz nach dem Laden zuverlaessig nachgebaut. Technisch: Additiver, verzoegerter Nachzieher in SkuNav\Options.lua (NICHT in der geschuetzten SkuNav\Core.lua): auf PLAYER_ENTERING_WORLD + C_Timer.After baut er SkuNav.ClickClackSoundsets neu aus BeaconLib:GetClickClackSoundSets() und zeigt die Auswahl (clickClackSoundset.values) darauf um. pcall-geschuetzt, No-Op falls SkuBeaconSoundsets fehlt. WICHTIG: ist SkuBeaconSoundsets deaktiviert/fehlt, bleibt die Liste leer (dann fehlen auch die Beacon-Sounds) - haeufige Ursache von "Audioproblemen" bei Nutzern. Details: Heute\Diagnose - Klick bei Beacon Tonmenue leer.txt. Maus: alternative Steuerung ("zum Ziel laufen") sauber abschaltbar + Schalter im Menue Einfach: Im Barrierefreiheitsmenue unter Sonstiges gibt es jetzt den Schalter "Bei Interagieren zum Ziel laufen". Sehende koennen die automatische Lauf-bei-Klick-Steuerung damit abschalten; sie stoert die normale Maus nicht mehr. Technisch: Der WorldFrame-Maushandler wird nicht mehr per SetScript ueberschrieben, sondern additiv per HookScript GENAU EINMAL installiert (Guard-Flag, nicht im 100ms-Pfad) und tut nichts, solange interactMove aus ist. Schalter ueber den vorhandenen Options-Knoten in die Barrierefreiheit (Sonstiges) eingehaengt. Plaketten an die Kamera gekoppelt Einfach: Die freundlichen Plaketten werden nur noch erzwungen, solange in der Kamera der SkuStandard aktiv ist. Bei freigegebenem Kameramenue kannst du die Plaketten selbst veraendern oder ausschalten. Technisch: Der Zwang nameplateShowFriends=1 im OnUpdate-Loop wird nur noch angewendet, wenn cameraOptions.skuStandard ~= false (reiner Read mit voller and-Kette, Kampf-Gate bleibt erhalten). Neu: Schwarzer Lesebalken (Barrierefreiheit, fuer Sehbehinderte) Einfach: Ein schwarzer Balken am oberen oder unteren Bildschirmrand zeigt gross und kontrastreich NUR den aktuellen Menuepunkt (nicht den ganzen Pfad), der gerade vorgelesen wird. Nur sichtbar, wenn das Menue offen ist. Standard AUS. Im neuen Menuepunkt Barrierefreiheit, Visuelle Hilfen, kannst du ihn ein- und ausschalten und Schriftgroesse (bis sehr gross; groesser wird auch fetter), Position (oben/unten) und Deckkraft einstellen. Lange Zeilen laufen rechts heraus - das ist gewollt. Korrektur: bei sehr grosser Schrift waechst der Balken jetzt nach UNTEN (Text war oben abgeschnitten); er wird nicht mehr oben am Bildschirmrand abgeschnitten. Technisch: Neues nicht-secure FontString-Frame an UIParent (EnableMouse(false), kein Taint), gespeist aus SkuOptions.currentMenuPosition.name (nur die aktuelle Zeile), event-getrieben (kein OnUpdate, nicht im 100ms-Loop), Text NACH der Sprachausgabe gesetzt. Schrift via SetFont mit THICKOUTLINE ab mittlerer Groesse (Fettung). FontString jetzt an TOPLEFT verankert (JustifyV TOP), Balkenhoehe px+40%+12, damit grosse Schrift nach unten waechst statt am oberen Rand abzuschneiden. Logik isoliert in SkuCore\visualAids.lua; Werte pro Profil unter db.profile.SkuCore.visualAids.lineBar. Neuer Menuepunkt "Visuelle Hilfen". Neu: Plaketten-Farben (Barrierefreiheit, fuer Sehbehinderte) Einfach: In Barrierefreiheit, Visuelle Hilfen, Plaketten-Farben kannst du die Plaketten nach Reaktion einfaerben (Feind, Neutral, Freund), jede Farbe selbst waehlen, dazu Modus (nur Ziel oder alle Plaketten), Groesse und Deckkraft. Standard AUS. Ein Warnhinweis erklaert, dass die Farben reine Anzeige sind. Technisch: Eigene Funktion in SkuCore\visualAids.lua, eigener Opt-in-Flag (nicht testMode), ereignisgesteuert (NAME_PLATE_UNIT_ADDED/REMOVED, PLAYER_TARGET_CHANGED), kein C_Timer-Fan-out, nicht im 100ms-Loop, keine TOOLTIP-Strata. Volle nil-Guards (UnitReaction, 4-stufige Frame-Pruefung). Im AUS-Zustand sind die Events abgemeldet. Neu: Maus-Finder (Barrierefreiheit, fuer Sehbehinderte) Einfach: In Barrierefreiheit, Visuelle Hilfen, Maus-Finder einschalten. Die Taste vergibst du jetzt DIREKT im Maus-Finder-Menue (dritter Punkt "maus finden", nach rechts, Neu belegen) - genau wie in der Sku Tastenbelegung, du musst sie nicht mehr separat suchen. Der reine Texthinweis ist entfallen. Auf Tastendruck leuchtet kurz eine kontrastreiche Markierung um die Maus auf (Pulsring oder Kompass-Striche waehlbar). Standard AUS. Technisch: Sauber geformter Tasten-Eintrag SKU_KEY_MOUSEFINDER (kein leerer Eintrag, daher kein Login-Crash), Handler ruft ein nicht-interaktives Overlay (EnableMouse(false)) zentriert auf GetCursorPosition, etwa ein Viertel Bildschirm, blendet via C_Timer.After automatisch aus. Kein Secure-Button, kein Taint. Der Tastenbelegungs-Eintrag im Maus-Finder-Menue ist vollstaendig in SkuCore\visualAids.lua gekapselt (eigener Capture-Helper, schreibt in dieselbe SkuKeyBinds-DB wie das Hauptmenue); SkuCore\Options.lua bleibt unangetastet. Neu: Anzahl der Gegner ansagen (Barrierefreiheit, Sonstiges) Einfach: Unter Barrierefreiheit, Sonstiges gibt es jetzt "Anzahl der Gegner ansagen" mit drei Einstellungen: "nur Elitegegner", "alle Gegner" und "ausgeschaltet". Damit setzt du mit einem Griff die passende Kombination, ohne die zwei Einzelschalter im Monitor feindlich suchen zu muessen. Technisch: Komfort-Auswahl, die zwei vorhandene Werte koppelt (in db.char.SkuCore.aq[talentSet].combat.hostile): relativeNumberUnitsInCombat.value und ignoreNonElite. Zuordnung: nur Elite -> ignoreNonElite=true, value=3 (Gegner die dich/Gruppe angreifen); alle Gegner -> ignoreNonElite=false, value=3; ausgeschaltet -> ignoreNonElite=true, value=1 (aus). Korrektur: bei "alle Gegner" und "nur Elite" wird jetzt ZUSAETZLICH der Kampfmonitor-Master aktiviert (db.char.SkuCore.aq[talentSet].combat.enabled=true) - vorher kam auf einem Charakter, bei dem der Master aus war, trotz "alle Gegner" keine Ansage. Bei "ausgeschaltet" bleibt der Master bewusst unberuehrt (nur die zwei Einzeloptionen werden gesetzt), damit anderes Kampfmonitoring nicht angetastet wird. Neu: Warnton wenn das Folgen abbricht (Barrierefreiheit, Sonstiges) Einfach: Unter Barrierefreiheit, Sonstiges gibt es jetzt "Warnton wenn Folgen abbricht" (ein/aus, Standard aus). Wenn du jemandem folgst (Autofollow) und das Folgen endet - egal ob das Ziel zu weit weg ist, stehen bleibt oder du dich bewegst -, kommt die Ansage "Folgen beendet". Eine Distanzmessung oder das Festlegen einer Person ist dafuer nicht noetig. Technisch: Schlanker Listener auf die oeffentlichen Events AUTOFOLLOW_BEGIN/END in SkuCore\visualAids.lua; Ansage nur, wenn vorher ein Folgen begann und der Schalter (db.profile.SkuCore.followBreakWarn) an ist. Kein Taint, keine Distanzmessung, kein OnUpdate. Hinweis: eine Warnung, wenn JEMAND ANDERES aufhoert DIR zu folgen, ist technisch nicht moeglich (kein Event dafuer). Neu: Taste "naechster Gegner im Kampf" (Sku Tastenbelegung) Einfach: In der Sku Tastenbelegung (Menue Core) gibt es die neue Aktion "naechster Gegner im Kampf". Belegst du sie mit einer Taste, schaltest du auf Tastendruck durch die nahen Gegner - auch mitten im Kampf. Sku sagt das neue Ziel wie gewohnt an. Standard: keine Taste vergeben. Technisch: SICHERE Umsetzung ueber einen SecureActionButton (Makro /targetenemy), an den die gewaehlte Taste per SetOverrideBindingClick gebunden wird. Damit ist der Zielwechsel im Kampf erlaubt (kein ADDON_ACTION_BLOCKED, kein Taint). SKU_KEY_NEXTCOMBATENEMY -> SkuCore:UpdateNextCombatEnemyBinding (in SkuCore\visualAids.lua), Bindung wird im Kampf zurueckgestellt und via PLAYER_REGEN_ENABLED nachgezogen. Hinweis: /targetenemy schaltet durch nahe angreifbare Gegner, nicht exakt gefiltert nur auf die, die mit dir kaempfen - eine exakt gefilterte Variante waere ein groesserer, spaeterer Ausbau. Neu: Auren-Sets anlegen und in der Gruppe teilen (Stufe 1+2) Einfach: Im Menue Auren gibt es jetzt "Sets (teilen)". Du kannst aus deinen aktuellen Auren ein benanntes Set anlegen (gleicher Name vorhanden -> es wird eine Zahl angehaengt), Sets auflisten und loeschen. Ein Set laesst sich "An Gruppe teilen": deine Gruppe sieht " teilt Aurenset " und am Ende "Teilen abgeschlossen". Wer Sku hat und in der Gruppe ist, bekommt das Set unter "Empfangene Sets" und kann es dort annehmen (mit Doubletten-Pruefung) oder verwerfen. Hinweis: in dieser Stufe nur zwischen gleicher Clientsprache; der Sprach-Uebersetzer kommt spaeter. Technisch: Isoliert in NEUER Datei SkuAuras\sharing.lua, pcall-geschuetzt, aendert das bestehende Auren-System NICHT (Auren bleiben name-basiert). Sets: db.char.SkuAuras.Sets (Schnappschuss). Transport ueber AceComm-3.0 (Embed in SkuAuras, Prefix SkuAuraSetV1, automatisches Zerteilen) plus AceSerializer (SkuOptions:Serialize/Deserialize). Empfang in db.char.SkuAuras.PendingSets; Annehmen importiert mit Doubletten-Pruefung und ruft UpdateAttributesListWithCurrentAuras. Sichtbare Gruppen-Ansage via SendChatMessage, Daten versteckt per Addon-Nachricht. Kein Taint. Spaeter: Stufe 3 (accountweite Bibliothek), Stufe 4 (Sprach-Uebersetzer ueber SkuDB.SpellDataTBC). Details im Plan im Heute-Ordner. Standardwert: Fortlaufend-Lautstaerke der Gesundheits-Monitore jetzt 100 Einfach: Bei einer NEUEN Installation ist die Lautstaerke fuer die fortlaufende Ausgabe der Gesundheits-Monitore (Spieler, Gruppe, Raid, Pet) jetzt 100 statt 50 - passend zur Ereignis-Lautstaerke (die war schon 100). Bestehende Profile bleiben unveraendert. Technisch: Default continouslyVolume in SkuCore\aq.lua von 50 auf 100 (4 Stellen: player/party/raid/pet health). Greift nur, wenn der Wert noch nil ist (Neuanlage). Soft-Targeting: "Hardtarget vor Softtarget" wirkt jetzt + kein Kampf-Fehler mehr Einfach: Die Einstellung "Hardtarget zaehlt vor Softtarget" hatte bisher KEINE Wirkung - ein Zauber ging trotz festem Ziel auf das Soft-Ziel. Behoben: mit festem (hard) Ziel zaehlt jetzt das feste Ziel. Ausserdem verschwindet der "ADDON_ACTION_BLOCKED"-Fehler, der nach Login beim ersten freundlichen Ziel im Kampf auftrat. Technisch: In UpdateSoftTargetingSettings (SkuZOptions/Core.lua) setzten frueher BEIDE Zweige SoftTargetMatchLocked = 0 (Bug) -> bei matchLocked>0 jetzt = 1. Zudem sind SoftTarget-CVars im Kampf gesperrt: die Funktion ueberspringt im Kampf alle SetCVar-Aufrufe (InCombatLockdown-Guard) und zieht sie nach Kampfende (PLAYER_REGEN_ENABLED) einmal nach. Kein Funktionsverlust (CVars sind im Kampf ohnehin eingefroren), kein ADDON_ACTION_BLOCKED mehr. Versionsnummer auf 41.05 angehoben. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.04 Auktionshaus: Kaufmeldungen jetzt in der richtigen Sprache Einfach: Wenn beim Kauf etwas schiefgeht (z. B. man drueckt zu frueh Enter), kommt die Meldung jetzt auf Englisch, wenn man den englischen Client spielt - vorher kam sie immer auf Deutsch. Technisch: Drei fest einprogrammierte deutsche Texte im Kaufpfad (auctionHouse.lua) sind jetzt ueber L[...] lokalisiert; Schluessel in deDE.lua und enUS.lua ergaenzt. Auktionshaus: Komplettscan startet zuverlaessig, keine falsche 16-Minuten-Sperre Einfach: Frueher konnte der Komplettscan stumm fehlschlagen und danach 16 Minuten gesperrt sein, ohne dass je gescannt wurde. Jetzt startet er entweder wirklich, oder es kommt die Ansage "Scan noch nicht moeglich, bitte kurz warten" - und die Sperre wird nur gesetzt, wenn wirklich gescannt wurde. Der Fokus bleibt auf dem Scan-Punkt. Technisch: AuctionHouseStartQuery gibt true nur zurueck, wenn QueryAuctionItems tatsaechlich abgesetzt wurde; der getAll-Scan wird vorher gegen CanSendAuctionQuery geprueft. Der Zeitstempel (AuctionLastFullScanTime) wird nur bei echtem Start gesetzt. noStepUpAfterSelect haelt den Fokus. Auktionshaus: Fokus bleibt beim Filtern/Sortieren Einfach: Nach dem Waehlen von z. B. "selten" oder "Level absteigend" springt der Fokus nicht mehr eine Ebene zu weit zurueck, sondern bleibt auf dem Filter. Technisch: Die fuenf Filter-/Sortier-Eintraege (Level min/max, Qualitaet, nur benutzbare, Sortierung) haben jetzt noStepUpAfterSelect = true. AtlasLoot/Wunschliste: keine Raid-Lags mehr Einfach: Die Wunschliste hat im Raid-Kampf bei vielen Chat-Nachrichten gebremst. Das ist behoben - der Wunsch-Item-Ton beim Looten/Wuerfeln/ Verlinken funktioniert weiter. Technisch: Statt pro Chat-Zeile/Item-Link die ganze Favoritenliste mit GetItemInfoInstant zu durchlaufen, gibt es jetzt einen itemID-Cache (O(1)-Lookup), der nur bei Aenderung neu gebaut wird. Bei leerer Wunschliste brechen die Chat-Handler sofort ab. AtlasLoot: Strg+Shift+L vereinfacht Einfach: Strg+Shift+L oeffnet jetzt einfach Atlas Loot. Der automatische Sprung auf die aktuelle Instanz oder den Boss im Ziel wurde entfernt - er war unzuverlaessig und konnte Fehler machen. Technisch: Die Kontext-Erkennung (Instanz/Boss/Schwierigkeit) in AtlasLootShortcut wurde entfernt; es wird immer der Standard-Pfad geoeffnet und das Kontext-Flag geleert. Freundesliste: Battle.net-Freunde einladen Einfach: Man kann jetzt einen Battle.net-Freund, der gerade WoW spielt, ueber das Menue in die Gruppe einladen. Vorher passierte nichts. Technisch: Im Invite-OnAction (friends.lua) gibt es jetzt einen BNet-Zweig: Charaktername + Realm aus gameAccountInfo, Einladung via C_PartyInfo.InviteUnit (Fallback InviteUnit/BNInviteFriend). Spielt der Freund nicht WoW, kommt eine Ansage. Auren: Anzeigename stuerzt nicht mehr ab Einfach: Beim Anzeigen oder Durchblaettern von Auren konnte es einen Lua-Fehler geben, wenn eine Aura einen Wert oder eine Aktion benutzte, die das Addon gerade nicht aufloesen konnte. Das ist behoben. Technisch: BuildAuraName (SkuAuras/Options.lua) macht alle dynamischen Lookups (Types, attributes, Operators, values, actions, outputs) jetzt nil-sicher; bei unbekanntem Schluessel wird der Rohschluessel angezeigt statt eines Fehlers. Nicht in dieser Version (bewusst verschoben) - Taschen: Fokus/Aktualisierung nach "wird an dich gebunden" - beruehrt den empfindlichen Taschen-Frame-Bereich und wird separat angegangen. - Soft-/Hardtarget (Hardtarget soll Softtarget verdraengen; weniger Target-Spam bei rausgezoomter Kamera) - liegt im geschuetzten Zielsystem; nur analysiert, noch nicht umgesetzt. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf v41.04 aktualisiert. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.03 Barrierefreiheit-Menue: 7.4 Sonstiges - Neuer Unterpunkt 7.4 "Sonstiges" unter Menuepunkt 7. Schnellzugriff auf: Spieltooltip nicht ausblenden, Alle Tooltips lesen, NPC-Begruessungen, Menuenummern ansagen, Untermenues ansagen. - Verknuepfungen auf die bestehenden Optionen - Aenderungen wirken in beide Richtungen. Der Cursor bleibt nach dem Umschalten auf dem Eintrag. AtlasLoot/Wunschliste: Boss-Quelle im Tooltip (Ansicht "Nach Slot") - In der Wunschliste unter "Nach Slot" wird die Drop-Quelle (Instanz und Boss) jetzt zuverlaessig im Tooltip angezeigt - auch direkt nach dem Login, ohne vorher die Ansicht "Nach Dungeon" geoeffnet zu haben. Auren: Waffenbuff-Bedingungen (neu) - Vier neue Bedingungen: "Deine Waffenverzauberung Haupthand" und "... Nebenhand" (enthaelt / enthaelt nicht) sowie deren verbleibende Dauer in Sekunden. - Damit lassen sich Alarme bauen, z. B. wenn ein Gift/Oel/Schaerfstein auf der Haupthand laeuft oder die Rest-Dauer unter einen Wert faellt. - Rein zusaetzlich gebaut; bestehende Auren sind unveraendert. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf v41.03 aktualisiert. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.08 Menue 7 "Barrierefreiheit" mit Schnellzugriffen - Menuepunkt 7 heisst jetzt "Barrierefreiheit". Darunter: 7.1 Lautstaerke, 7.2 Sprachausgabe, 7.3 Kamera. - 7.1 Lautstaerke: Gesamt-, Soundeffekte-, Musik-, Umgebungs- und Dialoglautstaerke, Beacon-Lautstaerke sowie Hall, positionsbezogener Tiefpassfilter, DSP-Effekte, Sound im Hintergrund und Zonenmusik ohne Verzoegerung. Es sind Verknuepfungen auf die bestehenden Optionen - Aenderungen wirken in beide Richtungen (Barrierefreiheit und Originalmenue). - 7.2 Sprachausgabe: TTS-Stimme, -Geschwindigkeit und -Lautstaerke. - 7.3 Kamera: das bisherige Video-Optionen-Menue (Verfolgung, Zoom usw.). - Die urspruenglichen Menues (Optionen/Optionen, Navigation/Optionen, Chat/Optionen) bleiben unveraendert erhalten. - Nach einer Wertaenderung bleibt der Cursor auf dem jeweiligen Regler (nur im 7er-Menue), sodass man zuegig mehrere Werte einstellen kann. Briefkasten: Fokus bleibt auf dem Brief - Nach dem Entnehmen von Gold oder einem Gegenstand bleibt der Cursor auf dem Brief stehen, statt zur Briefliste hochzuspringen. Per Pfeil- rechts oeffnet man die (aktualisierten) Anhaenge erneut und entnimmt weitere. Beim Loeschen wird sauber der Nachbar-Brief fokussiert. Navigation: Menuepunkt "Daten" ausgeblendet - Der Punkt "Daten" unter Navigation ist nicht mehr sichtbar. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf v41.02.08 aktualisiert. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.07 Kamera: Freie Kamera nach Brechen des SkuStandards - Wird der SkuStandard freigegeben, bleibt die selbst eingestellte Kamera jetzt erhalten - auch beim Drehen mit T oder zum Wegpunkt. Der erzwungene Kamera-Sprung (SetView) wirkt nur noch im SkuStandard. Die Drehung selbst funktioniert weiterhin korrekt. - Persoenlicher Kamera-Speicher: Aenderungen im freien Modus werden gespeichert und nach dem Login automatisch wieder geladen. Der sichere SkuStandard bleibt Standard fuer alle anderen Nutzer. - Menue 7 "Video-Optionen" als Grundlage fuer die neue Struktur. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf v41.02.07 aktualisiert. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.06 Kamera-Optionen (Menuepunkt 7) - Neues Menue "Kamera-Optionen" ersetzt den bisherigen Platzhalter "Reserviert". - Sku Standard sperren/entsperren: Sperrt alle Kameraeinstellungen auf den Sku-Standard (noetig fuer Wegpunktnavigation). Beim Sperren wird eine Bestaetigung abgefragt und ein vollstaendiger Kamera-Reset durchgefuehrt inkl. SaveView(2). Beim Entsperren werden die gespeicherten User-Einstellungen wiederhergestellt. - Kamera-Entfernung: 6 Stufen von Nah (Faktor 1) bis Maximum (Faktor 4). Zoom wird physisch ausgefuehrt. - Kamera-Hoehe: 4 Stufen von flach bis Vogelperspektive. Hinweis: funktioniert nur wenn Verfolgungsstil nicht auf Immer steht. - Kamera-Neigungsgeschwindigkeit: 4 Stufen von Langsam bis Sehr schnell. - Kamera-Verfolgungsstil: 4 Optionen wie im WoW-Original (Intelligent, Nur bei Bewegung, Immer, Niemals). "Immer" ist der Sku Standard fuer Wegpunktnavigation. - Interface ein/ausblenden: Blendet die gesamte WoW-Oberflaeche ein oder aus. - Weitere Kamerafunktionen: Kamera-Uebergang (sofort/sanft), Ueber-die-Schulter-Ansicht, Plaketten (Gegner/Freundliche/Alle ein/aus). - Alle Einstellungen zeigen ihren aktuellen Wert im Menuenamen an. Aktive Option mit "(eingestellt)" markiert. - Bei gesperrtem Sku Standard sind alle Untermenues blockiert mit Ansage. - Einstellungen bleiben ueber Logout/Login erhalten (persistent in SavedVariables). Auktionshaus: Absturz auf englischem Client behoben - Beim Oeffnen des Auktionshauses konnte ein Fehler auftreten (ipairs auf nil), wenn AuctionCategories noch nicht von Blizzard initialisiert war. Fix: nil-Guard vor beiden ipairs-Schleifen und 0.3s Verzoegerung beim Menue-Aufbau. AtlasLoot: Lokalisierung korrigiert - Die Gruppen "Instanzen", "Schlachtzuege" und "Weltbosse" unter AtlasLoot Listen waren hardcoded auf Deutsch. Sie verwenden jetzt L[]-Eintraege und erscheinen auf englischen Clients korrekt. Ebenso "Heroisch", "Normal" und der Schwierigkeitsgrad-Fallback. Charakterfenster: Gegenstand im Slot - CheckFrames wird nach dem Aufnehmen eines Gegenstands aus einem Equipment-Slot nicht mehr sofort aufgerufen. Dadurch kann der Gegenstand in die Tasche gelegt werden, ohne dass das Menue den Slot-Zustand verfaelscht. Soulbind-Bestaetigung: Fokus-Verbesserung - Nach dem Bestaetigen der "Gegenstand wird gebunden"-Abfrage springt der Fokus nicht mehr auf die Taschen-Ebene zurueck. Stattdessen wird CheckFrames verzoegert aufgerufen und der Cursor korrekt positioniert. Weltkarte: Visuelles Flackern reduziert - Das Addon oeffnete und schloss die Weltkarte im Hintergrund (alle 0.15s), um Positionsdaten zu lesen. Wenn die Karte bereits offen war, verursachte dies visuelles Flackern. Fix: Show/Hide wird nur noch ausgefuehrt, wenn die Karte nicht sichtbar ist. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc aktualisiert auf v41.02.06. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.05 Begleiter-Aktionsleiste: Automodus repariert - Der Automodus (Autocast) fuer Begleiterfaehigkeiten funktioniert jetzt. Die Umschaltung nutzt macrotext mit /click RightButton im Hardware-Event-Kontext. Menue zeigt "Permanent (aktiviert/deaktiviert)" mit Untereintraegen zum Ein- und Ausschalten. Rollenabfrage-Fenster zugaenglich gemacht - Die Rollenabfrage des Gruppenleiters oeffnet jetzt ein Sku-Menue mit den Optionen "Tank", "Heiler" und "Schaden". Enter auf eine Rolle waehlt sie und bestaetigt sofort. Bereits gewaehlte Rollen werden nicht zurueckgesetzt. Equipment-Slot Doppelklick behoben - Linksklick auf ausgeruestete Gegenstaende im Charakterfenster nahm den Gegenstand auf und legte ihn sofort wieder ab. Ursache: macrotext und OnAction feuerten beide. Fix: OnAction prueft per GetCursorInfo ob der Gegenstand bereits am Cursor haengt. Tastenbelegung: Konflikt-Aufloesung repariert - Beim Umbelegen einer Taste auf eine andere Aktion wurden bisher ALLE Belegungen der alten Aktion geloescht (primaer und sekundaer). Jetzt wird nur die konfliktbehaftete Taste entfernt, die andere Belegung bleibt erhalten. Sockelfenster: Duplikat-Edelsteine repariert - Gleichnamige Edelsteine werden jetzt gruppiert und mit Anzahl angezeigt (z.B. "Gediegener Zirkon 2x"). Nach dem Einsetzen in einen Sockel wird der genutzte Taschenplatz als belegt markiert, sodass der naechste Sockelplatz den verbleibenden Stein korrekt anzeigt und einsetzen kann. Wunschliste: Kategorie "Sonstiges" hinzugefuegt - Items ohne Equipment-Slot (Tokens, Rezepte, Reittiere) koennen jetzt zur Wunschliste hinzugefuegt werden. Sie erscheinen unter "Nach Slot" in der neuen Kategorie "Sonstiges". Tastenbelegungsliste beigelegt - Drei Readme-Dateien im Sku-Ordner: Standard-Tastenbelegung fuer blinde Spieler auf Deutsch, Englisch und Franzoesisch. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.04 PageDown/PageUp im Sku-Menue korrigiert - PageDown/Up springt nicht mehr 10 Menuepunkte im Sku-Menue. Die Tasten loesen jetzt nur noch das Blaettern in Berufefenstern (Rezeptlisten) aus und aktualisieren das Menue entsprechend. In allen anderen Menues (Taschen, Auktionshaus etc.) haben die Tasten keine Wirkung mehr. Lokalisierung: Ausruestungssets - Der Menuepunkt "Ausruestungssets" im Charakterfenster war bisher ein hardcoded deutscher String. Er verwendet jetzt L["Equipment sets"] und erscheint auf englischen Clients korrekt als "Equipment sets". Lokalisierung: Sockelfenster - Der Frame-Name "Sockeln" auf der ersten Menue-Ebene war bisher ein hardcoded String. Er verwendet jetzt L["Sockeln"] und erscheint auf englischen Clients korrekt als "Socket". ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.03 Briefkasten: Neue kombinierte Eingabe - Neuer Brief hat jetzt drei Menuepunkte: "Gegenstaende anhaengen", "Gold anhaengen" und "Versendevorgang starten". Die Reihenfolge ist logisch: zuerst optionale Anhaenge, dann Versand. - "Versendevorgang starten" oeffnet ein Eingabefeld. Bedienung: Name eingeben, Tab druecken, Betreff eingeben, Tab druecken, optional Text eingeben, Enter druecken. Der Brief wird direkt gesendet. - Nach dem Anhaengen von Gegenstaenden oder Gold kehrt der Fokus automatisch zum jeweiligen Menuepunkt zurueck. Nach dem Senden kehrt der Fokus auf "Neuer Brief" zurueck. - Technisch: Neue Funktion SkuCore:MailEditorCombined() in mail.lua. Nutzt OnKeyDown-Handler auf der EditBox fuer Tab- und Enter-Erkennung. Tab wechselt das Feld (Name/Betreff/Text), Enter schliesst ab und ruft SendMail() direkt auf. Das Menue bleibt offen (MailFrame muss fuer SendMail() sichtbar sein). Hexenmeister-Begleiter: Eigenes Zielmenue - Das Zielmenue fuer Hexenmeister-Begleiter (Daemonen) zeigt jetzt die korrekten Aktionen: Schlachtzugsymbol, Fokus setzen, Interagieren und Freigeben. Bisher wurden faelschlich die Jaeger-Pet-Aktionen angezeigt. - Technisch: SkuMob/Options.lua, tIsPet-Block: Klassenpruefung via UnitClass("player"). HUNTER zeigt Jaeger-Aktionen, alle anderen Klassen zeigen das generische Pet-Menue. Fehlende Audiowoerter behoben - "Tabulatortaste" und "absenden" durch "Tab" und "Senden" ersetzt, da die urspruenglichen Woerter keine Audiodateien im SkuAudioData hatten und einen Beep ausloesten. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.02 (Arbeitsversion) Erkenntnisse aus der Briefkasten-Reparatur: - CloseMenu() schliesst auch das Blizzard MailFrame. SendMail() benoetigt aber ein offenes MailFrame. Daher darf CloseMenu() NICHT vor der Mail-Eingabe aufgerufen werden. - EditBox OnEnterPressed feuert nicht wenn SetScript("OnKeyDown") gesetzt ist. Enter muss im OnKeyDown-Handler manuell abgefangen werden. - SkuOptionsEditBoxOkScript ist eine lokale Variable in SkuZOptions/Core.lua und kann nicht aus anderen Dateien (z.B. mail.lua) aufgerufen werden. Callbacks muessen als lokale Funktionen im aufrufenden Scope definiert werden. - RegisterForClicks("AnyDown") verhindert Double-Enter, blockiert aber EditBox-OnEnterPressed (feuert auf Key-Up). Loesung: OnKeyDown-Handler auf der EditBox faengt Enter direkt ab — unabhaengig vom SecureActionButton-Override-Binding. - Debounce-Ansatz (100ms Sperre im PostClick) funktioniert fuer Taschen und Wunschliste, bricht aber Briefkasten und andere EditBox-Eingaben. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02.01 (Arbeitsversion) Doppeltes Ausloesen von Enter behoben - Der SecureActionButton reagierte auf Taste-runter UND Taste-hoch, wodurch jeder Enter-Druck zwei Aktionen ausloeste. Betroffen waren alle Menues: Taschen (Enter sprang 2 Ebenen statt 1), Auktionshaus, Wunschliste (Items wurden sofort wieder entfernt). Fix: RegisterForClicks auf AnyDown geaendert (1x pro Tastendruck). - Technisch: SkuZOptions/Core.lua Zeile 2738. "AnyUp, AnyDown" -> "AnyDown". AnyDown liefert Hardware-Event-Kontext (wichtig fuer Linksklick/Gegenstaende). AnyUp allein liefert keinen Hardware-Kontext. Stallmeister repariert - Die Stallmeister-Funktionen aus Version 40.x wurden uebernommen, da sie funktionsfaehig sind. Der Stallmeister ist nun wieder bedienbar. - Technisch: SkuCore/LocalMenu.lua, Build_PetStableFrame 1:1 aus Vorlage 2.x kopiert. Nutzt tFrame:GetScript("OnDragStart")(...) und OnReceiveDrag — funktioniert im Gossip/LocalMenu-System ueber den click=true-Pfad des Gossip-Builders. Pet-Umbenennung repariert - Fix: Menue wird vor dem Eingabefeld geschlossen (CloseMenu), EditBoxShow statt EditBoxPasteShow, mit Verzoegerung (C_Timer.After 0.3s). - Technisch: SkuMob/Options.lua. EditBoxPasteShow war fuer Paste-Eingabe (OnChar, min. 10 Zeichen). EditBoxShow ist fuer Tastatur-Eingabe (OnEnterPressed). CloseMenu() hebt das Enter-Override-Binding auf, sodass die EditBox Enter empfangen kann. secureMacro-System fuer geschuetzte Funktionen - Das SecureActionButton-Attribut wurde mit dem ungueltigen Mausbutton-Parameter "ENTER" gesetzt. TBC 2.5.5 findet type/macrotext-Attribute nicht fuer unbekannte Button-Namen (kein Fallback auf Default-Attribute). - Fix: Neues secureMacro-Flag auf Menu-Eintraegen. Wenn gesetzt, werden zusaetzlich typeENTER/macrotextENTER-Attribute gesetzt, die der SecureActionButton korrekt verarbeitet. Eintraege ohne secureMacro loeschen diese Attribute (verhindert Konflikte mit Linksklick/OnAction). - Technisch: SkuZOptions/templates.lua OnEnter-Handler (Zeile 274). SkuMob/Options.lua: secureMacro=true auf PetDismiss und PetRename-Bestaetigungseintrag. - Erkenntnis: macrotext feuert NICHT im Gossip/LocalMenu-System (getestet mit /say, /run, /click — keine Ausgabe). macrotext feuert NUR im SkuMob/SkuGenericMenuItem-System (bewiesen durch PetRename/PetDismiss). Tier freigeben / Tier zuruecklassen - Lokalisierung an In-Game-Begriffe angepasst. - secureMacro-Flag fuer PetDismiss (/petdismiss im Hardware-Event-Kontext). ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.02 Versionssprung 40.x auf 41.x - Performance verbessert, Wiki-Bereich entfernt. - Lokalisierung der neuen Inhalte: Sockeln, AtlasLoot-Wunschliste, Dropdown-Menue, Dungeonfinder. Bugfix: Zahlen- und Buchstabentasten auf englischem Client blockiert - Beim Einloggen auf einem englischen WoW-Client wurden nach einem automatischen Profilwechsel alle Buchstaben-, Zahlen- und Leertasten-Eingaben durch verwaiste Override-Bindings blockiert. Betroffen war z. B. die Taste 7 (und damit / auf QWERTZ-Tastaturen). Ursache: SkuKeyBindsUpdate() rief direkt den OnShow-Handler des Menuefensters auf, der saemtliche Menue-Navigations-Bindings setzte, ohne dass OnHide sie wieder raeumte. Der betroffene Keybinding-Eintrag (SKU_KEY_QUESTABANDON) wurde korrigiert. - Zusaetzlich werden alle Modul-OnEnable-Aufrufe in den Profil-Handlern (OnProfileChanged, OnProfileCopied, OnProfileReset) nun per pcall geschuetzt, damit SkuKeyBindsUpdate() auch bei einzelnen Modul-Fehlern immer erreicht wird. - Die Deduplizierung in SkuKeyBindsUpdate wurde repariert: Funktionen wie CreateMainFrame werden jetzt nur noch einmal statt ~30-mal aufgerufen. Lokalisierung: Sockelfenster - Alle ~20 hardcoded deutschen Strings in Build_SocketingFrame.lua durch L[]-Aufrufe ersetzt. Auf englischen Clients erscheinen nun korrekte englische Texte (Sockelfarben, Menuepunkte, Statusmeldungen). - Kritischer Menueabgleich (child.name == "Sockeln") lokalisiert, sodass das Sockelmenue auf englischen Clients korrekt gefunden wird. Fehlender Locale-Key - L["Warlock"] in enUS.lua ergaenzt. Der Key war in deDE.lua vorhanden, fehlte aber in der englischen Locale-Datei. API-Kompatibilitaet - SetMinResize/SetMaxResize in SkuNav/SkuMM.lua durch Capability Detection ersetzt (SetResizeBounds bevorzugt, Fallback auf SetMinResize). Verhindert moegliche Fehler auf TBC Anniversary (Interface 11508). Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf v41.01.04 aktualisiert (ohne beta). ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.01.03 beta Pet-Umbenennung - ADDON_ACTION_BLOCKED behoben: Der SecureActionButton war durch einen HookScript-Handler getaintet. WoW blockierte deshalb den geschuetzten PetRename()-Aufruf. Der HookScript wurde durch PostClick ersetzt, der die sichere Macro-Ausfuehrung nicht beeintraechtigt. - Menu-Rebuild nach Namenseingabe wiederhergestellt: Nach dem Eintippen des neuen Namens wird das Menu jetzt automatisch aktualisiert, damit der Bestaetigungseintrag sofort sichtbar ist. Auktionshaus - Absturz bei "Neue Auktion" behoben: Wenn ein Gegenstand im Inventar noch nicht vollstaendig im Client-Cache geladen war, fuehrte ein nil-Wert bei der Namensabfrage zum Absturz. Items ohne gecachten Namen werden jetzt uebersprungen. Navigation - Absturz bei Spezialaufgaben behoben: Wenn die Aufgaben-Datenbank nicht geladen war, fuehrte der Zugriff auf SkuDB.Tasks zum Absturz. Es wird jetzt vorher geprueft ob die Daten vorhanden sind. - Gefaehrlichen Menuepunkt entfernt: Der Menuepunkt "Alle Routen und Wegpunkte loeschen" unter Navigation/Daten wurde entfernt. Er haette alle benutzerdefinierten Navigationsdaten unwiderruflich geloescht. - Export-Funktion freigeschaltet: Unter Navigation/Daten kann die Routendaten-Kartierung jetzt als Text exportiert werden, um sie im SkuMapper-Tool zu importieren. Wunschliste (Atlasloot) - Audio-Feedback bei Enter repariert: Die Rueckmeldung beim Hinzufuegen/Entfernen von Wunschlisten-Items wurde von einer internen Bereinigung sofort geloescht. Die Sprachausgabe wird jetzt leicht verzoegert abgespielt, sodass sie zuverlaessig hoerbar ist. Stabilitaet - Nil-Guard fuer Menueposition-Name: Verhindert den Folgefehler "bad argument #1 to find (string expected, got nil)" wenn das Menue in einem ungueltigen Zustand ist. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc aktualisiert auf v41.01.03 beta. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.01.02 beta Fehlerbehebungen (Sound) - Sound-Verlust behoben: Wenn das gespeicherte Profil eine Gesamt-Lautstaerke von 0 enthielt (z.B. durch beschaedigte SavedVariables), wurden beim Login alle WoW-Sound-Kanaele auf stumm gesetzt. Es gibt jetzt einen Schutz: Wird im Profil eine Gesamt-Lautstaerke von 0 erkannt, liest das Addon die aktuellen Blizzard-Einstellungen neu ein, anstatt die 0 anzuwenden. - CVar-Reads abgesichert: Alle Lautstaerke-Abfragen beim Profil-Erststart verwenden jetzt tonumber() mit Fallback auf 100 Prozent. Falls WoW einen ungueltigen Wert zurueckgibt, wird die volle Lautstaerke verwendet statt stumm. - Vorbestehenden CVar-Bug behoben: Drei Sound-Einstellungen (DSP-Effekte, Sound im Hintergrund, Zonenmusik ohne Verzoegerung) wurden bisher nicht korrekt an WoW uebergeben, weil durch einen Copy-Paste-Fehler immer derselbe CVar-Name verwendet wurde. Die drei Einstellungen werden jetzt korrekt angewendet. Hinweis zur Installation - Nach dem Kopieren des neuen Addons wird empfohlen, einmalig die Sku-SavedVariables zu loeschen. Die Datei befindet sich unter WTF/Account/ACCOUNTNAME/SavedVariables/Sku.lua im WoW-Ordner. Dadurch wird ein frisches Profil erstellt, das die korrekten Blizzard-Lautstaerken uebernimmt. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc aktualisiert auf Titel/Version v41.01.02 beta. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v41.01.01 beta Performance - Wiki/Tutorial-Modul entfernt: Das Modul "Tutorials und Wiki" (Menuepunkt 7) wurde vollstaendig entfernt. Das spart ca. 30 MB Arbeitsspeicher (28 MB Wiki-Datenbank plus Lookup-Index) und beschleunigt den Login spuerbar, da 39.600 Zeilen weniger geparst werden muessen. - Kein permanenter OnUpdate-Handler mehr: Der Frame-Handler, der bei jedem Wiki-Menueoeffnen lief (~60x pro Sekunde), existiert nicht mehr. Menue - Menuepunkt 7 ist jetzt ein Platzhalter mit dem Namen "Reserviert". Er zeigt den Hinweis "Dieser Bereich wird derzeit ueberarbeitet" an. Der Bereich wird in einer zukuenftigen Version mit neuen Inhalten befuellt. Tastenbelegung - Die Standard-Tastenbelegung SHIFT-F4 (Abenteuerfuehrer oeffnen) wurde entfernt, da das zugehoerige Modul nicht mehr existiert. Spieler, die die Taste manuell umbelegt hatten, muessen nichts tun — der Eintrag wird ignoriert und verursacht keinen Fehler. Sicherheit - Nil-Guards fuer Wiki-Referenzen: Alle Stellen im TTS-System (SkuTTS), im Optionssystem (SkuZOptions) und in der Sprachausgabe (SkuVoice), die auf Wiki-Daten zugreifen, sind jetzt mit Nil-Pruefungen abgesichert. Damit wird sichergestellt, dass keine Fehlermeldungen auftreten, obwohl die Wiki-Daten nicht mehr geladen werden. Fehlerbehebungen - tasks.lua (Navigations-Aufgaben fuer DK-Quests) wurde faelschlicherweise mit dem Wiki-Modul entfernt. Die Datei wurde wiederhergestellt. Behebt den Fehler "bad argument #1 to 'pairs' (table expected, got nil)" in specialNavigationTasks.lua. Begleit-Addons - SkuAudioData_fast_de: Interface-Version auf 11508 aktualisiert, Abhaengigkeit zu Sku hinzugefuegt. Behebt "attempt to index global 'Sku' (a nil value)". - SkuBeaconSoundsets: Interface-Version auf 11508 aktualisiert. - SkuCustomBeaconsAdditional: Interface-Version auf 11508 aktualisiert, Abhaengigkeiten hinzugefuegt. - SkuCustomBeaconsEssential: Interface-Version auf 11508 aktualisiert, Abhaengigkeiten hinzugefuegt. - Die korrigierten TOC-Dateien liegen im Ergebnisordner neben dem Sku-Ordner. Einfach in die bestehenden Addon-Ordner im Spiel kopieren. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc aktualisiert auf Titel/Version v41.01.01 beta. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v40.06 Wunschliste - Items hinzufuegen/entfernen repariert: Die Wunschliste reagiert jetzt zuverlaessig beim Hinzufuegen und Entfernen von Items. Vorher konnte die Aktion still fehlschlagen, wenn das Item noch nicht im Cache war oder der Menu-Rebuild einen Fehler ausloeste. - Audio-Feedback: Beim Hinzufuegen eines Items wird jetzt "Auf Wunschliste gesetzt" angesagt, beim Entfernen "Von Wunschliste entfernt". Bisher gab es keinerlei Rueckmeldung. - Cache-Fallback: Wenn ein Item beim ersten Versuch noch nicht im Client-Cache liegt, wird es automatisch angefragt und nach kurzer Verzoegerung erneut versucht. Pet-Umbenennung - Bestaetigung repariert: Der Zwei-Schritt-Prozess (Name eingeben, dann "Umbenennung bestaetigen" waehlen) funktioniert wieder zuverlaessig. Der fehlerhafte Menu-Rebuild nach der Namenseingabe, der den Absturz "attempt to call method 'BuildChildren' (a nil value)" ausloeste, wurde entfernt. Stallmeister - Drag/Drop repariert: Pet-Tausch zwischen aktivem Begleiter und Stallplaetzen nutzt jetzt macrotext im Hardware-Event-Kontext. Vorher lief der Klick im Addon-Kontext und konnte von Blizzard blockiert werden. - Kaufpreis: Der Button "Weiteren Platz kaufen" zeigt jetzt den Preis in Gold/Silber/Kupfer an. - Automatischer Refresh: Nach einem Pet-Tausch oder Stallplatz-Kauf wird das Stallmeister-Fenster automatisch aktualisiert (PET_STABLE_UPDATE Event). - Event-Registrierung: PET_STABLE_SHOW, PET_STABLE_CLOSED und PET_STABLE_UPDATE werden jetzt korrekt im SkuDispatcher registriert. Die Event-Handler existierten vorher, wurden aber nie aufgerufen. Fehlerbehebungen - VocalizeCurrentMenuName: Nil-Guard fuer BuildChildren eingefuegt. Verhindert den generischen Absturz "attempt to call method 'BuildChildren' (a nil value)", der in mehreren Menuebereichen (Wunschliste, Pet-Umbenennung, Stallmeister) auftreten konnte. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc aktualisiert auf Titel/Version v40.06. ------------------------------------------------------------------------------------------------------- Aenderungen in Sku v40.05 Wunschliste - Sound bei Chat-Link: Wenn ein Wunschlisten-Gegenstand im Party-, Raid-, Sag- oder Schrei-Chat verlinkt wird, ertoennt jetzt der gleiche Hinweiston wie beim Wuerfelfenster. - Farbcodes entfernt: Dungeon-Namen und Boss-Namen aus AtlasLoot werden jetzt ohne WoW-Farbcodes (|cff...) angezeigt. Betrifft sowohl die Ansicht "Nach Dungeon" als auch den Tooltip mit Boss-Drop-Quellen. Fehlerbehebungen - Fehlende Locale-Eintraege: L["Up"] und L["Down"] fuer die Wunschlisten-Reihenfolge hinzugefuegt. Behebt "AceLocale-3.0: Missing entry for 'Down'" Fehler. - Kampflog: CombatLog_OnEvent wird jetzt auf Verfuegbarkeit geprueft, bevor es aufgerufen wird. Behebt den Absturz "attempt to call global 'CombatLog_OnEvent' (a nil value)" auf TBC Anniversary. - Gegenstandsliste: C_Item.GetItemNameByID wird jetzt mit einem Fallback abgesichert. Behebt den Absturz "attempt to concatenate a nil value" wenn ein Item noch nicht im Cache ist. - Interaktionsdistanz: CheckInteractDistance wird jetzt per pcall aufgerufen. Behebt "ADDON_ACTION_BLOCKED CheckInteractDistance()" im Kampf. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc aktualisiert auf Titel/Version v40.05. ------------------------------------------------------------------------------------------------------- Changes in Sku v40.04.01 Atlas Loot - Atlas Loot ist jetzt ueber Strg+Shift+L erreichbar (wenn installiert). Das Tastenkuerzel kann unter Shift+F1, Core, Skutastenbelegung frei umbelegt werden. - Wunschliste mit Sound: Wenn ein Wunschlisten-Item im Loot erscheint, ertoennt ein Sound. Beim Erhalten des Items wird es automatisch von der Wunschliste entfernt. - Wunschliste: Neue Menuestruktur mit zwei Untermenues "Nach Dungeon" und "Nach Slot". "Nach Dungeon" zeigt nur Dungeons, die Items auf der Wunschliste haben (Format: "Anzahl Dungeonname"). "Nach Slot" enthaelt die bisherige Slot-basierte Liste. Ausruestungsmanager - Der Ausruestungsmanager ist im Charakterfenster (Taste C) erreichbar. Ausruestungssets koennen gespeichert, angelegt, ueberschrieben, umbenannt und geloescht werden. - Makro erstellen: Neuer Menueeintrag bei jedem Ausruestungsset. Erstellt ein Charaktermakro, das beim Ausfuehren das Set anlegt. Bereits vorhandene Makros werden aktualisiert. - Lokalisierung: Alle Menue-Eintraege und Statusmeldungen des Ausruestungsmanagers sind jetzt lokalisiert. Auf englischen Clients erscheinen alle Texte auf Englisch. Ziel-Aktionsmenue (CTRL+T) / Pet-Aktionen - Zuruecklassen repariert: "Zuruecklassen" verwendet jetzt macrotext (/petdismiss) statt eines Addon-Kontext-Aufrufs. Dadurch wird ADDON_ACTION_FORBIDDEN vermieden und das Pet wird zuverlaessig temporaer weggeschickt. - Umbenennen repariert: Die Pet-Umbenennung funktioniert jetzt ueber ein Zwei-Schritt-Verfahren. Schritt 1: Name eingeben. Schritt 2: "Umbenennung bestaetigen" waehlen (macrotext im Hardware-Kontext). Dadurch wird ADDON_ACTION_FORBIDDEN beim Speichern des Namens vermieden. - Aufloesen mit Sicherheitsabfrage: "Pet aufloesen" heisst jetzt "Pet dauerhaft entlassen" und erfordert eine Bestaetigung ueber einen Sicherheitsdialog. Der bisherige Code rief PetAbandon direkt auf, was das Pet permanent entliess, ohne dass der Benutzer gewarnt wurde. PopUp-Erkennung - Verzoegerter Zweitaufruf: StaticPopup_Show ruft CheckFrames jetzt zusaetzlich mit 0,15 Sekunden Verzoegerung auf. Damit werden PopUps (z.B. Verzauberung ueberschreiben, Pet-Umbenennung bestaetigen) zuverlaessig im Sku-Menue angezeigt, auch wenn der PopUp-Inhalt beim ersten Aufruf noch nicht vollstaendig gesetzt ist. Fehlerprotokoll (ErrorLog) - Kampf-Throttling: Waehrend des Kampfes werden maximal 5 Fehler pro Sekunde protokolliert. Ueberzaehlige Fehler werden verworfen. Die BugGrabber-Bridge wird im Kampf vollstaendig pausiert. Dadurch wird die Fehlermeldung "insecure scripts exceeded execution limit" in Raids (z.B. Karazhan, AQ40) vermieden. - Lokalisierung: Alle Slash-Befehl-Hilfe und Statusmeldungen sind jetzt lokalisiert. Lokalisierung - Rund 70 neue L[]-Eintraege in beiden Locale-Dateien (AL_*, EQ_*, ERRLOG_*, MOB_*). - Hardcoded deutsche Strings in alIntegration.lua, equipmentSets.lua und ErrorLog.lua durch L[]-Aufrufe ersetzt. - equipmentSets.lua: Fehlerhaftes Locale-System (SkuLocale) durch Sku.L ersetzt. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf Title/Version v40.04.01 aktualisiert. ------------------------------------------------------------------------------------------------------- Changes in Sku v40.04 Dungeon-Browser - Lokalisierung: Alle Menue-Eintraege des Dungeon-Browsers (Rollen, Status, Dungeon-Liste, Spielerliste, Aktionen) verwenden jetzt das Lokalisierungssystem. Auf englischen Clients erscheinen alle Texte korrekt auf Englisch. - Heroische Dungeons: Der Dungeon-Browser zeigt jetzt auch heroische Dungeons an. Diese erscheinen in einer eigenen Sektion unterhalb der normalen Dungeons mit dem Praefix "Heroisch: " vor dem Namen. Heroische Dungeons koennen wie normale Dungeons ausgewaehlt und angemeldet werden. - Tastenkuerzel: Der Dungeon-Browser hat jetzt ein eigenes Tastenkuerzel unter Shift+F1, Core, Skutastenbelegung, Taste zuweisen, "Dungeon Browser oeffnen". Standard ist keine Taste belegt; der User kann frei zuweisen. - Alle abwaehlen: Neuer Button "Alle abwaehlen" im Dungeon-Browser. Setzt alle Dungeon-Auswahlen auf einmal zurueck. - Anzeige: Der Hinweis "Ausgewaehlt" wird jetzt vor den Dungeon-Namen gesetzt (statt dahinter), damit blinde Spieler beim Durchblaettern sofort hoeren, ob ein Dungeon bereits markiert ist. - Technisch: ~39 neue L[]-Eintraege (DB_*) in beiden Locale-Dateien. Hardcoded Strings in dungeonBrowser.lua durch L[]-Aufrufe ersetzt. Zwei "not info.isHeroic"-Filter entfernt (tGetEligibleDungeons und tBuildPhaseB). Heroische Dungeons werden in Phase A als eigene Sektion mit L["DB_HeroicSection"] dargestellt. SKU_KEY_OPENDUNGEONBROWSER in SkuKeyBinds.lua definiert, Handler und Override-Binding in SkuZOptions/Core.lua. DungeonBrowserDeselectAll() setzt db.selection = {} und triggert Menu-Rebuild. Navigation / Nahe Route - Bugfix: "Nahe Route" bricht nicht mehr nach dem ersten Wegpunkt ab. Die Navigation ueber "Nahe Route" (im Questbuch und im SkuNav-Menue) wurde nach Erreichen des ersten Wegpunkts faelschlicherweise mit "Route folgen beendet" abgebrochen, anstatt zum Ziel weiterzufuehren. Dieser Fehler trat zonenuebergreifend auf und betraf alle Nahe-Route-Navigationen. Das Problem ist behoben -- Nahe Routen fuehren nun zuverlaessig bis zum Ziel. - Technisch: Die BuildChildren der "Closest route"-Handler in SkuQuest/Options.lua (Zeilen 1101ff) und SkuNav/Options.lua (Zeilen 447ff) verwendeten eine flache Struktur, die metapathFollowingStart und metapathFollowingMetapaths einmalig fuer den ersten Einstiegspunkt setzte. Der bereits korrigierte "Route"-Handler setzte in seinen Per-Entry-Point-Submenues metapathFollowingTarget = nil, was bei Menue-Navigation zwischen Geschwistern die Nahe-Route-Daten zerstoerte. Fix: Gleiche Umstrukturierung auf Per-Entry-Point-Submenues wie beim "Route"-Handler -- jeder Einstiegspunkt berechnet seine eigenen Metapaths in seiner eigenen BuildChildren-Funktion. Chat-Einladung - Bugfix: Die Einladungsfunktion im Chat-Kontextmenue (CTRL+Enter) funktioniert wieder. Bisher konnte ein Fehler auftreten, wenn InviteUnit als globale Funktion nicht verfuegbar war. - Technisch: SkuChat/Core.lua Zeile 2688: InviteUnit() durch C_PartyInfo.InviteUnit()-Fallback ersetzt (gleicher Pattern wie in SkuMob/Options.lua). Ziel-Aktionsmenue (CTRL+T) - Pet-Aktionen erweitert: Zwei neue Eintraege im Pet-Untermenue. "Zuruecklassen" schickt das Pet temporaer weg (es kann jederzeit wieder gerufen werden). "Umbenennen" oeffnet ein Eingabefeld, in dem ein neuer Name eingegeben und mit Eingabetaste bestaetigt werden kann. - Lokalisierung: Alle Eintraege des Ziel-Aktionsmenues (Untersuchen, Folgen, Handeln, Duell, Fluestern, Einladen, Freund hinzufuegen, Ignorieren, Anfuehrer uebergeben, Entfernen, Pet-Aktionen, Pet-Modus, Raid-Markierungen, Spieler melden, Pluendermethode, Instanzen zuruecksetzen, Gruppe verlassen) sind jetzt lokalisiert. Auf englischen Clients erscheinen alle Texte auf Englisch. - Technisch: SkuMob/Options.lua: ~78 neue L[]-Eintraege (MOB_*) in beiden Locale-Dateien. Alle hardcoded Strings in tRaidMarkers, tReportReasons, tLootMethods, tBuildPetModeSubmenu und tBuildTargetMenu durch L[]-Aufrufe ersetzt. PetDismiss (nur temporaer) und PetRename (ueber EditBoxPasteShow) als neue tAddAction-Eintraege im tIsPet-Zweig. Charakterfenster (Equipment-Slots) - Bugfix: Wizard Oil, Gifte und Schleifsteine koennen jetzt ueber das Sku-Menue auf ausgeruestete Waffen angewendet werden, ohne ADDON_ACTION_FORBIDDEN-Fehler. Bisher wurde der Klick auf Equipment-Slots aus dem Addon-Kontext ausgefuehrt, was von Blizzard blockiert wurde. - Technisch: SkuZOptions/Core.lua Zeile 3958: Equipment-Slot-Linksklick verwendet jetzt macrotext ("/click SlotName LeftButton") statt reinem OnAction mit PickupInventoryItem. Dadurch laeuft der Klick im Hardware-Event-Kontext und Blizzard erlaubt die Interaktion. Der bisherige OnAction-Code bleibt als Fallback erhalten. Rollenabfrage - Bugfix: Die manuelle Rollenabfrage (Tank/Heiler/Schaden) verursacht keinen Absturz mehr. Bisher konnte ein Fehler auftreten, wenn die Rollenbuttons keine .role-Eigenschaft hatten, was zu einem nil-Fehler fuehrte und einen Reload erforderte. - Technisch: SkuCore/LocalMenu.lua Zeile 2026: Nil-Guard und Fallback-Rollennamen (TANK/HEALER/DAMAGER) eingefuegt. tButtons[x] wird zusaetzlich auf Existenz geprueft. Aura-Export - Bugfix: "Alle Auren exportieren" funktioniert wieder und wirft keinen Fehler mehr. Die Funktion GetAddOnMetadata war in neueren WoW-Versionen nicht verfuegbar und verursachte beim Export einen Absturz. - Technisch: SkuAuras/Options.lua Zeile 812: GetAddOnMetadata durch sicheren Fallback-Pattern ersetzt (GetAddOnMetadata oder C_AddOns.GetAddOnMetadata, mit "unknown" als letztem Fallback). Gleicher Fix auch in SkuZOptions/Core.lua Zeile 5252 (Wegpunkt-Export). /sku version Befehl - Bugfix: Der Chat-Befehl "/sku version" gibt jetzt zuverlaessig die Addon-Version aus. Bisher konnte die Ausgabe leer bleiben, wenn GetAddOnInfo nicht verfuegbar war. - Technisch: SkuZOptions/Core.lua Zeile 128: GetAddOnInfo durch sicheren GetAddOnMetadata-Fallback ergaenzt (gleicher Pattern wie ErrorLog.lua). Ausgabe zeigt jetzt Titel und Versionsnummer. Minimap-Ressourcen-Scan - Bugfix: Die passive Minimap-Ueberwachung (Erz, Kraeuter, etc.) faengt keine Mausklicks mehr ab. Bisher konnte beim Klicken an verschiedenen Stellen im Addon ein "Ping"-Geraeusch ertoennen und der Klick wurde nicht ausgefuehrt, weil die unsichtbare 1-Pixel-Minimap unter dem Cursor Klicks abgefangen hat. - Technisch: SkuCore/minimapScanner.lua: In MinimapScanFast() werden jetzt vor dem Positionieren der Minimap unter den Cursor alle sichtbaren Minimap-Kinder (insbesondere MiniMapTrackingFrame) versteckt. Schutz portiert aus Version 1.x (Zeilen 479-484). RestoreMinimap stellt die Kinder per MMA_VISIBLE wieder her. - Bugfix: Kraeutersuche, Bergbau und weitere Tracking-Funktionen funktionieren jetzt korrekt mit dem passiven Minimap-Scan. Bisher wurde der Tracking-Zustand bei jedem Scan-Durchlauf deaktiviert und konnte nicht wiederhergestellt werden, weil die C_Minimap.GetTrackingInfo-Rueckgabe (Tabelle statt Einzelwerte) falsch entpackt wurde. Kraeuter und Erze erschienen nicht mehr auf der Minimap, obwohl der Buff-Balken die Suche als aktiv anzeigte. - Technisch: GetTrackingInfo-Aufrufe in tCaptureMinimapState() und in der Tracking-Disable-Schleife von MinimapScanFast() verwenden jetzt den gleichen type(result)=="table"-Check wie SlashActiveSeekings und SkuZOptions/Core.lua. tCaptureMinimapState/tApplyMinimapState sichern und stellen den Tracking-Zustand korrekt wieder her. - Bugfix: Der passive Minimap-Scan kuendigt Kraeuter, Erze und andere Ressourcen beim Laufen jetzt wieder per Sprache an. Bisher blieb die Ansage aus, weil die Tooltip-Auswertung im passiven Scan-Pfad die Ressourcennamen nie korrekt erkennen konnte -- die Matching-Logik verwendete exakte Gleichheit statt Teilstring-Suche und konnte bei Sonderzeichen (Apostrophe in "Khadgar's Whisker" etc.) oder fehlenden Abhaengigkeiten den Tooltip-Text nicht zuordnen. - Technisch: C_Timer.After-Callback in MinimapScanFast() verwendet jetzt denselben string.find-Substring-Match wie der aktive Scan (MinimapScanFindActiveRessource). SkuChat:Unescape wird optional genutzt, blockiert aber nicht mehr die Verarbeitung. gmatch-Fragmentierung und exakte Gleichheitspruefung entfernt. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf Title/Version v40.04 aktualisiert. ------------------------------------------------------------------------------------------------------- Changes in Sku v40.03y Briefkasten - Mehrfach-Anhaenge: nach dem Entnehmen eines einzelnen Anhangs werden die verbleibenden Anhaenge im selben Brief wieder zuverlaessig per Sapi vorgelesen. Auto-Jump-Pfad entfernt -- der Briefkasten nutzt jetzt wieder den Standard-Refresh (MAIL_INBOX_UPDATE, currentMenuPosition:OnUpdate), exakt wie beim physischen Wieder-Oeffnen des Briefkastens. Atlas Loot - Tastenkuerzel zum Oeffnen frei umbelegbar: unter Shift+F1, Core, Skutastenbelegung, Taste zuweisen erscheint jetzt der Eintrag "Atlas Loot oeffnen". Die Standardtaste bleibt Strg+Shift+L; der User kann sie aber wie alle anderen Sku-Tastenkuerzel auf eine eigene Kombination umlegen. Die neue Belegung wird sofort wirksam. - Zielorientierter Sprung in Boss-/Instanz-Submenue deutlich verbessert: Pfad-Reihenfolge entspricht jetzt exakt der Menue-Hierarchie (Listen, Plugin, Erweiterung, Gruppe, Instanz/Raid, Boss, Schwierigkeit, Items). Die Schwierigkeitsstufe wurde vorher faelschlich vor die Instanz gesetzt -- Pfad konnte nie aufgeloest werden. Schwierigkeits-Erkennung dreifach abgesichert: primaer GetInstanceInfo, sekundaer die Charakterportrait-Einstellung (GetDungeonDifficulty / GetRaidDifficulty -- wird beim Betreten der Instanz festgenagelt und ist daher zuverlaessig), tertiaer Default "Normal" fuer Welt-Bosse. Lookup-Tabellen werden jetzt bereits beim Login (mit gestaffelten Retries 5/10/20/35/60 s) und bei Zonenwechsel ins Instanz-Innere vorbefuellt. Damit ist der Sprung beim ersten Tastendruck ohne Latenz nutzbar. - Wunschlisten-Auto-Remove: sobald der "I feel Good"-Sound spielt (Wunschlisten-Item ist im Inventar gelandet), wird das Item automatisch aus allen Wunschlisten-Slots entfernt. Vergleich primaer per itemID, mit Hyperlink-Pattern als Fallback. Items wie Ringe oder Schmuckstuecke, die in zwei Slots gleichzeitig stehen koennen, werden vollstaendig abgeraeumt. Charakterfenster (Equipment-Slots) - Linksklick / Rechtsklick auf ausgeruestete Items funktioniert wieder. Auf TBC-Anniversary 2.5.5 ruft /click LeftButton ohne Modifier-Taste nur UseInventoryItem auf -- wirkungslos fuer Ruestung, Ringe und Schmuckstuecke. Sku nutzt fuer Equipment-Slots jetzt den direkten API-Pfad: Linksklick: PickupInventoryItem(slotID) -- Item heftet sich an den Cursor (zum Umsetzen, Verkaufen oder Abstecken). Rechtsklick: ausziehen -- PickupInventoryItem + Iteration ueber die Taschen, erstes freies Fach, PickupContainerItem. Bei vollen Taschen Cursor leeren und Sapi-Hinweis "Keine Tasche frei". Bei leerem Slot Sapi-Hinweis "Leer". Dungeon-Browser - Auto-Refresh entfernt: die Spielerliste wird nicht mehr automatisch alle 10 Sekunden aktualisiert. Der bisherige Ticker griff faelschlich auf alle Sku-Menues durch (currentMenuPosition:OnUpdate unabhaengig vom aktuellen Menue-Pfad) und unterbrach Ansagen in komplett unbeteiligten Untermenues. - Manueller "Liste aktualisieren"-Button: loest /who-Suche aus und rebuildet das Dungeon-Browser-Menue gezielt nach 0,6 s. Cross-Menue-Schutz: wenn der User in der Zwischenzeit wegnavigiert ist, passiert nichts. - Sapi-Feedback nach erfolgreichem Refresh: "Aktualisiert. N Spieler gefunden" (oder "Keine Spieler gefunden" / "1 Spieler gefunden"). Wird zeitversetzt nach der OnUpdate-Vokalisierung abgesetzt, damit die Status-Ansage nicht unterdrueckt wird. - Phasenwechsel A nach B (Anmeldung): zwei zeitversetzte Paesse -- erster Pass mit Sapi-Ansage des neuen Status, zweiter Pass stumm im Hintergrund (DungeonBrowserRebuildSilent), um die per /who eingelaufenen Spieler nachzuziehen. Status-Ansage laeuft jetzt vollstaendig durch, und die Spielerliste ist trotzdem sofort gefuellt. - Phasenwechsel B nach A (Abmeldung): Doppel-Rebuild auf einen reduziert; Sapi-Ansage wird nicht mehr abgeschnitten. - Verhalten bei Gruppeneinladung: Sku-Menue bleibt waehrend eines offenen Einladungs-Popups offen. Skus Standard-Pfad fokussiert das Popup, der User kann direkt mit Ja/Nein interagieren. Bei Annehmen schliesst Blizzard das Container-Frame automatisch -- Sku-Menue folgt und schliesst sich. Bei Ablehnen bleibt das Container-Frame stehen und das Sku-Menue ebenfalls. Stabilitaet / Quest-Tooltip - Crash beim Quest-Tooltip-Aufruf (Shift+Pfeil-Runter) im Schattenmondtal behoben. Ursache: tInternalChannelName konnte in CHAT_MSG_CHANNEL_NOTICE/YOU_LEFT nil werden (zonen-spezifischer Channel ohne Mapping), string.lower(nil) crashte. Der nachfolgende Lua-Error riss den currentMenuPosition-Pointer mit sich, wodurch alle weiteren Pfeil-/Enter-Tastendrucke mit "attempt to index nil" kaskadierten -- Sku-Menue blieb bis zum Reload unbedienbar. - Drei zusammenwirkende Schutzschichten: 1. Direkter nil-Guard in SkuChat/Core.lua vor dem string.lower-Aufruf. 2. Defensiver nil-Schutz im SkuGenericMenuItem-OnUpdate (templates.lua) fuer currentMenuPosition:OnEnter / VocalizeCurrentMenuName. 3. Recovery-Guard im OnClick-Key-Dispatcher: bei nil-currentMenuPosition wird Menu[1] als Fallback gesetzt, andernfalls der Tastendruck still verworfen -- kein Crash-Spam mehr. Versionsanzeige - Sku.toc und SkuDispatcher/Sku.toc auf Title/Version v40.03y aktualisiert. -------------------------------------------------------------------------------------------------------