Опишите аддон одним предложением и скачайте готовый к установке zip. Это бесплатно и не требует аккаунта. Все используемые глобальные функции и события проверяются по списку API сборки Forever 70338.
Спросите нашего потного ИИ-задрота о конструкторе аддонов
Опишите аддон, что мы проверяем, исправление после патча, проверенные примеры и другое
Всё, что охватывают наши гайды. Ответы берутся с этой страницы и из остальных гайдов, с реальными значениями на графиках и ссылками на разделы гайдов. Это ИИ, поэтому проверяйте источник, прежде чем цитировать.
Попробуйте
Опишите аддон
Бесплатно. Без регистрации. Код остается у вас. Сломалось после патча? Вставьте ошибку, и мы исправим.
Создание своих аддонов отключено. Восемь проверенных примеров по-прежнему можно скачать.
Выберите пример или опишите свой аддон.
Ваш аддон
Еще не тестировался в игре. Клиент 1.60.1.70338.
Уведомление об ИИ: создано в конструкторе аддонов WoW Forever Guides (Claude), проверено по списку API клиента Forever.
local ADDON = ...
local NAME = "GuildChatFilter"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local seen = {}
local function repeatSpam(message)
local now = GetTime()
local count = 0
local kept = {}
for i = 1, #seen do
if now - seen[i].at < 30 then
kept[#kept + 1] = seen[i]
if seen[i].text == message then count = count + 1 end
end
end
kept[#kept + 1] = { text = message, at = now }
seen = kept
return count >= 2
end
local function filter(_, _, message)
if type(message) ~= "string" or message == "" then return false end
local hide = false
safeCall(function() hide = repeatSpam(message) end)
return hide
end
ChatFrame_AddMessageEventFilter("CHAT_MSG_GUILD", filter)
SLASH_GUILDCHATFILTER1 = "/guildfilter"
SlashCmdList["GUILDCHATFILTER"] = function(msg)
if msg == "errors" then showErrors() else print(NAME .. ": hiding guild lines that repeat within 30 seconds") end
end
Подсвечивать предметы для заданий
Выводит предметы для заданий из ваших сумок золотой строкой. Здесь у Forever нет безопасного способа подсветить кнопку сумки, поэтому сигналом служит список.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
local ADDON = ...
local NAME = "QuestItemSparkle"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local frame = CreateFrame("Frame", "QuestItemSparkleFrame", UIParent)
frame:SetSize(240, 72)
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 160)
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
frame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("CENTER")
label:SetText("QuestItemSparkleFrame")
local function scan()
local lines = {}
for bag = 0, 4 do
local slots = C_Container.GetContainerNumSlots(bag) or 0
for slot = 1, slots do
local isQuest = C_Container.GetContainerItemQuestInfo(bag, slot)
if isQuest then
local info = C_Container.GetContainerItemInfo(bag, slot)
local name = info and info.itemID and C_Item.GetItemInfo(info.itemID) or nil
lines[#lines + 1] = name or "Quest item"
end
end
end
if #lines == 0 then label:SetText("No quest items in your bags")
else label:SetText(table.concat(lines, "\n")) end
end
frame:RegisterEvent("BAG_UPDATE")
frame:RegisterEvent("PLAYER_LOGIN")
frame:SetScript("OnEvent", function() safeCall(scan) end)
SLASH_QUESTITEMSPARKLE1 = "/questitems"
SlashCmdList["QUESTITEMSPARKLE"] = function(msg)
if msg == "errors" then showErrors() else scan() end
end
Автоматически отклонять приглашения в группу
Отклоняет приглашение в группу при его получении. Отключается командой /declineinvites off.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
local ADDON = ...
local NAME = "DeclineInvites"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local on = true
local frame = CreateFrame("Frame")
frame:RegisterEvent("PARTY_INVITE_REQUEST")
frame:SetScript("OnEvent", function()
if not on then return end
safeCall(function()
DeclineGroup()
StaticPopup_Hide("PARTY_INVITE")
print(NAME .. ": declined a party invite")
end)
end)
SLASH_DECLINEINVITES1 = "/declineinvites"
SlashCmdList["DECLINEINVITES"] = function(msg)
if msg == "errors" then showErrors() return end
if msg == "off" then on = false print(NAME .. ": off") return end
on = true
print(NAME .. ": on")
end
Считать всех убитых мной мобов
Считает убийства группы для этого персонажа, в том числе без опыта и в группе. Счетчики хранятся в SavedVariables.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
## Interface: 16001
## Title: Local Kill Count
## Notes: Local kill counts. No mob database.
## Author: You
## Version: 1.0.0
## X-Generator: WoW Forever Guides Addon Maker
## X-License: CC0 (public domain)
## SavedVariables: LocalKillCountDB
LocalKillCount.lua
LocalKillCount/LocalKillCount.lua
local ADDON = ...
local NAME = "LocalKillCount"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
LocalKillCountDB = LocalKillCountDB or { total = 0, xp = 0, gray = 0, grouped = 0 }
local function bump(key)
LocalKillCountDB[key] = (LocalKillCountDB[key] or 0) + 1
end
local frame = CreateFrame("Frame")
frame:RegisterEvent("PARTY_KILL")
frame:SetScript("OnEvent", function()
safeCall(function()
local before = UnitXP("player")
local grouped = IsInGroup()
C_Timer.After(0.5, function()
safeCall(function()
bump("total")
if grouped then bump("grouped") end
local after = UnitXP("player")
if issecretvalue(before) then return end
if issecretvalue(after) then return end
if after == before then bump("gray") else bump("xp") end
end)
end)
end)
end)
local function report()
local db = LocalKillCountDB
print(NAME .. ": " .. (db.total or 0) .. " kills, " .. (db.xp or 0) .. " with XP, " .. (db.gray or 0) .. " with no XP, " .. (db.grouped or 0) .. " while grouped")
end
SLASH_LOCALKILLCOUNT1 = "/kills"
SlashCmdList["LOCALKILLCOUNT"] = function(msg)
if msg == "errors" then showErrors() else report() end
end
Цена продажи торговцу в каждой подсказке
Добавляет в подсказку предмета цену продажи торговцу или строку о том, что цена еще не загружена.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
local ADDON = ...
local NAME = "VendorPriceTip"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local function coins(copper)
if type(copper) ~= "number" or copper <= 0 then return nil end
local gold = math.floor(copper / 10000)
local silver = math.floor((copper % 10000) / 100)
local rest = copper % 100
return gold .. "g " .. silver .. "s " .. rest .. "c"
end
local function addPrice(tip)
safeCall(function()
local _, link = tip:GetItem()
if not link then return end
local sell = select(11, C_Item.GetItemInfo(link))
local line = coins(sell)
if not line then
C_Item.RequestLoadItemDataByID(link)
line = "Vendor price not loaded"
end
tip:AddLine(line, 1, 0.82, 0.45)
end)
end
GameTooltip:HookScript("OnTooltipSetItem", addPrice)
if TooltipDataProcessor and TooltipDataProcessor.AddTooltipPostCall and Enum and Enum.TooltipDataType and Enum.TooltipDataType.Item then
TooltipDataProcessor.AddTooltipPostCall(Enum.TooltipDataType.Item, addPrice)
end
SLASH_VENDORPRICETIP1 = "/vendorprice"
SlashCmdList["VENDORPRICETIP"] = function(msg)
if msg == "errors" then showErrors() else print(NAME .. ": vendor price is added to item tooltips") end
end
Опыт в час и время до следующего уровня
Показывает опыт в час и примерное время до уровня. Простой и только что полученный уровень не вызывают деления на ноль.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
## Interface: 16001
## Title: XP Per Hour
## Notes: XP per hour and time to level.
## Author: You
## Version: 1.0.0
## X-Generator: WoW Forever Guides Addon Maker
## X-License: CC0 (public domain)
XpPerHour.lua
XpPerHour/XpPerHour.lua
local ADDON = ...
local NAME = "XpPerHour"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local frame = CreateFrame("Frame", "XpPerHourFrame", UIParent)
frame:SetSize(240, 72)
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 160)
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
frame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("CENTER")
label:SetText("XpPerHourFrame")
local state = { start = nil, xp = nil, last = nil }
local function paint(now)
local xp = UnitXP("player")
local maxXp = UnitXPMax("player")
if issecretvalue(xp) then label:SetText("XP is hidden right now") return end
if issecretvalue(maxXp) then label:SetText("XP is hidden right now") return end
if not state.start or not state.xp then
state.start = now
state.xp = xp
state.last = now
label:SetText("Waiting for XP")
return
end
if now - state.last > 120 then label:SetText("Idle. No recent XP.") return end
local gained = xp - state.xp
local elapsed = now - state.start
if gained <= 0 or elapsed < 1 then label:SetText("Waiting for XP") return end
local perHour = gained / elapsed * 3600
if perHour <= 0 then label:SetText("Waiting for XP") return end
local remain = maxXp - xp
if remain < 0 then remain = 0 end
local minutes = math.floor(remain / perHour * 60)
label:SetText(math.floor(perHour) .. " XP/hour, about " .. minutes .. " min")
end
local elapsed = 0
frame:SetScript("OnUpdate", function(_, gap)
elapsed = elapsed + gap
if elapsed < 1 then return end
elapsed = 0
safeCall(function() paint(GetTime()) end)
end)
frame:RegisterEvent("PLAYER_XP_UPDATE")
frame:RegisterEvent("PLAYER_LEVEL_UP")
frame:SetScript("OnEvent", function(_, event)
safeCall(function()
if event == "PLAYER_LEVEL_UP" then state.start = nil state.xp = nil state.last = nil end
if event == "PLAYER_XP_UPDATE" then state.last = GetTime() end
paint(GetTime())
end)
end)
SLASH_XPPERHOUR1 = "/xphour"
SlashCmdList["XPPERHOUR"] = function(msg)
if msg == "errors" then showErrors() else paint(GetTime()) print(NAME .. ": " .. (label:GetText() or "")) end
end
frame:Show()
Напоминать, когда пропадает мой бафф
Вне боя показывает заданное вами имя баффа, если тот отсутствует. В бою остается скрытым.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
## Interface: 16001
## Title: Buff Reminder
## Notes: Out-of-combat reminder when one buff is missing.
## Author: You
## Version: 1.0.0
## X-Generator: WoW Forever Guides Addon Maker
## X-License: CC0 (public domain)
## SavedVariables: BuffReminderDB
BuffReminder.lua
BuffReminder/BuffReminder.lua
local ADDON = ...
local NAME = "BuffReminder"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local frame = CreateFrame("Frame", "BuffReminderFrame", UIParent)
frame:SetSize(240, 72)
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 160)
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
frame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("CENTER")
label:SetText("BuffReminderFrame")
BuffReminderDB = BuffReminderDB or { spell = "" }
frame:Hide()
local function remind()
if InCombatLockdown() or UnitAffectingCombat("player") then frame:Hide() return end
local spell = BuffReminderDB.spell or ""
if spell == "" then frame:Hide() return end
local aura = C_UnitAuras.GetAuraDataBySpellName("player", spell, "HELPFUL")
if issecretvalue(aura) then frame:Hide() return end
if aura then frame:Hide() return end
label:SetText("Buff down: " .. spell)
frame:Show()
end
frame:RegisterEvent("UNIT_AURA")
frame:RegisterUnitEvent("UNIT_AURA", "player")
frame:RegisterEvent("PLAYER_REGEN_DISABLED")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")
frame:SetScript("OnEvent", function() safeCall(remind) end)
SLASH_BUFFREMINDER1 = "/buffremind"
SlashCmdList["BUFFREMINDER"] = function(msg)
if msg == "errors" then showErrors() return end
if msg == "" then print(NAME .. ": /buffremind Spell Name") return end
BuffReminderDB.spell = msg
print(NAME .. ": watching " .. msg)
remind()
end
Список подготовки к рейду для моей гильдии
Личный список, в котором вы отмечаете пункты перед рейдом. Не читает состав гильдии.
Ошибок проверки нет. Еще не тестировалось в игре. Клиент 1.60.1.70338.
## Interface: 16001
## Title: Raid Prep List
## Notes: A personal raid prep checklist.
## Author: You
## Version: 1.0.0
## X-Generator: WoW Forever Guides Addon Maker
## X-License: CC0 (public domain)
## SavedVariables: RaidPrepDB
RaidPrepList.lua
RaidPrepList/RaidPrepList.lua
local ADDON = ...
local NAME = "RaidPrepList"
local errors = {}
local function safeCall(func)
return xpcall(func, function(err)
errors[#errors + 1] = tostring(err)
if #errors > 10 then table.remove(errors, 1) end
print(NAME .. " error: " .. tostring(err))
end)
end
local function showErrors()
if #errors == 0 then print(NAME .. ": no errors saved") return end
for i = 1, #errors do print(i .. ". " .. errors[i]) end
end
local frame = CreateFrame("Frame", "RaidPrepFrame", UIParent)
frame:SetSize(240, 72)
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 160)
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
frame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
label:SetPoint("CENTER")
label:SetText("RaidPrepFrame")
RaidPrepDB = RaidPrepDB or { items = { "Food", "Water", "Flasks", "Repair" }, done = {} }
local function line()
local parts = {}
for i = 1, #RaidPrepDB.items do
local item = RaidPrepDB.items[i]
local mark = RaidPrepDB.done[item] and "[x] " or "[ ] "
parts[#parts + 1] = mark .. item
end
if #parts == 0 then label:SetText("Checklist is empty") else label:SetText(table.concat(parts, "\n")) end
end
frame:SetScript("OnMouseUp", function()
safeCall(function()
if #RaidPrepDB.items == 0 then return end
local item = RaidPrepDB.items[1]
for i = 1, #RaidPrepDB.items do
if not RaidPrepDB.done[RaidPrepDB.items[i]] then item = RaidPrepDB.items[i] break end
end
RaidPrepDB.done[item] = not RaidPrepDB.done[item]
line()
end)
end)
line()
SLASH_RAIDPREPLIST1 = "/raidprep"
SlashCmdList["RAIDPREPLIST"] = function(msg)
if msg == "errors" then showErrors() return end
local add = msg:match("^add%s+(.+)$")
if add then
RaidPrepDB.items[#RaidPrepDB.items + 1] = add
line()
print(NAME .. ": added " .. add)
return
end
if msg == "reset" then RaidPrepDB.done = {} line() print(NAME .. ": cleared") return end
line()
print(NAME .. ": click the box to tick the next open line")
end
Создание своих аддонов отключено. Проверенные примеры по-прежнему можно скачать.
Конструктор пока достиг лимита. Проверенные примеры по-прежнему можно скачать.
Вы израсходовали сегодняшние создания или изменения. Проверенные примеры по-прежнему можно скачать.
Проверка не пройдена. Попробуйте снова. Примеры по-прежнему можно скачать.
Создание своих аддонов не настроено на этом сервере. Примеры по-прежнему можно скачать.
Конструктор не завершил работу. Ваш запрос остался в поле.
Создание заняло слишком много времени и было остановлено. Ваш запрос остался в поле.
Соединение прервалось. Ваш запрос и последний рабочий аддон остались здесь.
Остановлено. Ваш запрос остался в поле.
Срок действия ссылки истек или сохраненная копия была удалена.
Этот браузер не сохранял аддон, поэтому не может его изменить.
Обновите страницу и попробуйте с wowforeverguides.com.
Не удалось использовать запрос. Напишите короткое предложение и попробуйте снова.
Для создания своего аддона нужен скрипт проверки. Примеры по-прежнему можно скачать.
Создаем. Это может занять минуту.
Проверяем файлы и исправляем проблемы.
Сохранено в этом браузере на 90 дней. Любой, у кого есть ссылка для доступа, может прочитать последнюю копию.
Браузер заблокировал хранилище. Ключ владельца действует только в этой вкладке, а аддон не сохранен.
Не удалось сохранить список аддонов этого браузера.
Скопировано.
Выделите код и скопируйте его вручную.
Сохраненная копия удалена.
Удалить
Ссылка для доступа скопирована. Ключа владельца в ней нет.
Последняя проверка не пройдена, поэтому скачивание недоступно. Предыдущая рабочая копия не изменилась.
Запрос отклонен.
Один вопрос перед созданием.
Это уже делает опубликованный аддон.
Аддон по ссылке. Только чтение.
Изменение и исправление работают с сохраненным аддоном. Опишите свой аддон, чтобы создать его.
Проверенный пример. Еще не тестировался в игре.
Аддоны могут показывать информацию, которую клиент уже предоставляет. Они не могут играть за вас.Blizzard: Developer Q&A, сентября 17, 2026. Списки ниже соответствуют возможностям восьми примеров. Прочитайте, что работает и что ломается, прежде чем полагаться на аддон.
Да. Дневные лимиты позволяют оставить сервис бесплатным для всех. Восемь примеров скачиваются без аккаунта.
Нужно ли знать Lua?
Нет. При желании вы можете прочитать каждый файл. Каждый пример состоит из файла .toc и одного файла .lua.
Безопасен ли код аддона, написанный ИИ?
Созданный по запросу аддон не содержит сетевых вызовов, и его исходный код открыт для чтения. Проверка сравнивает каждую глобальную функцию и событие со списком API сборки Forever 70338 и правилами Blizzard для аддонов, а также предупреждает о методах виджетов, которые не может подтвердить. Это не обещание безопасности аддона в бою; ни один из этих файлов еще не тестировался в игре.
Разрешены ли аддоны в WoW Forever?
Да, на современном API, с боевыми ограничениями Midnight. Ответ от 17 сентября есть на странице аддонов.
Почему нельзя создать аддон для ротации или автоматического применения заклинаний?
Конструктор не создает автоматизацию боя или код для обхода защищенных действий, которые блокирует игра. Каждое создание проверяется по правилам Blizzard для аддонов интерфейса. Попросите заметку, список, строку в подсказке или напоминание вне боя.
Работает ли WeakAuras в Forever?
Wowhead сообщила, что разработка WeakAuras прекратилась до изменений аддонов в Midnight. Другой автор указал форк, а Musca Auras публикует файл для Forever. Blizzard не сообщала, что работает сам WeakAuras. Эти сообщения собраны на странице аддонов.
Можно ли поделиться аддоном или опубликовать его?
Да. Файлы примеров находятся в общественном достоянии, CC0. Используйте, изменяйте и публикуйте их. Указывать авторство не обязательно. Если сайт просит раскрыть использование ИИ, вставьте эту строку. Уведомление об ИИ: создано в конструкторе аддонов WoW Forever Guides (Claude), проверено по списку API клиента Forever.
Что делать, если аддон сломается после патча?
Вставьте ошибку в «Исправить». Если новая копия не пройдет проверку, последняя рабочая копия сохранится, а скачать неудачную будет нельзя.
Какой ИИ его пишет?
Claude от Anthropic пишет черновик по вашему запросу. Затем наша проверка сверяет каждую глобальную функцию и событие со списком API сборки 70338 и отмечает методы виджетов, которые не может подтвердить. Ничего еще не тестировалось в игре, поэтому прочитайте файлы, прежде чем полагаться на аддон.
Что вы храните?
Сохраненные проекты содержат ваш запрос и файлы. Их удаление запланировано через 90 дней после последнего изменения. Удаление использует ключ владельца, чтобы удалить сохраненный проект и все его версии.
На странице конфиденциальности описаны доступ по ссылкам для обмена, хранилище браузера и отдельные сроки хранения кеша и данных у провайдера.
Имена и события проверены по клиенту 1.60.1.70338. Эти файлы не тестировались в игре.
Бросаем кубик на аналитику? Нужно = Clicky, GA4 и Microsoft Clarity с файлами cookie и записью сессий, чтобы видеть, какие гайды помогают. Пас = никакой аналитики.Конфиденциальность