Modèles de code d’addon WoW Forever à coller

Publié le Mis à jour le Rapports de la bêta de la build 1.60.1.69913

Partager

Guide des addons page 5 sur 7

Copiez ces modèles pour l’interface 16001 : hello world, SavedVariables, barre sécurisée contre les secrets, Addon Compartment et verrouillage du combat. Ils suivent la documentation Mainline du Warcraft Wiki, donc vérifiez chacun sur votre build bêta.

Posez vos questions sur les modèles de code d’addon à notre IA de tryhardeur dégénéré

Hello World, SavedVariables, barres sûres pour les secrets, compartiment d’addon et plus

Tout ce que couvrent nos guides. Les réponses proviennent de cette page et du reste de nos guides, avec les vraies valeurs en graphique et les sections de guide liées. C’est une IA : vérifiez la source avant de la citer.

Chaque bloc est un pattern complet pour l’interface 16001. Le nom du dossier et celui du fichier TOC doivent correspondre.

Interface TOC
16001
SavedVariables
Bug signalé comme corrigé
Addon compartment
Non testé ici
Verrouillage du combat
File d’attente jusqu’à la régénération

Cette bibliothèque fait partie du guide du développeur d’addons WoW Forever. Pour la conception côté client derrière ces extraits, voir les patterns d’addons WoW Forever. Pour vérifier chaque signature, utilisez l’aide-mémoire de l’API Forever. Pour un addon fini et téléchargeable qui relie notes, sonde, compartment et barre sécurisée contre les secrets, consultez l’addon de référence Forever Beacon.

Ce site n’a exécuté aucun de ces modèles dans un client Forever. Ils suivent la documentation Mainline du Warcraft Wiki, les rapports de la bêta cités et le code client de Blizzard conservé de la build 70338. La sonde d’ID de projet distincte a été exécutée en jeu ; cela ne signifie pas que ces exemples ont été testés en jeu.

Les ajouts du 13 octobre citent l’extrait client conservé 70338. Les miroirs de sources liés peuvent afficher une build plus récente.

Fonctions avec plusieurs commandes

Une fonction Lua peut contenir plusieurs instructions. Placez chaque opération sur sa propre ligne entre function et end ; elles s’exécutent dans l’ordre lorsque vous appelez la fonction. Cet exemple affiche un message local et joue un son d’interface :

Ready.lua
local function AnnounceReady()
    print("[Forever Notes] Ready.")
    PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON)
end

AnnounceReady()

Vous n’avez pas besoin de plusieurs définitions de fonction ni de points-virgules. Un return anticipé termine la fonction, et une erreur non interceptée arrête les instructions restantes.Source : Lua 5,1 Reference Manual, function definitions and blocks et error handling, vérifiés le 13 oct. 2026. Les instructions Lua diffèrent des commandes slash de macros telles que /cast. Ces exemples affichent du texte et jouent un son ; ils ne réalisent pas d’actions de combat protégées.

Dans la discussion, le diagnostic équivalent est /run print("Ready."); PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON). Gardez le code réutilisable dans un fichier Lua répertorié dans votre TOC. L’aide-mémoire des ID de sons liste les constantes utilisées ici.

Commande de message et alias de commandes slash

Pour un message visible uniquement par vous, utilisez print("Hello.") ou DEFAULT_CHAT_FRAME:AddMessage("Hello.", 1, 0.82, 0). Dans la discussion, tapez /run print("Hello."). L’affichage est local ; cela n’envoie ni message de groupe ni chuchotement.

Pour définir une fonction avec plusieurs commandes slash, donnez à la même clé SlashCmdList des alias numérotés. Cet exemple complet à deux fichiers fait afficher le texte fourni localement par /wfgmessage Hello et /wfgmsg Hello :

WFGMessageExample.toc
## Interface: 16001
## Title: WFG Message Example
## Notes: Two slash commands for one local message handler.
## Version: 0.1.0

WFGMessageExample.lua
WFGMessageExample.lua
local function ShowLocalMessage(text)
    if not text:find("%S") then
        print("Usage: /wfgmessage Hello")
        return
    end
    DEFAULT_CHAT_FRAME:AddMessage("[WFG Message] " .. text, 1, 0.82, 0)
end

SLASH_WFGMESSAGEEXAMPLE1 = "/wfgmessage"
SLASH_WFGMESSAGEEXAMPLE2 = "/wfgmsg"
SlashCmdList["WFGMESSAGEEXAMPLE"] = ShowLocalMessage

Utilisez le nom de dossier WFGMessageExample, puis redémarrez le client lors de l’ajout. La clé d’enregistrement en majuscules doit correspondre aux deux variables globales SLASH_. Enregistrez les alias au chargement du fichier, pas à chaque exécution du gestionnaire. Le registre de commandes slash de Blizzard utilise ce même modèle de variables globales numérotées.Source : registre de commandes slash de Blizzard, build du client conservée 70338, inspectée le 13 oct. 2026.

Si "message command" désigne l’envoi de messages à d’autres personnes, c’est une opération distincte : C_ChatInfo.SendChatMessage("Hello.", "PARTY") envoie un message de groupe lorsque le client l’autorise. Appelez-la uniquement à la suite d’une action délibérée du joueur et vérifiez les restrictions actuelles de discussion. La documentation générée marque cette API HasRestrictions ; cette page n’affirme pas que l’envoi automatisé arbitraire est autorisé.Source : documentation ChatInfo de Blizzard, SendChatMessage, build du client conservée 70338, inspectée le 13 oct. 2026.

Afficher un message dans une fenêtre

Enregistrez une entrée propre à l’addon dans StaticPopupDialogs, puis appelez StaticPopup_Show avec cette clé. Cet exemple affiche un message d’information fixe avec un bouton OK et une fermeture par Échap. Placez-le dans un fichier Lua chargé par votre TOC :

PopupMessage.lua
StaticPopupDialogs["WFG_EXAMPLE_READY_MESSAGE"] = {
    text = "Forever Notes is ready.",
    button1 = OKAY,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
}

SLASH_WFGPOPUPEXAMPLE1 = "/wfgpopup"
SlashCmdList["WFGPOPUPEXAMPLE"] = function()
    StaticPopup_Show("WFG_EXAMPLE_READY_MESSAGE")
end

Après avoir chargé l’addon, tapez /wfgpopup. Le message reste affiché jusqu’à sa fermeture car timeout = 0. Utilisez votre propre clé, gardez intactes les définitions de fenêtres de Blizzard et demandez délibérément l’ouverture plutôt que de la répéter dans une boucle de mise à jour. Cet exemple n’a pas été exécuté dans le client Forever.Source : implémentation StaticPopup de Blizzard, StaticPopup_Show, timeout, whileDead et hideOnEscape, build du client conservée 70338, inspectée le 13 oct. 2026.

Hello

Le plus petit addon possible : il affiche un message à la connexion et ne touche jamais un nom qui pourrait être secret.

HelloForever.toc
## Interface: 16001
## Title: Hello Forever
## Notes: Prints once on login, without touching a secret name.
## Author: YourName
## Version: 0.1.0
## Category: Miscellaneous

HelloForever.lua
HelloForever.lua
local addonName = ...
local frame = CreateFrame("Frame")
frame:SetScript("OnEvent", function()
    print("|cffd4a85a[" .. addonName .. "]|r Forever client accepted this addon.")
end)
frame:RegisterEvent("PLAYER_LOGIN")

SavedVariables

Déclarez la table dans le TOC : ## SavedVariables: BeaconNotesDB. Le nom est une globale, car le client la remplit après l’exécution de vos fichiers. Ne la touchez que dans ADDON_LOADED, et fusionnez les clés par défaut pour ne jamais écraser les paramètres d’un joueur.

SavedVariables.lua
local addonName, ns = ...
local defaults = { scale = 1, locked = false }

local events = {}
function events:ADDON_LOADED(loaded)
    if loaded ~= addonName then return end
    BeaconNotesDB = BeaconNotesDB or {}
    local db = BeaconNotesDB
    for key, value in pairs(defaults) do
        if db[key] == nil then db[key] = value end
    end
    ns.db = db
end

local frame = CreateFrame("Frame")
frame:SetScript("OnEvent", function(self, event, ...)
    if events[event] then events[event](self, ...) end
end)
frame:RegisterEvent("ADDON_LOADED")

Ne définissez pas BeaconNotesDB = BeaconNotesDB or {} au niveau du fichier. C’est le piège 08 des pièges courants des addons écrits par IA.

Barre sécurisée contre les secrets

Sur la build 69913, UnitHealth("player") est revenu sous forme de nombre secret. Les règles Midnight du Warcraft Wiki disent que UnitHealthMax peut aussi être secret. Vous ne pouvez pas en calculer un pourcentage en Lua, mais un StatusBar les accepte directement.

HealthBar.lua
local bar = CreateFrame("StatusBar", nil, UIParent)
bar:SetSize(200, 14)
bar:SetPoint("CENTER", 0, -40)
bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
bar:SetStatusBarColor(0.55, 0.12, 0.12)

local function Paint()
    -- Both values may be secret. The bar may have them. Lua may not do math on them.
    bar:SetMinMaxValues(0, UnitHealthMax("player"))
    bar:SetValue(UnitHealth("player"))
end

local frame = CreateFrame("Frame")
frame:SetScript("OnEvent", Paint)
frame:RegisterUnitEvent("UNIT_HEALTH", "player")
frame:RegisterUnitEvent("UNIT_MAXHEALTH", "player")
frame:RegisterEvent("PLAYER_ENTERING_WORLD")

Addon Compartment

L’Addon Compartment de la minicarte n’a pas besoin de LibDataBroker : le TOC nomme des fonctions globales et le client les appelle. Le Warcraft Wiki documente ces champs pour Mainline. Ce site ne les a pas testés sur un client Forever, vérifiez donc que l’entrée apparaît.

CompartmentStub.toc
## Interface: 16001
## Title: Compartment Stub
## Notes: Minimap compartment without LibDataBroker.
## IconTexture: Interface\Icons\INV_Misc_Note_01
## AddonCompartmentFunc: CompartmentStub_OnClick
## AddonCompartmentFuncOnEnter: CompartmentStub_OnEnter
## AddonCompartmentFuncOnLeave: CompartmentStub_OnLeave

CompartmentStub.lua
CompartmentStub.lua
function CompartmentStub_OnClick()
    print("|cffd4a85a[Stub]|r compartment click")
end

function CompartmentStub_OnEnter(_, owner)
    GameTooltip:SetOwner(owner, "ANCHOR_LEFT")
    GameTooltip:SetText("Compartment Stub", 1, 0.82, 0.45)
    GameTooltip:Show()
end

function CompartmentStub_OnLeave()
    GameTooltip:Hide()
end

File d’attente du verrouillage du combat

En combat, tant que InCombatLockdown() est vrai, les addons ne peuvent ni afficher, ni masquer, ni déplacer les cadres protégés, ni changer leurs attributs. Mettez ces changements en file d’attente et exécutez-les quand PLAYER_REGEN_ENABLED se déclenche.

Queue.lua
local pending = {}

local function Queue(fn)
    if InCombatLockdown() then
        pending[#pending + 1] = fn
    else
        fn()
    end
end

local frame = CreateFrame("Frame")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")
frame:SetScript("OnEvent", function()
    for i = 1, #pending do pending[i]() end
    wipe(pending)
end)

-- Use Queue only for protected frames.
-- Your own unprotected frames may Show() during combat.

Pour des prompts qui produisent du code sous cette forme, voir les prompts IA prêts à l’emploi.

Écrire pour Forever ; comparer la constante nommée d’ID de projet

WOW_PROJECT_IDvalait 18 dans la sonde en direct conservée sur la build bêta Forever 1.60.1.70338, le 12 octobre 2026. Le code source de Blizzard nomme cette valeur WOW_PROJECT_CAMELOT. WOW_PROJECT_MAINLINE valait 1 et WOW_PROJECT_CLASSIC valait 2 ; la branche habituelle if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE était donc fausse sur cette build. L’ancien rapport communautaire de 1 concerne la build 69913 ; conservez son numéro de build au lieu de le traiter comme la constante actuelle.Source : constantes de projet Camelot de Blizzard, fichiers du client 70338 conservés, inspectés le 13 oct. 2026. Constantes mesurées dans le client bêta 1.60.1.70338 le 12 oct. 2026.

Un addon qui ne tourne que sur Forever n’a rien à brancher. Écrivez la version Forever et dites-le en commentaire, pour que le prochain lecteur ne cherche pas la branche.

Detect.lua
-- Build 70338 recorded WOW_PROJECT_ID 18, named WOW_PROJECT_CAMELOT.
-- WOW_PROJECT_MAINLINE was 1 and WOW_PROJECT_CLASSIC was 2, so an
-- "is this Retail" or "is this Classic" branch was false; retest.
-- A Forever-only add-on writes for Forever directly.
local FOREVER_PROJECT_ID = WOW_PROJECT_CAMELOT

L’ancien exemple du wiki nomme une branche "camelot/forever" parce que Forever est un type de jeu au sein de la famille Mainline. Cette architecture commune ne détermine pas son ID de projet. La déclaration de Blizzard sur le Discord WoW UI, citée par Wowhead, décrit Forever et Midnight comme "two game types within the Mainline code family." (« deux types de jeu au sein de la famille de code Mainline »). La même déclaration nomme le type de Forever "Camelot (to be renamed before launch)" (« Camelot, qui sera renommé avant le lancement ») et indique que Forever partage "the vast majority of APIs available in 12.1.5," (« la grande majorité des API disponibles dans cette version »), ce qui explique pourquoi les pages Mainline du wiki ci-dessous s’appliquent.Source : WoW: Forever Will Have Addon Changes from Midnight, vérifié le 28 sept. 2026.

Pour les addons communs à plusieurs clients, comparez WOW_PROJECT_ID à WOW_PROJECT_CAMELOT lorsque cette constante existe, puis vérifiez l’API de la fonctionnalité. Un addon réservé à Forever peut cibler Forever directement. Vous pouvez aussi séparer les fichiers via le TOC. Pour les règles actuelles, le statut Hardcore ou le préréglage d’expérience Classic/Modern, utilisez la référence GameRules ; un ID de client ne répond pas à ces questions.

<details><summary>Notes techniques : constantes d’extension</summary>

L’exemple du wiki conservé imbrique LE_EXPANSION_LEVEL_CURRENT et LE_EXPANSION_CLASSIC dans sa branche d’ID de projet Mainline. Cette branche est fausse sur le client Forever 70338 capturé. Le client de l’ère Midnight est un autre type de jeu de la famille Mainline ; ne déduisez pas son ID de projet de ce lien.

</details>

Séparer les fichiers avec des variables TOC

Les variables TOC [Family] et [Game] sont résolues au chargement : un seul AddonName.toc peut donc pointer vers des fichiers différents selon le client, sans aucune branche Lua.

Split.toc
## Interface: 16001
## Title: Split Example

[Family]\File.lua
[Game]\File.lua

[Family]devient Mainline ou Classic. [Game] devient Camelot sur un client Forever. Les autres types de jeu listés sont Standard, Vanilla et TBC.Source : format TOC, vérifié le 28 sept. 2026.

La même page répertorie un suffixe camelot propre au client, de sorte que AddonName_Camelot.toc se charge à la place du fichier par défaut. Sa table d’interface place 16001 sur la ligne « Forever Beta » et laisse « Forever Test » et « Forever » vides : ne supposez donc pas que ce numéro survive après la bêta.

Rechercher un objet sans course contre le cache

C_Item.GetItemInforenvoie 18 valeurs distinctes, et non une table : nom, lien, qualité, niveau, et ainsi de suite jusqu’à itemDescription. Il répond nil tant que le client n’a pas mis cet objet en cache, que l’objet existe ou non.Source : C_Item.GetItemInfo, vérifié le 28 sept. 2026.

Demander les données, puis lire l’événement

ItemLookup.lua
local function OnItemData(_, event, itemID, success)
    if not success then return end
    local name = C_Item.GetItemInfo(itemID)
    if name then print(name, "is cached now") end
end

local frame = CreateFrame("Frame")
frame:SetScript("OnEvent", OnItemData)
frame:RegisterEvent("ITEM_DATA_LOAD_RESULT")

C_Item.RequestLoadItemDataByID(4306)

Depuis le patch 10.0.5, le serveur peut répondre success = false pour un ID d’objet précis ; vérifiez donc ce drapeau avant d’appeler à nouveau GetItemInfo sur la même session.Source : ITEM_DATA_LOAD_RESULT, vérifié le 28 sept. 2026.

RequestLoadItemDataByID accepte aussi un lien d’objet complet, ce qui permet de transmettre tel quel ce qu’un hook d’infobulle ou un lien de chat vous a fourni, sans extraire d’abord l’ID numérique.

Rechercher un sort de la même façon

C_Spell.GetSpellInforenvoie une seule table, contrairement à l’appel pour les objets : spellInfo.name, spellInfo.iconID, spellInfo.castTime et le reste. Il a remplacé les anciennes fonctions GetSpellInfo et C_SpellBook.GetSpellInfo, qui étaient globales.Source : C_Spell.GetSpellInfo, vérifié le 28 sept. 2026.

SpellLookup.lua
local function OnSpellData(_, event, spellID, success)
    local info = C_Spell.GetSpellInfo(spellID)
    if not info then return end
    -- success == false can still mean a partial record, such as no description.
    print(info.name, info.castTime, success and "full" or "partial")
end

local frame = CreateFrame("Frame")
frame:SetScript("OnEvent", OnSpellData)
frame:RegisterEvent("SPELL_DATA_LOAD_RESULT")

C_Spell.RequestLoadSpellData(2061)

Le wiki précise que success "Might return false when only partial spell data is available," (« peut renvoyer false quand seules des données partielles du sort sont disponibles »), par exemple tout sauf la description.Source : SPELL_DATA_LOAD_RESULT, vérifié le 28 sept. 2026. C’est pourquoi le modèle lit la table même sur un résultat false au lieu de s’arrêter. La liste des pièges de l’IA pour les addons couvre d’autres endroits où une réponse générée oublie une protection de ce genre.

Les deux appels acceptent un ID ou un nom de sort. Si vous passez un nom, C_Spell.GetSpellInfo cherche d’abord le remplacement actuel de ce sort pour le joueur ; une capacité transformée peut donc renvoyer l’icône du sort qui la remplace.

Différer une tâche sans script OnUpdate

C_Timer.Afterplanifie un rappel unique. Un post de Blizzard cité sur le wiki indique que le système de minuteurs ne travaille que lorsqu’un minuteur est créé ou détruit, alors qu’un gestionnaire OnUpdate coûte un appel Lua à chaque frame affichée.Source : C_Timer.After, vérifié le 28 sept. 2026.

Debounce.lua
local pendingSave = false

local function ScheduleSave()
    if pendingSave then return end
    pendingSave = true
    C_Timer.After(2, function()
        pendingSave = false
        -- update an in-memory table or refresh a preview here
    end)
end

Use this to debounce follow-up work after a setting changes, such as updating an in-memory table or refreshing a preview. The timer does not write SavedVariables to disk; the client persists declared variables on logout or UI reload.

Lire les métadonnées de votre propre TOC

C_AddOns.GetAddOnMetadata(name, variable)lit Title, Notes, Author, Version ou tout champ X- personnalisé directement depuis votre propre fichier TOC, sans tenir compte de la casse.Source : C_AddOns.GetAddOnMetadata, vérifié le 28 sept. 2026.

Version.lua
local addonName = ...
local version = C_AddOns.GetAddOnMetadata(addonName, "Version") or "dev"
print(("%s v%s loaded"):format(addonName, version))

Contrairement à l’ancien global GetAddOnMetadata, cet appel lève une erreur pour un nom qui ne correspond à aucun addon installé ; enveloppez donc toute recherche dont vous n’êtes pas sûr dans pcall. Affichez la version dans une infobulle du compartiment pour qu’un joueur qui signale un bug puisse vous la donner sans ouvrir le fichier TOC.

Ajouter un panneau d’options avec l’API Settings

Le wiki indique que l’API Settings a été refaite dans le patch 10.0.0, avec d’autres changements cassants dans le patch 11.0.2. Le code d’options copié d’un tutoriel antérieur au patch 10,0 ne correspondra pas aux appels ci-dessous, pas plus qu’une réponse d’IA entraînée sur ces tutoriels.Source : Settings API, vérifié le 28 sept. 2026.

Options.lua
local addonName, ns = ...

function ns.BuildOptions(db)
    local category = Settings.RegisterVerticalLayoutCategory("Beacon Notes")
    local setting = Settings.RegisterAddOnSetting(
        category, "BeaconNotes_Locked", "locked", db,
        "boolean", "Lock the notes frame", false
    )
    Settings.CreateCheckbox(category, setting, "Prevents dragging the frame.")
    Settings.RegisterAddOnCategory(category)
end

-- Call ns.BuildOptions(ns.db) at the end of your ADDON_LOADED handler.

Construisez le panneau dans ADDON_LOADED, une fois que le modèle SavedVariables ci-dessus a rempli la table. Au niveau du fichier, la table sauvegardée n’existe pas encore, et le réglage serait donc lié à nil.

Définir un repère sans appel protégé

Un rapport de bêta de la communauté sur Warcraft Forever indique que C_SuperTrack.SetSuperTrackedUserWaypoint est protégé sur ce client. L’appel échoue en silence et ajoute seulement un au compteur d’erreurs d’interface du panneau AddOns, qui "only resets on a full client restart, not on /reload."Source : Addons, vérifié le 28 sept. 2026. (« ne se réinitialise qu’au redémarrage complet du client, pas avec /reload »). Le même rapport cite C_Map.SetUserWaypoint comme moyen sûr de poser un repère. Considérez les deux comme non confirmés tant que vous ne les avez pas testés.

Les repères sont le terrain des addons de guides. Zygor Guides met en avant une "3D Waypoint Arrow" et RestedXP a pour slogan "Follow the arrow" ; vérifiez donc comment se comporte un addon d’itinéraire sur la bêta avant de bâtir votre propre code de repères par-dessus.

Waypoint.lua
local mapID = C_Map.GetBestMapForUnit("player")

if mapID and C_Map.CanSetUserWaypointOnMap(mapID) then
    local pos = C_Map.GetPlayerMapPosition(mapID, "player")
    if pos then
        C_Map.SetUserWaypoint(UiMapPoint.CreateFromVector2D(mapID, pos))
    end
end

Le même rapport range aussi ChatFrame_OpenChat et l’écriture d’attributs sécurisés sur les cadres d’unité de Blizzard parmi les opérations protégées, avec HandleModifiedItemClick comme voie sûre pour les liens par Maj+clic. Aucune des trois ne lève d’erreur interceptable : une enveloppe pcall ne vous dira donc pas que l’appel a échoué. Comparez un nouveau modèle avec le guide du développeur d’addons et le téléchargement de Forever Beacon avant de le publier, car rien sur cette page n’a encore été exécuté sur un client Forever.

Faits clés

  • Interface TOC Modifiée16001 dans la ligne Forever Beta du tableau TOC du Warcraft Wiki ; vérifiez avec /dump select(4, GetBuildInfo())Classic : Classic Era indique 11509 dans le même tableau.
  • SavedVariablesRapportées comme perdues entre deux sessions à la mi-septembre ; une réponse du 25 septembre indique que la build 70009 les recharge
  • Addon compartment Nouveau dans ForeverLes champs TOC sont documentés pour Mainline ; pas encore testés ici sur un client Forever
  • Verrouillage du combat Identique à ClassicLes cadres protégés ne peuvent pas être affichés, masqués ni déplacés en combat ; mettez en file d’attente jusqu’à PLAYER_REGEN_ENABLED

Sources

  1. TOC formatWarcraft Wiki
  2. Saving variables between game sessionsWarcraft Wiki
  3. WOWF Beta: Addon SavedVariables appear to write correctly to disk but are not restored at startupWorld of Warcraft Forums (player bug report)
  4. Addon compartmentWarcraft Wiki
  5. InCombatLockdownWarcraft Wiki
  6. Secret ValuesWarcraft Wiki
  7. AddonsWarcraft Forever
  8. WOW_PROJECT_IDWarcraft Wiki
  9. WoW: Forever Will Have Addon Changes from MidnightWowhead
  10. C_Item.GetItemInfoWarcraft Wiki
  11. ITEM_DATA_LOAD_RESULTWarcraft Wiki
  12. C_Spell.GetSpellInfoWarcraft Wiki
  13. C_Timer.AfterWarcraft Wiki
  14. C_AddOns.GetAddOnMetadataWarcraft Wiki
  15. Settings APIWarcraft Wiki
  16. What the WoW Forever beta breaks for addons: secret health values, dead secure snippets, new APIsWoW Forever Builds
  17. SPELL_DATA_LOAD_RESULTWarcraft Wiki
  18. RestedXP home pageRestedXP
  19. Zygor Guides home pageZygor Guides
  20. Blizzard client source: ProjectConstants.lua (retained build 70338; mirror may change)Blizzard Entertainment (source mirrored by Gethe)
  21. Blizzard client source: SlashCommandsRegistry.lua (retained build 70338; mirror may change)Blizzard Entertainment (source mirrored by Gethe)
  22. Blizzard client source: StaticPopup.lua (retained build 70338; mirror may change)Blizzard Entertainment (source mirrored by Gethe)
  23. Lua 5.1 Reference ManualLua.org
  24. Blizzard client source: ChatInfoDocumentation.lua (retained build 70338; mirror may change)Blizzard Entertainment (source mirrored by Gethe)