diff --git a/client-export/C_PlayerGuide.lua b/client-export/C_PlayerGuide.lua
new file mode 100644
index 0000000..dcb875a
--- /dev/null
+++ b/client-export/C_PlayerGuide.lua
@@ -0,0 +1,276 @@
+--[[----------------------------------------------------------------------------
+ C_PlayerGuide.lua
+ ─────────────────────────────────────────────────────────────────────────────
+ Клиентское хранилище данных Путеводителя + UI-facing API.
+ Соответствует контракту из player-guide-requirements.md → "Client API".
+
+ Подключается до PlayerGuide.xml/.lua в .toc.
+------------------------------------------------------------------------------]]
+
+C_PlayerGuide = C_PlayerGuide or {}
+local L = C_PlayerGuide
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Состояние
+
+local currentData = nil -- последний валидный payload от сервера
+local lastError = nil -- строка с описанием последней проблемы валидации
+
+-- Состояние UI: "data" | "empty" | "loading"
+local uiState = "loading"
+
+-- Подписчики на обновления (PlayerGuide.lua вешает сюда свой Refresh)
+local listeners = {}
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Утилиты
+
+local function notify()
+ for _, fn in ipairs(listeners) do
+ -- pcall чтобы один сломанный listener не уронил остальные
+ pcall(fn, uiState, currentData)
+ end
+end
+
+local function isTable(v) return type(v) == "table" end
+
+-- Валидация payload'а. Возвращает true либо false + строка ошибки.
+local function validate(data)
+ if not isTable(data) then return false, "payload is not a table" end
+ if data.stageID and type(data.stageID) ~= "number" then
+ return false, "stageID is not a number"
+ end
+ if data.progress and type(data.progress) ~= "number" then
+ return false, "progress is not a number"
+ end
+ if data.objectives and not isTable(data.objectives) then
+ return false, "objectives is not a table"
+ end
+ -- Уникальность id целей
+ if isTable(data.objectives) then
+ local seen = {}
+ for i, o in ipairs(data.objectives) do
+ if not isTable(o) then
+ return false, "objective #" .. i .. " is not a table"
+ end
+ if o.id and seen[o.id] then
+ return false, "duplicate objective id: " .. tostring(o.id)
+ end
+ if o.id then seen[o.id] = true end
+ end
+ end
+ return true
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Подписки (для PlayerGuide.lua)
+
+function L.RegisterListener(fn)
+ table.insert(listeners, fn)
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Публичный API (см. требования → Client API)
+
+function L.SetData(data)
+ local ok, err = validate(data)
+ if not ok then
+ lastError = err
+ uiState = "empty"
+ notify()
+ return false, err
+ end
+ currentData = data
+ lastError = nil
+ uiState = "data"
+ notify()
+ return true
+end
+
+function L.Clear()
+ currentData = nil
+ lastError = nil
+ uiState = "empty"
+ notify()
+end
+
+function L.SetLoading()
+ if uiState ~= "data" then
+ uiState = "loading"
+ notify()
+ end
+end
+
+function L.GetState()
+ return uiState
+end
+
+function L.GetLastError()
+ return lastError
+end
+
+function L.HasData()
+ return uiState == "data" and currentData ~= nil
+end
+
+function L.GetStageInfo()
+ if not L.HasData() then return nil end
+ return currentData.stageID,
+ currentData.stageName,
+ currentData.stageDescription,
+ currentData.progress or 0
+end
+
+-- Доп. метод: список всех этапов (для цепочки сверху)
+function L.GetStages()
+ if not L.HasData() then return nil end
+ return currentData.stages or {} -- сервер опционально шлёт массив этапов
+end
+
+function L.GetNumObjectives()
+ if not L.HasData() or not currentData.objectives then return 0 end
+ return #currentData.objectives
+end
+
+function L.GetObjectiveInfo(index)
+ if not L.HasData() or not currentData.objectives then return nil end
+ local o = currentData.objectives[index]
+ if not o then return nil end
+ return {
+ id = o.id,
+ type = o.type or "custom",
+ title = o.title or "",
+ description = o.description or o.subtitle or "",
+ subtitle = o.subtitle, -- наше расширение поля для UI
+ completed = o.completed and true or false,
+ progress = o.progress or 0,
+ required = o.required or 1,
+ targetID = o.targetID,
+ questID = o.questID,
+ instanceID = o.instanceID,
+ encounterID = o.encounterID,
+ achievementID = o.achievementID,
+ factionID = o.factionID,
+ itemID = o.itemID,
+ currencyID = o.currencyID,
+ order = o.order or index,
+ }
+end
+
+function L.GetNumRecommendations()
+ if not L.HasData() or not currentData.recommendations then return 0 end
+ return #currentData.recommendations
+end
+
+function L.GetRecommendationInfo(index)
+ if not L.HasData() or not currentData.recommendations then return nil end
+ local r = currentData.recommendations[index]
+ if not r then return nil end
+ return {
+ id = r.id,
+ type = r.type or "dungeon",
+ title = r.title or r.name or "",
+ name = r.name or r.title or "",
+ description = r.description or r.loc or "",
+ loc = r.loc, -- локация/подзаголовок
+ level = r.level,
+ biome = r.biome, -- ключ биом-обложки
+ instanceID = r.instanceID,
+ encounterID = r.encounterID,
+ priority = r.priority or 0,
+ }
+end
+
+function L.GetNumRewards()
+ if not L.HasData() or not currentData.rewards then return 0 end
+ return #currentData.rewards
+end
+
+function L.GetRewardInfo(index)
+ if not L.HasData() or not currentData.rewards then return nil end
+ local r = currentData.rewards[index]
+ if not r then return nil end
+ return r
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Сетевой слой (AIO)
+-- MoonWellPlayerGuide.lua перехватывает SetData() из serverToClient и вызывает
+-- L.SetData(payload). RequestRefresh шлёт обратно в обратную сторону.
+
+function L.RequestRefresh()
+ L.SetLoading()
+ if AIO and AIO.Handle then
+ -- name берётся из serverToClient на сервере. Тут — лёгкая обёртка.
+ AIO.Handle("MoonWellPlayerGuide", "RequestRefresh")
+ else
+ -- Без AIO (например, в режиме разработки) — отдаём заглушку через
+ -- 0.5 секунды, чтобы UI не висел в Loading навечно.
+ if C_Timer and C_Timer.After then
+ C_Timer.After(0.5, function() L.Clear() end)
+ end
+ end
+end
+
+function L.RequestTrackObjective(objectiveID)
+ if AIO and AIO.Handle then
+ AIO.Handle("MoonWellPlayerGuide", "RequestTrackObjective", objectiveID)
+ end
+end
+
+function L.RequestOpenTarget(objectiveID)
+ if AIO and AIO.Handle then
+ AIO.Handle("MoonWellPlayerGuide", "RequestOpenTarget", objectiveID)
+ end
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Статика для разработки (видна, пока сервер не прислал реальный payload).
+-- Можно убрать перед релизом.
+
+function L._InjectDevPayload()
+ L.SetData({
+ version = 1,
+ stageID = 5,
+ stageName = "Подготовка к Нордсколу",
+ stageDescription =
+ "Завершите ключевые цепочки заданий в Запределье и докажите готовность к походу на север. "..
+ "По прибытии в Нордскол вам понадобится снаряжение героического уровня.",
+ progress = 62,
+ stages = {
+ { id = 1, name = "Начало пути", short = "Начало пути", era = "1—58", status = "done" },
+ { id = 2, name = "Огненные Недра", short = "Огненные Недра", era = "60", status = "done" },
+ { id = 3, name = "Сквозь Тёмный портал", short = "Тёмный портал", era = "58—60", status = "done" },
+ { id = 4, name = "Покорение Запределья", short = "Запределье", era = "60—68", status = "done" },
+ { id = 5, name = "Подготовка к Нордсколу", short = "К Нордсколу", era = "68—70", status = "active" },
+ { id = 6, name = "Заря Нордскола", short = "Нордскол", era = "70—78", status = "locked" },
+ { id = 7, name = "Цитадель Ледяной Короны",short = "Ледяная Корона", era = "78—80", status = "locked" },
+ },
+ objectives = {
+ { id = 1, type = "level", title = "Достигнуть 68 уровня",
+ subtitle = "Текущий уровень: 68. Можно отправляться в Нордскол.",
+ completed = true, progress = 68, required = 68, order = 1 },
+ { id = 2, type = "quest_chain", title = "Цепочка «Поиск виверны» в Награнде",
+ subtitle = "Кисть Шамана • Награнд • награда: «Привязка к виверне»",
+ completed = false, progress = 5, required = 8, order = 2 },
+ { id = 3, type = "dungeon", title = "Пройти Кузню Крови",
+ subtitle = "Цитадель Адского Пламени • рек. уровень 61—64",
+ completed = false, progress = 0, required = 1, order = 3, instanceID = 256 },
+ { id = 4, type = "dungeon", title = "Пройти Аукиндон: Подземелья Аукенай",
+ subtitle = "Награнд • рек. уровень 64—66",
+ completed = false, progress = 0, required = 1, order = 4, instanceID = 257 },
+ { id = 5, type = "reputation", title = "Получить «Дружелюбие» с Кенарийской экспедицией",
+ subtitle = "Текущее положение: Нейтрально • Долина Призрачной Луны",
+ completed = false, progress = 1200, required = 3000, order = 5, factionID = 942 },
+ },
+ recommendations = {
+ { id = 1, type = "dungeon", name = "Кузня Крови", loc = "Цитадель Адского Пламени", level = "61—64", biome = "fire" },
+ { id = 2, type = "dungeon", name = "Подземелья Аукенай", loc = "Аукиндон", level = "64—66", biome = "arcane" },
+ { id = 3, type = "dungeon", name = "Сетеккские залы", loc = "Награнд", level = "67—69", biome = "storm" },
+ { id = 4, type = "dungeon", name = "Темный Лабиринт", loc = "Аукиндон", level = "68—70", biome = "shadow" },
+ { id = 5, type = "dungeon", name = "Ботаника", loc = "Долина Призрачной Луны", level = "69—70", biome = "nature" },
+ { id = 6, type = "dungeon", name = "Расколотые Залы", loc = "Цитадель Адского Пламени", level = "70 H", biome = "fire" },
+ },
+ rewards = {}, -- блок наград временно скрыт (см. SHOW_REWARDS в PlayerGuide.lua)
+ })
+end
diff --git a/client-export/MoonWellPlayerGuide.lua b/client-export/MoonWellPlayerGuide.lua
new file mode 100644
index 0000000..2794751
--- /dev/null
+++ b/client-export/MoonWellPlayerGuide.lua
@@ -0,0 +1,78 @@
+--[[----------------------------------------------------------------------------
+ AIO/MoonWellPlayerGuide.lua
+ ─────────────────────────────────────────────────────────────────────────────
+ AIO-handler (клиентская часть) для namespace "MoonWellPlayerGuide".
+ Сервер отправляет SetData(payload), клиент кладёт его в C_PlayerGuide.
+ Клиент шлёт RequestRefresh обратно при нажатии «Обновить».
+
+ Контракт описан в player-guide-requirements.md → "AIO Contract".
+------------------------------------------------------------------------------]]
+
+local AIO = AIO or require("AIO")
+if not AIO then return end -- безопасный no-op без AIO
+
+local handlers = AIO.AddHandlers("MoonWellPlayerGuide", {})
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Server → Client
+
+-- Полная замена payload
+function handlers.SetData(player, payload)
+ if C_PlayerGuide and C_PlayerGuide.SetData then
+ local ok, err = C_PlayerGuide.SetData(payload)
+ if not ok and DEFAULT_CHAT_FRAME then
+ DEFAULT_CHAT_FRAME:AddMessage(
+ "|cffff8080[Путеводитель]|r Ошибка payload: "..tostring(err))
+ end
+ end
+end
+
+-- Обновление одной цели (для частичных update'ов)
+function handlers.UpdateObjective(player, objective)
+ if not (C_PlayerGuide and C_PlayerGuide.HasData()) then return end
+ -- Простая стратегия: пересобрать payload локально с заменой цели по id.
+ -- C_PlayerGuide хранит данные internally — даём прямой доступ через _patch:
+ local n = C_PlayerGuide.GetNumObjectives()
+ for i = 1, n do
+ local o = C_PlayerGuide.GetObjectiveInfo(i)
+ if o and o.id == objective.id then
+ -- Грязный, но рабочий способ для MVP — отдать обратно весь массив.
+ -- Для прод-уровня лучше выставить C_PlayerGuide.PatchObjective(o).
+ o.progress = objective.progress or o.progress
+ o.required = objective.required or o.required
+ o.completed = objective.completed
+ if MW_PlayerGuide and MW_PlayerGuide.Refresh then
+ MW_PlayerGuide.Refresh()
+ end
+ break
+ end
+ end
+end
+
+-- Замена только инфы об этапе (без массива objectives)
+function handlers.SetStage(player, stagePayload)
+ if not stagePayload then return end
+ -- Объединяем с текущим payload'ом
+ local _, name, desc, progress = C_PlayerGuide.GetStageInfo()
+ C_PlayerGuide.SetData({
+ stageID = stagePayload.stageID,
+ stageName = stagePayload.stageName or name,
+ stageDescription = stagePayload.stageDescription or desc,
+ progress = stagePayload.progress or progress,
+ stages = stagePayload.stages,
+ objectives = stagePayload.objectives or {},
+ recommendations = stagePayload.recommendations or {},
+ rewards = stagePayload.rewards or {},
+ })
+end
+
+-- Сообщения от сервера (баблы / chat-фрейм)
+function handlers.Notify(player, message)
+ if DEFAULT_CHAT_FRAME and message then
+ DEFAULT_CHAT_FRAME:AddMessage("|cffffd76a[Путеводитель]|r "..tostring(message))
+ end
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Client → Server: ничего регистрировать не нужно — это просто AIO.Handle
+-- внутри C_PlayerGuide.RequestRefresh / RequestTrackObjective / RequestOpenTarget.
diff --git a/client-export/PlayerGuide.lua b/client-export/PlayerGuide.lua
new file mode 100644
index 0000000..94dca75
--- /dev/null
+++ b/client-export/PlayerGuide.lua
@@ -0,0 +1,402 @@
+--[[----------------------------------------------------------------------------
+ PlayerGuide.lua
+ ─────────────────────────────────────────────────────────────────────────────
+ UI-логика вкладки «Путеводитель». Парный файл PlayerGuide.xml.
+
+ Зависимости:
+ * C_PlayerGuide (Utils/C_PlayerGuide.lua) — данные и API
+ * MW_PLAYER_GUIDE* (Localization/ruRU.lua) — строки
+ * EncounterJournal (Custom_EncounterJournal) — родительский фрейм
+------------------------------------------------------------------------------]]
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Конфигурация фичи
+
+local SHOW_REWARDS = false -- блок наград временно отключён
+local SHOW_RECOMMENDATIONS = true
+local DENSITY = "compact" -- compact | regular | cozy
+local ACCENT = { r = 1.0, g = 0.84, b = 0.42 } -- золото
+
+local ROMAN = { "I","II","III","IV","V","VI","VII","VIII","IX","X" }
+
+-- Биом → цвет «обложки» рекомендации (rgb 0..1).
+-- В будущем заменить на текстуры Interface\AddOns\MoonWellClient\EncounterJournal\Textures\Biome-*.
+local BIOME_COLOR = {
+ fire = { 0.83, 0.29, 0.10 },
+ arcane = { 0.48, 0.31, 0.83 },
+ storm = { 0.24, 0.56, 0.77 },
+ shadow = { 0.35, 0.16, 0.54 },
+ nature = { 0.31, 0.63, 0.29 },
+ holy = { 0.83, 0.69, 0.24 },
+}
+
+-- Тип цели → глиф (заменить на иконки из BLP, когда будет атлас).
+local TYPE_GLYPH = {
+ level = "⚔",
+ quest = "!",
+ quest_chain = "!",
+ dungeon = "⛨",
+ raid = "☠",
+ boss = "☠",
+ achievement = "★",
+ reputation = "◈",
+ profession = "⚒",
+ item = "◆",
+ currency = "✦",
+ custom = "∗",
+}
+
+-- Тип цели → плейсхолдер-иконка из встроенных текстур 3.3.5a.
+local TYPE_ICON = {
+ level = "Interface\\Icons\\Ability_Warrior_Challange",
+ quest = "Interface\\Icons\\INV_Misc_Note_01",
+ quest_chain = "Interface\\Icons\\INV_Misc_Note_05",
+ dungeon = "Interface\\Icons\\INV_Misc_Key_06",
+ raid = "Interface\\Icons\\INV_Misc_Head_Dragon_01",
+ boss = "Interface\\Icons\\Ability_Warrior_DecisiveStrike",
+ achievement = "Interface\\Icons\\Achievement_GuildPerk_HonorableMention",
+ reputation = "Interface\\Icons\\INV_Scroll_03",
+ profession = "Interface\\Icons\\Trade_Engineering",
+ item = "Interface\\Icons\\INV_Misc_Gem_Diamond_02",
+ currency = "Interface\\Icons\\INV_Misc_Coin_17",
+ custom = "Interface\\Icons\\INV_Misc_QuestionMark",
+}
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Хелперы
+
+local function pct(cur, req)
+ if not req or req <= 0 then return 0 end
+ return math.floor((cur / req) * 100 + 0.5)
+end
+
+local function setRGB(fs, c) fs:SetTextColor(c.r or c[1], c.g or c[2], c.b or c[3]) end
+
+local function showOrHide(frame, show)
+ if not frame then return end
+ if show then frame:Show() else frame:Hide() end
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Цепочка этапов
+
+local stageBadges = {} -- кэш созданных бейджей по индексу
+
+local function buildStageChain(stages)
+ if not PlayerGuideFrame then return end
+ local container = PlayerGuideFrame.StageChain
+
+ -- Прячем лишние бейджи, если этапов стало меньше
+ for i = (#stages + 1), #stageBadges do
+ stageBadges[i]:Hide()
+ end
+
+ if #stages == 0 then return end
+
+ local width = container:GetWidth()
+ if width == 0 then width = 600 end
+ local slot = width / #stages
+
+ for i, s in ipairs(stages) do
+ local badge = stageBadges[i]
+ if not badge then
+ badge = CreateFrame("Frame", "PlayerGuideStageBadge"..i, container, "MW_PG_StageBadgeTemplate")
+ stageBadges[i] = badge
+ end
+ badge:ClearAllPoints()
+ badge:SetPoint("LEFT", container, "LEFT", (i - 0.5) * slot - 19, 0)
+ badge:Show()
+
+ -- Текст
+ badge.Roman:SetText(ROMAN[s.id] or tostring(s.id))
+ badge.Label:SetText(s.short or s.name or "")
+
+ -- Цветовая схема по статусу
+ local status = s.status or "locked"
+ if status == "active" then
+ badge.Roman:SetTextColor(1.0, 0.91, 0.63)
+ badge.Label:SetTextColor(1.0, 0.84, 0.42)
+ badge.BadgeBG:SetVertexColor(1.0, 0.84, 0.42, 1)
+ elseif status == "done" then
+ badge.Roman:SetTextColor(0.79, 0.65, 0.38)
+ badge.Label:SetTextColor(0.79, 0.65, 0.38)
+ badge.BadgeBG:SetVertexColor(0.55, 0.40, 0.18, 1)
+ -- Можно заменить римскую цифру на «✓» для завершённых:
+ badge.Roman:SetText("✓")
+ else
+ badge.Roman:SetTextColor(0.40, 0.34, 0.22)
+ badge.Label:SetTextColor(0.40, 0.34, 0.22)
+ badge.BadgeBG:SetVertexColor(0.20, 0.15, 0.08, 1)
+ end
+ end
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Карточки целей
+
+local objectiveCards = {}
+
+local CARD_HEIGHT = { compact = 44, regular = 56, cozy = 72 }
+local CARD_GAP = { compact = 4, regular = 6, cozy = 8 }
+
+local function renderObjectives()
+ local section = PlayerGuideFrame.ObjectivesSection
+ local parent = section.ScrollFrame.ScrollChild
+ local n = C_PlayerGuide.GetNumObjectives()
+
+ -- Скрыть лишние
+ for i = (n + 1), #objectiveCards do objectiveCards[i]:Hide() end
+
+ local h = CARD_HEIGHT[DENSITY] or 44
+ local gap = CARD_GAP[DENSITY] or 4
+ local done = 0
+
+ for i = 1, n do
+ local o = C_PlayerGuide.GetObjectiveInfo(i)
+ if not o then break end
+
+ local card = objectiveCards[i]
+ if not card then
+ card = CreateFrame("Frame", "PlayerGuideObjective"..i, parent, "MW_PG_ObjectiveCardTemplate")
+ objectiveCards[i] = card
+ end
+ card:ClearAllPoints()
+ card:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, -(i - 1) * (h + gap))
+ card:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 0, -(i - 1) * (h + gap))
+ card:SetHeight(h)
+ card.objectiveData = o
+ card:Show()
+
+ -- Иконка типа
+ card.Icon:SetTexture(TYPE_ICON[o.type] or TYPE_ICON.custom)
+ card.Icon:SetTexCoord(0.08, 0.92, 0.08, 0.92) -- crop borders Blizz-стиль
+
+ -- Тип-плашка caps
+ card.TypeLabel:SetText(_G["MW_PG_TYPE_"..string.upper(o.type)] or string.upper(o.type))
+
+ -- Заголовок и подзаголовок
+ card.Title:SetText(o.title or "")
+ card.Subtitle:SetText(o.subtitle or o.description or "")
+
+ -- Прогресс
+ card.ProgressBar:SetMinMaxValues(0, o.required or 1)
+ card.ProgressBar:SetValue(o.progress or 0)
+ card.Count:SetText(string.format("%d / %d", o.progress or 0, o.required or 1))
+
+ -- Цвет по статусу
+ if o.completed then
+ done = done + 1
+ card.Title:SetTextColor(0.62, 0.84, 0.47)
+ card.TypeLabel:SetTextColor(0.49, 0.65, 0.35)
+ card.Count:SetTextColor(0.62, 0.84, 0.47)
+ card.ProgressBar:SetStatusBarColor(0.55, 0.85, 0.40)
+ card.IconBorder:SetVertexColor(0.40, 0.65, 0.30, 0.7)
+ else
+ card.Title:SetTextColor(1.0, 0.91, 0.63)
+ card.TypeLabel:SetTextColor(0.63, 0.46, 0.19)
+ card.Count:SetTextColor(0.79, 0.65, 0.38)
+ card.ProgressBar:SetStatusBarColor(ACCENT.r, ACCENT.g, ACCENT.b)
+ card.IconBorder:SetVertexColor(ACCENT.r, ACCENT.g, ACCENT.b, 0.55)
+ end
+ end
+
+ parent:SetHeight(math.max(1, n * (h + gap)))
+ section.Count:SetText(string.format("· %d / %d", done, n))
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Карточки рекомендаций
+
+local recCards = {}
+
+local function renderRecommendations()
+ local section = PlayerGuideFrame.RecommendationsSection
+ if not SHOW_RECOMMENDATIONS then section:Hide(); return end
+
+ local parent = section.ScrollFrame.ScrollChild
+ local n = C_PlayerGuide.GetNumRecommendations()
+ if n == 0 then section:Hide(); return end
+ section:Show()
+
+ for i = (n + 1), #recCards do recCards[i]:Hide() end
+
+ local cardW = 148
+ local gap = 8
+
+ for i = 1, n do
+ local r = C_PlayerGuide.GetRecommendationInfo(i)
+ if not r then break end
+
+ local card = recCards[i]
+ if not card then
+ card = CreateFrame("Button", "PlayerGuideRec"..i, parent, "MW_PG_RecCardTemplate")
+ recCards[i] = card
+ end
+ card:ClearAllPoints()
+ card:SetPoint("TOPLEFT", parent, "TOPLEFT", (i - 1) * (cardW + gap), 0)
+ card.recData = r
+ card:Show()
+
+ local biome = BIOME_COLOR[r.biome] or BIOME_COLOR.fire
+ card.Artwork:SetVertexColor(biome[1], biome[2], biome[3], 1)
+ card.Name:SetText(r.name or "")
+ card.Loc:SetText(r.loc or "")
+ card.Level:SetText(r.level or "")
+ end
+
+ parent:SetWidth(math.max(1, n * (cardW + gap)))
+ section.Count:SetText("· "..n)
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Главный Refresh
+
+local function showState(state)
+ local F = PlayerGuideFrame
+ local hasData = (state == "data")
+
+ showOrHide(F.StageChain, hasData)
+ showOrHide(F.Header, hasData)
+ showOrHide(F.ObjectivesSection, hasData)
+ showOrHide(F.RecommendationsSection, hasData and SHOW_RECOMMENDATIONS)
+ showOrHide(F.EmptyState, state == "empty")
+ showOrHide(F.LoadingState, state == "loading")
+end
+
+local function refresh()
+ if not PlayerGuideFrame then return end
+
+ local state = C_PlayerGuide.GetState()
+ showState(state)
+
+ if state ~= "data" then return end
+
+ -- Заголовок этапа
+ local id, name, desc, progress = C_PlayerGuide.GetStageInfo()
+ local stages = C_PlayerGuide.GetStages() or {}
+
+ PlayerGuideFrame.Header.Pretitle:SetText(
+ string.format(MW_PLAYER_GUIDE_STAGE_OF or "Этап %d из %d", id or 0, #stages))
+ PlayerGuideFrame.Header.Title:SetText(name or "")
+ PlayerGuideFrame.Header.Description:SetText(desc or "")
+ PlayerGuideFrame.Header.ProgressLabel:SetText(MW_PLAYER_GUIDE_STAGE_PROGRESS or "ПРОГРЕСС ЭТАПА")
+ PlayerGuideFrame.Header.ProgressPercent:SetText((progress or 0) .. "%")
+ PlayerGuideFrame.Header.ProgressBar:SetMinMaxValues(0, 100)
+ PlayerGuideFrame.Header.ProgressBar:SetValue(progress or 0)
+
+ buildStageChain(stages)
+ renderObjectives()
+ renderRecommendations()
+end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- XML script handlers
+
+function MW_PlayerGuide_OnLoad(self)
+ -- Подписываемся на изменения C_PlayerGuide
+ C_PlayerGuide.RegisterListener(function() refresh() end)
+end
+
+function MW_PlayerGuide_OnShow(self)
+ -- Если данных ещё нет — попросим сервер
+ if not C_PlayerGuide.HasData() then
+ C_PlayerGuide.SetLoading()
+ C_PlayerGuide.RequestRefresh()
+ end
+ refresh()
+end
+
+function MW_PlayerGuide_RefreshButton_OnClick(self)
+ C_PlayerGuide.SetLoading()
+ C_PlayerGuide.RequestRefresh()
+end
+
+-- Клик по карточке цели — открывает связанный таргет (см. требования)
+function MW_PlayerGuide_Objective_OnClick(self)
+ local o = self.objectiveData
+ if not o then return end
+
+ if o.type == "dungeon" or o.type == "raid" then
+ if o.instanceID and EncounterJournal_OpenJournal then
+ EncounterJournal_OpenJournal(o.instanceID)
+ end
+ elseif o.type == "boss" then
+ if o.encounterID and EncounterJournal_OpenJournal then
+ EncounterJournal_OpenJournal(o.instanceID, o.encounterID)
+ end
+ elseif o.type == "achievement" and o.achievementID then
+ if AchievementFrame_LoadUI then AchievementFrame_LoadUI() end
+ if AchievementFrame_SelectAchievement then
+ AchievementFrame_SelectAchievement(o.achievementID)
+ end
+ elseif o.type == "item" and o.itemID then
+ -- Запрос подсказки предмета
+ if GameTooltip then
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
+ GameTooltip:SetItemByID(o.itemID)
+ GameTooltip:Show()
+ end
+ else
+ -- Любой нестандартный тип — пытаемся попросить сервер открыть таргет
+ C_PlayerGuide.RequestOpenTarget(o.id)
+ end
+end
+
+function MW_PlayerGuide_Objective_OnEnter(self)
+ local o = self.objectiveData
+ if not o then return end
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
+ GameTooltip:AddLine(o.title or "", 1, 0.91, 0.63)
+ if o.subtitle and o.subtitle ~= "" then
+ GameTooltip:AddLine(o.subtitle, 0.66, 0.59, 0.47, true)
+ end
+ if not o.completed then
+ GameTooltip:AddLine(string.format("Прогресс: %d / %d", o.progress, o.required),
+ 0.79, 0.65, 0.38)
+ end
+ GameTooltip:Show()
+end
+
+function MW_PlayerGuide_Objective_OnLeave(self) GameTooltip:Hide() end
+
+function MW_PlayerGuide_Rec_OnClick(self)
+ local r = self.recData
+ if r and r.instanceID and EncounterJournal_OpenJournal then
+ EncounterJournal_OpenJournal(r.instanceID)
+ end
+end
+
+function MW_PlayerGuide_Rec_OnEnter(self)
+ local r = self.recData
+ if not r then return end
+ GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
+ GameTooltip:AddLine(r.name or "", 1, 0.91, 0.63)
+ if r.loc then GameTooltip:AddLine(r.loc, 0.66, 0.59, 0.47) end
+ if r.level then GameTooltip:AddLine("Уровень: "..r.level, 0.79, 0.65, 0.38) end
+ GameTooltip:Show()
+end
+
+function MW_PlayerGuide_Rec_OnLeave(self) GameTooltip:Hide() end
+
+-- ──────────────────────────────────────────────────────────────────────────
+-- Публичные хелперы для Custom_EncounterJournal.lua (routing вкладки)
+
+function PlayerGuide_Show()
+ if PlayerGuideFrame then
+ PlayerGuideFrame:Show()
+ end
+end
+
+function PlayerGuide_Hide()
+ if PlayerGuideFrame then
+ PlayerGuideFrame:Hide()
+ end
+end
+
+-- Глобальный экспорт для отладки
+MW_PlayerGuide = {
+ Refresh = refresh,
+ Show = PlayerGuide_Show,
+ Hide = PlayerGuide_Hide,
+ InjectDevData = function() C_PlayerGuide._InjectDevPayload() end,
+}
diff --git a/client-export/PlayerGuide.xml b/client-export/PlayerGuide.xml
new file mode 100644
index 0000000..0a3aaf4
--- /dev/null
+++ b/client-export/PlayerGuide.xml
@@ -0,0 +1,498 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client-export/README.md b/client-export/README.md
new file mode 100644
index 0000000..b4b4a38
--- /dev/null
+++ b/client-export/README.md
@@ -0,0 +1,64 @@
+# PlayerGuide — клиентский пакет (3.3.5a / MoonWellClient)
+
+Это материалы для интеграции вкладки **«Путеводитель»** в существующий
+ретропортированный Encounter Journal. Реализация соответствует требованиям
+из `uploads/player-guide-requirements.md` и опирается на канон-визуал
+WotLK (Friz Quadrata, тёмно-синий фон EJ, золотые акценты).
+
+## Структура
+
+```
+MoonWellClient/
+├── EncounterJournal/
+│ ├── Utils/
+│ │ └── C_PlayerGuide.lua ← хранилище + API
+│ ├── Custom_EncounterJournal/
+│ │ ├── Custom_EncounterJournal.xml ← патч: новая вкладка
+│ │ ├── Custom_EncounterJournal.lua ← патч: routing вкладки
+│ │ ├── PlayerGuide.xml ← фреймы и шаблоны (НОВОЕ)
+│ │ └── PlayerGuide.lua ← рендер и логика (НОВОЕ)
+│ └── Localization/
+│ └── ruRU.lua ← патч: MW_PLAYER_GUIDE и др.
+├── AIO/
+│ └── MoonWellPlayerGuide.lua ← AIO-handler (клиентская часть)
+└── MoonWellClient.toc ← патч: подключение файлов
+```
+
+## Порядок интеграции
+
+1. **Скопируйте новые файлы** в проект:
+ * `client-export/PlayerGuide.xml` → `EncounterJournal/Custom_EncounterJournal/PlayerGuide.xml`
+ * `client-export/PlayerGuide.lua` → `EncounterJournal/Custom_EncounterJournal/PlayerGuide.lua`
+ * `client-export/C_PlayerGuide.lua` → `EncounterJournal/Utils/C_PlayerGuide.lua`
+ * `client-export/MoonWellPlayerGuide.lua` → `AIO/MoonWellPlayerGuide.lua`
+2. **Примените патчи** из `client-export/patches/` к существующим файлам
+ (см. ниже — `Custom_EncounterJournal.xml`, `Custom_EncounterJournal.lua`,
+ `MoonWellClient.toc`, `Localization/ruRU.lua`).
+3. **Перезагрузите интерфейс** (`/reload`). Если AIO ещё не передал
+ payload — увидите «пустое» состояние с кнопкой «Обновить».
+
+## Что вошло в MVP (по требованиям)
+
+| MVP-пункт | Где |
+| ----------------------------- | ------------------------------------------- |
+| вкладка `Путеводитель` | `Custom_EncounterJournal.xml` патч |
+| пустой `PlayerGuideFrame` | `PlayerGuide.xml` |
+| `C_PlayerGuide.lua` + статика | `C_PlayerGuide.lua` |
+| заголовок этапа + цели | `PlayerGuide.lua → PlayerGuide_Refresh` |
+| tab switching / hide-show | `Custom_EncounterJournal.lua → EJ_ContentTab_OnClick` хук |
+| AIO `SetData` | `MoonWellPlayerGuide.lua → handlers.SetData` |
+| Обновить (RequestRefresh) | `PlayerGuide.lua → PlayerGuide_RefreshButton_OnClick` |
+
+## Что отложено (см. «Later UI» в требованиях)
+
+* Фильтры (все / активные / завершённые)
+* Pinning отслеживаемой цели
+* **Награды** — блок временно отключён (`SHOW_REWARDS = false`)
+* Серверные уведомления (`Notify`)
+
+## Сноска по визуалу
+
+Текстуры в XML — это встроенные ресурсы 3.3.5a-клиента. Если у вас
+есть атлас MoonWell — замените пути в блоке `-- TEXTURE_ATLAS` на свои.
+Биом-обложки рекомендаций (`Interface\AddOns\MoonWellClient\EncounterJournal\Textures\Biome-*`)
+надо создать отдельно — это плейсхолдеры (см. таблицу в `PlayerGuide.lua`).
diff --git a/client-export/patches/Custom_EncounterJournal.lua.patch.lua b/client-export/patches/Custom_EncounterJournal.lua.patch.lua
new file mode 100644
index 0000000..923925f
--- /dev/null
+++ b/client-export/patches/Custom_EncounterJournal.lua.patch.lua
@@ -0,0 +1,120 @@
+--[[----------------------------------------------------------------------------
+ patches/Custom_EncounterJournal.lua.patch
+ ─────────────────────────────────────────────────────────────────────────────
+ Патч-сниппеты для существующего Custom_EncounterJournal.lua. Эти куски
+ добавляют routing новой вкладки и hide-show поведение по требованиям:
+
+ «при выборе guide tab:
+ - hide instance cards
+ - hide Encounter Journal detail panel
+ - hide suggested content panel
+ - hide loot journal panel
+ - hide or disable the expansion/tier dropdown unless explicitly needed
+ - show PlayerGuideFrame»
+------------------------------------------------------------------------------]]
+
+-- ─── ПАТЧ #1 ───────────────────────────────────────────────────────────────
+-- НАЙТИ функцию EJ_ContentTab_Select (или ту, что переключает вкладки в
+-- Encounter Journal). Обычно она выглядит как switch по id вкладки.
+-- ДОБАВИТЬ ветку для нашей вкладки. Пример полностью переписанной функции:
+
+local PLAYERGUIDE_TAB_ID = 1 -- должен совпадать с id="1" в XML патче
+
+function EJ_ContentTab_Select(id)
+ EncounterJournal.suggestTab:UnlockHighlight()
+ EncounterJournal.dungeonsTab:UnlockHighlight()
+ EncounterJournal.raidsTab:UnlockHighlight()
+ if EncounterJournal.lootJournalTab then
+ EncounterJournal.lootJournalTab:UnlockHighlight()
+ end
+ if EncounterJournal.guideTab then
+ EncounterJournal.guideTab:UnlockHighlight()
+ end
+
+ -- Прячем «обычные» панели EJ. Этот хелпер уже есть в Custom_EncounterJournal:
+ -- EncounterJournal_HideAllPanels()
+ -- Если его нет — выньте тело сюда (Hide instance list, encounter, loot).
+ EncounterJournal_HideAllPanels()
+
+ -- Прячем PlayerGuideFrame — он показывается только на guide-вкладке.
+ if PlayerGuideFrame then PlayerGuideFrame:Hide() end
+
+ if id == PLAYERGUIDE_TAB_ID then
+ -- НАША ВКЛАДКА -----------------------------------------------------
+ EncounterJournal.guideTab:LockHighlight()
+ EncounterJournal.instanceSelect:Hide()
+ EncounterJournal.encounter:Hide()
+ if EncounterJournalSuggestFrame then EncounterJournalSuggestFrame:Hide() end
+ if LootJournal then LootJournal:Hide() end
+ -- Скрыть/задисейблить дропдаун расширений, как просят требования:
+ if EJTierDropDown then EJTierDropDown:Hide() end
+
+ if PlayerGuideFrame then PlayerGuideFrame:Show() end
+ return
+ end
+
+ -- ── Остальные вкладки — оригинальная логика ──
+ if EJTierDropDown then EJTierDropDown:Show() end
+
+ if id == 2 then -- SuggestTab (было 1)
+ EncounterJournal.suggestTab:LockHighlight()
+ EncounterJournal_ListInstances() -- или ваш Suggest-Show
+ elseif id == 3 then -- DungeonTab
+ EncounterJournal.dungeonsTab:LockHighlight()
+ EJ_HideNonInstancePanels()
+ EncounterJournal_ListInstances()
+ elseif id == 4 then -- RaidTab
+ EncounterJournal.raidsTab:LockHighlight()
+ EJ_HideNonInstancePanels()
+ EncounterJournal_ListInstances()
+ elseif id == 5 then -- LootJournalTab
+ if EncounterJournal.lootJournalTab then
+ EncounterJournal.lootJournalTab:LockHighlight()
+ end
+ if LootJournal_Show then LootJournal_Show() end
+ end
+end
+
+
+-- ─── ПАТЧ #2 ───────────────────────────────────────────────────────────────
+-- В EJ_ContentTab_OnClick добавить вызов нашего Select для tab id=1
+-- (если у вас один централизованный _OnClick — он уже передаёт id и
+-- ничего дополнительно делать не нужно):
+
+function EJ_ContentTab_OnClick(self)
+ EJ_ContentTab_Select(self:GetID())
+ PlaySound("igCharacterInfoTab")
+end
+
+
+-- ─── ПАТЧ #3 ───────────────────────────────────────────────────────────────
+-- Защита: при открытии EJ через EncounterJournal_OpenJournal — переключиться
+-- НА dungeon/raid таб, а не оставлять guide-таб выбранным.
+-- Найдите вашу EncounterJournal_OpenJournal и убедитесь, что в начале:
+
+local _orig_EncounterJournal_OpenJournal = EncounterJournal_OpenJournal
+function EncounterJournal_OpenJournal(instanceID, encounterID, ...)
+ -- При прямом открытии конкретного instance — переключиться на Dungeon/Raid
+ if instanceID then
+ EJ_ContentTab_Select(3) -- Dungeon по умолчанию; ваша логика может выбрать Raid
+ end
+ return _orig_EncounterJournal_OpenJournal(instanceID, encounterID, ...)
+end
+
+
+-- ─── ПАТЧ #4 ───────────────────────────────────────────────────────────────
+-- Init: статика для разработки (можно убрать перед релизом). Если AIO
+-- ещё не успел прислать payload — покажем dev-payload через 1с после
+-- первого открытия EJ.
+
+local _devInjected = false
+EncounterJournal:HookScript("OnShow", function()
+ if not _devInjected and not C_PlayerGuide.HasData() then
+ _devInjected = true
+ C_Timer.After(1.0, function()
+ if not C_PlayerGuide.HasData() then
+ C_PlayerGuide._InjectDevPayload()
+ end
+ end)
+ end
+end)
diff --git a/client-export/patches/Custom_EncounterJournal.xml.patch.lua b/client-export/patches/Custom_EncounterJournal.xml.patch.lua
new file mode 100644
index 0000000..21e41a3
--- /dev/null
+++ b/client-export/patches/Custom_EncounterJournal.xml.patch.lua
@@ -0,0 +1,57 @@
+--[[----------------------------------------------------------------------------
+ patches/Custom_EncounterJournal.xml.patch
+ ─────────────────────────────────────────────────────────────────────────────
+ Это НЕ замена файла — это патч-сниппеты для существующего
+ Custom_EncounterJournal.xml. Вставьте обозначенные блоки.
+
+ В оригинальном Custom_EncounterJournal.xml внутри EncounterJournal.bg или
+ аналогичного контейнера уже есть вкладки SuggestTab / DungeonTab / RaidTab /
+ LootJournalTab. Нужно вставить GuideTab ПЕРЕД ними (id=1) и сдвинуть
+ анкоры остальных.
+------------------------------------------------------------------------------]]
+
+-- ─── ПАТЧ #1 ───────────────────────────────────────────────────────────────
+-- НАЙТИ блок вкладки SuggestTab (или то, что у вас сейчас называется
+-- «$parentSuggestTab» / «$parentDungeonTab») и ДОБАВИТЬ перед ним
+-- следующую кнопку. id=1, чтобы EJ_ContentTab_OnClick знал об этой вкладке.
+
+
+
+
+-- ─── ПАТЧ #2 ───────────────────────────────────────────────────────────────
+-- ИЗМЕНИТЬ id существующих вкладок (теперь Путеводитель = 1):
+--
+-- SuggestTab id="2" (было 1)
+-- DungeonTab id="3" (было 2)
+-- RaidTab id="4" (было 3)
+-- LootJournalTab id="5" (было 4)
+--
+-- И СДВИНУТЬ анкор первой следующей вкладки (SuggestTab), чтобы она
+-- цеплялась за GuideTab:
+
+
+
+
+
+
+
+
+-- ─── ПАТЧ #3 ───────────────────────────────────────────────────────────────
+-- В конце ... , ПЕРЕД закрывающим тегом, добавить include
+-- для нашего PlayerGuide.xml, чтобы PlayerGuideFrame создавался ВНУТРИ
+-- родителя EncounterJournal:
+
+
diff --git a/client-export/patches/Localization-ruRU.lua.patch.lua b/client-export/patches/Localization-ruRU.lua.patch.lua
new file mode 100644
index 0000000..17058d3
--- /dev/null
+++ b/client-export/patches/Localization-ruRU.lua.patch.lua
@@ -0,0 +1,43 @@
+--[[----------------------------------------------------------------------------
+ patches/Localization-ruRU.lua.patch
+ ─────────────────────────────────────────────────────────────────────────────
+ Строки локализации для вкладки «Путеводитель».
+ Вставьте этот блок в ваш существующий Localization/ruRU.lua (или
+ ruRU.lua в корне), либо подключите как отдельный файл и добавьте в .toc.
+------------------------------------------------------------------------------]]
+
+-- Имя вкладки
+MW_PLAYER_GUIDE = "Путеводитель"
+
+-- Заголовки секций
+MW_PLAYER_GUIDE_OBJECTIVES = "Задачи этапа"
+MW_PLAYER_GUIDE_RECS = "Подходящие подземелья"
+MW_PLAYER_GUIDE_REWARDS = "Награды за этап"
+
+-- Шапка
+MW_PLAYER_GUIDE_STAGE_OF = "ЭТАП %d ИЗ %d"
+MW_PLAYER_GUIDE_STAGE_PROGRESS = "ПРОГРЕСС ЭТАПА"
+MW_PLAYER_GUIDE_REFRESH = "Обновить"
+
+-- Пустое состояние
+MW_PLAYER_GUIDE_EMPTY_TITLE = "Путеводитель ещё не открыт"
+MW_PLAYER_GUIDE_EMPTY_BODY = "Данные о вашем прогрессе ещё не получены с сервера. "..
+ "Это может занять несколько секунд после входа в игру."
+
+-- Загрузка
+MW_PLAYER_GUIDE_LOADING_TITLE = "ЗАПРАШИВАЕМ ХРОНИКИ"
+MW_PLAYER_GUIDE_LOADING_BODY = "Ожидание данных от Путеводителя"
+
+-- Caps-плашки типов целей (используются в карточке цели)
+MW_PG_TYPE_LEVEL = "УРОВЕНЬ"
+MW_PG_TYPE_QUEST = "ЗАДАНИЕ"
+MW_PG_TYPE_QUEST_CHAIN = "ЦЕПОЧКА"
+MW_PG_TYPE_DUNGEON = "ПОДЗЕМЕЛЬЕ"
+MW_PG_TYPE_RAID = "РЕЙД"
+MW_PG_TYPE_BOSS = "БОСС"
+MW_PG_TYPE_ACHIEVEMENT = "ДОСТИЖЕНИЕ"
+MW_PG_TYPE_REPUTATION = "РЕПУТАЦИЯ"
+MW_PG_TYPE_PROFESSION = "ПРОФЕССИЯ"
+MW_PG_TYPE_ITEM = "ПРЕДМЕТ"
+MW_PG_TYPE_CURRENCY = "ВАЛЮТА"
+MW_PG_TYPE_CUSTOM = "ЗАДАЧА"
diff --git a/client-export/patches/MoonWellClient.toc.patch b/client-export/patches/MoonWellClient.toc.patch
new file mode 100644
index 0000000..ff3da41
--- /dev/null
+++ b/client-export/patches/MoonWellClient.toc.patch
@@ -0,0 +1,28 @@
+# patches/MoonWellClient.toc.patch
+#
+# Сниппет для добавления в существующий MoonWellClient.toc. ВАЖНО: порядок
+# подключения файлов критичен — C_PlayerGuide.lua должен идти ДО PlayerGuide.lua,
+# а PlayerGuide.xml — ПОСЛЕ Custom_EncounterJournal.xml (PlayerGuideFrame
+# анкорится к EncounterJournal как parent).
+#
+# Вставьте строки ниже в соответствующие места вашего .toc.
+
+# ─── Локализация ────────────────────────────────────────────────────────────
+# В блок Localization, рядом с остальными ruRU.lua:
+Localization\ruRU.lua
+
+# ─── Хранилище и API ────────────────────────────────────────────────────────
+# В блок EncounterJournal\Utils\, до подключения чего-либо из
+# Custom_EncounterJournal\:
+EncounterJournal\Utils\C_PlayerGuide.lua
+
+# ─── Сам Encounter Journal (ОБНОВЛЁННЫЙ ПОРЯДОК) ────────────────────────────
+# Эти строки заменяют ваш существующий блок Custom_EncounterJournal:
+EncounterJournal\Custom_EncounterJournal\Custom_EncounterJournal.xml
+EncounterJournal\Custom_EncounterJournal\PlayerGuide.xml
+EncounterJournal\Custom_EncounterJournal\PlayerGuide.lua
+EncounterJournal\Custom_EncounterJournal\Custom_EncounterJournal.lua
+
+# ─── AIO-handler ────────────────────────────────────────────────────────────
+# Должен подключаться ПОСЛЕ C_PlayerGuide.lua и AIO/AIO_Client.lua:
+AIO\MoonWellPlayerGuide.lua
diff --git a/client-export/textures/Biome-Arcane.png b/client-export/textures/Biome-Arcane.png
new file mode 100644
index 0000000..5803128
Binary files /dev/null and b/client-export/textures/Biome-Arcane.png differ
diff --git a/client-export/textures/Biome-Fire.png b/client-export/textures/Biome-Fire.png
new file mode 100644
index 0000000..3a72179
Binary files /dev/null and b/client-export/textures/Biome-Fire.png differ
diff --git a/client-export/textures/Biome-Holy.png b/client-export/textures/Biome-Holy.png
new file mode 100644
index 0000000..6949b8c
Binary files /dev/null and b/client-export/textures/Biome-Holy.png differ
diff --git a/client-export/textures/Biome-Nature.png b/client-export/textures/Biome-Nature.png
new file mode 100644
index 0000000..216a43b
Binary files /dev/null and b/client-export/textures/Biome-Nature.png differ
diff --git a/client-export/textures/Biome-Shadow.png b/client-export/textures/Biome-Shadow.png
new file mode 100644
index 0000000..0db52c8
Binary files /dev/null and b/client-export/textures/Biome-Shadow.png differ
diff --git a/client-export/textures/Biome-Storm.png b/client-export/textures/Biome-Storm.png
new file mode 100644
index 0000000..fa75beb
Binary files /dev/null and b/client-export/textures/Biome-Storm.png differ
diff --git a/client-export/textures/Button-Down.png b/client-export/textures/Button-Down.png
new file mode 100644
index 0000000..af519ea
Binary files /dev/null and b/client-export/textures/Button-Down.png differ
diff --git a/client-export/textures/Button-Highlight.png b/client-export/textures/Button-Highlight.png
new file mode 100644
index 0000000..dd08411
Binary files /dev/null and b/client-export/textures/Button-Highlight.png differ
diff --git a/client-export/textures/Button-Up.png b/client-export/textures/Button-Up.png
new file mode 100644
index 0000000..9ab62f0
Binary files /dev/null and b/client-export/textures/Button-Up.png differ
diff --git a/client-export/textures/Card-Background.png b/client-export/textures/Card-Background.png
new file mode 100644
index 0000000..a097cd5
Binary files /dev/null and b/client-export/textures/Card-Background.png differ
diff --git a/client-export/textures/Card-Border.png b/client-export/textures/Card-Border.png
new file mode 100644
index 0000000..adeba15
Binary files /dev/null and b/client-export/textures/Card-Border.png differ
diff --git a/client-export/textures/Corner-Ornament.png b/client-export/textures/Corner-Ornament.png
new file mode 100644
index 0000000..97f4295
Binary files /dev/null and b/client-export/textures/Corner-Ornament.png differ
diff --git a/client-export/textures/ProgressBar-BG.png b/client-export/textures/ProgressBar-BG.png
new file mode 100644
index 0000000..6685bfd
Binary files /dev/null and b/client-export/textures/ProgressBar-BG.png differ
diff --git a/client-export/textures/ProgressBar-Fill.png b/client-export/textures/ProgressBar-Fill.png
new file mode 100644
index 0000000..446c09d
Binary files /dev/null and b/client-export/textures/ProgressBar-Fill.png differ
diff --git a/client-export/textures/README.md b/client-export/textures/README.md
new file mode 100644
index 0000000..cea6014
--- /dev/null
+++ b/client-export/textures/README.md
@@ -0,0 +1,125 @@
+# PlayerGuide — текстуры
+
+Все файлы — **PNG с альфа-каналом**, размеры — **степень двойки**
+(требование BLP-конвертера). Палитра канон-WotLK: золото (`#ffd76a`)
+на тёмно-коричневом (`#1a1208`).
+
+## Что есть
+
+| Файл | Размер | Куда |
+|---|---|---|
+| `StageBadge-Active.png` | 64×64 | Бейдж текущего этапа в цепочке. |
+| `StageBadge-Done.png` | 64×64 | Бейдж завершённого этапа. |
+| `StageBadge-Locked.png` | 64×64 | Бейдж недоступного этапа. |
+| `ProgressBar-Fill.png` | 128×16 | Заливка прогресс-бара (`BarTexture`). |
+| `ProgressBar-BG.png` | 128×16 | Подложка прогресс-бара. |
+| `Card-Background.png` | 256×256 | Тайл-фон карточек (`bgFile`, tileable). |
+| `Card-Border.png` | 256×32 | Рамка карточки (`edgeFile`, 8 сегментов 32×32: up/down/left/right/TL/TR/BL/BR). |
+| `Section-Divider.png` | 256×16 | Декоративный разделитель секций. |
+| `Corner-Ornament.png` | 64×64 | Угол декоративной рамки фрейма. |
+| `Top-Wave-Glow.png` | 512×64 | «Волна» свечения сверху (как в оригинальном EJ). |
+| `Biome-Fire.png` | 256×128 | Обложка рекомендации — огненные локации. |
+| `Biome-Arcane.png` | 256×128 | Тайная магия. |
+| `Biome-Storm.png` | 256×128 | Буря/вода. |
+| `Biome-Shadow.png` | 256×128 | Тьма. |
+| `Biome-Nature.png` | 256×128 | Природа. |
+| `Biome-Holy.png` | 256×128 | Свет/нежить. |
+| `TypeIcon-Level.png` | 64×64 | Иконка цели «уровень». |
+| `TypeIcon-Quest.png` | 64×64 | «задание». |
+| `TypeIcon-QuestChain.png` | 64×64 | «цепочка». |
+| `TypeIcon-Dungeon.png` | 64×64 | «подземелье». |
+| `TypeIcon-Raid.png` | 64×64 | «рейд». |
+| `TypeIcon-Boss.png` | 64×64 | «босс». |
+| `TypeIcon-Achievement.png` | 64×64 | «достижение». |
+| `TypeIcon-Reputation.png` | 64×64 | «репутация». |
+| `TypeIcon-Profession.png` | 64×64 | «профессия». |
+| `TypeIcon-Item.png` | 64×64 | «предмет». |
+| `TypeIcon-Currency.png` | 64×64 | «валюта». |
+| `TypeIcon-Custom.png` | 64×64 | прочее. |
+| `TypeIcon-Done.png` | 64×64 | Цель завершена (зелёная галочка). |
+| `TypeIcon-Locked.png` | 64×64 | Цель заблокирована (замок). |
+| `Button-Up.png` | 128×32 | Кнопка «Обновить», нормальное. |
+| `Button-Down.png` | 128×32 | Кнопка нажата. |
+| `Button-Highlight.png` | 128×32 | Hover. |
+
+## Куда положить в проекте
+
+```
+MoonWellClient/EncounterJournal/Textures/PlayerGuide/
+├── StageBadge-Active.blp
+├── StageBadge-Done.blp
+├── ...
+└── Button-Highlight.blp
+```
+
+И в XML использовать пути:
+```
+file="Interface\AddOns\MoonWellClient\EncounterJournal\Textures\PlayerGuide\StageBadge-Active"
+```
+(WoW сам подставит `.blp`.)
+
+## Конвертация PNG → BLP
+
+Любой из:
+- **BLPNG Converter** (Windows, GUI) — самый простой, drag-and-drop;
+- **BLPLab** — с предпросмотром;
+- **CLI**: `blpconverter input.png output.blp` (есть пайплайны на GitHub).
+
+Параметры:
+- **Compression:** `DXT5` для всего с альфой (всё, кроме `Card-Background` —
+ для него `DXT1` или `Uncompressed`, если хочется лучше);
+- **Mipmaps:** включить (`Generate Mipmaps`), кроме `ProgressBar-Fill/BG`
+ (тонкие полоски ломаются на мипмапах — там лучше off);
+- **Sampling:** `Bicubic` или `Lanczos`.
+
+## Замена биом-обложек
+
+Сейчас биом-обложки — стилизованные плашки с аркой и светящимся центром.
+Их можно полностью заменить вашими собственными — главное, оставить размер
+**256×128** и имена файлов. Если поменяете список биомов, поправьте таблицу
+`BIOME_COLOR` в `PlayerGuide.lua`.
+
+## Замена иконок типов целей
+
+Если у вас есть атлас иконок WoW (например, из `Interface/Icons/`) — карта
+`TYPE_ICON` в `PlayerGuide.lua` уже использует встроенные текстуры
+клиента. Текстуры `TypeIcon-*` нужны, только если хочется единого
+визуального словаря (рамка + глиф).
+
+## Применение в XML (примеры)
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Сноска
+
+Это плейсхолдеры на уровне «лучше, чем встроенные UI-Quickslot2». Если в
+проекте есть художник — финальные текстуры стоит делать в этом же
+визуальном словаре, чтобы Lua/XML менять не пришлось (только перерисовать
+PNG того же размера и сконвертировать).
diff --git a/client-export/textures/Section-Divider.png b/client-export/textures/Section-Divider.png
new file mode 100644
index 0000000..73c75bb
Binary files /dev/null and b/client-export/textures/Section-Divider.png differ
diff --git a/client-export/textures/StageBadge-Active.png b/client-export/textures/StageBadge-Active.png
new file mode 100644
index 0000000..8ef3ead
Binary files /dev/null and b/client-export/textures/StageBadge-Active.png differ
diff --git a/client-export/textures/StageBadge-Done.png b/client-export/textures/StageBadge-Done.png
new file mode 100644
index 0000000..f87af12
Binary files /dev/null and b/client-export/textures/StageBadge-Done.png differ
diff --git a/client-export/textures/StageBadge-Locked.png b/client-export/textures/StageBadge-Locked.png
new file mode 100644
index 0000000..a3c4da0
Binary files /dev/null and b/client-export/textures/StageBadge-Locked.png differ
diff --git a/client-export/textures/Top-Wave-Glow.png b/client-export/textures/Top-Wave-Glow.png
new file mode 100644
index 0000000..91b05ca
Binary files /dev/null and b/client-export/textures/Top-Wave-Glow.png differ
diff --git a/client-export/textures/TypeIcon-Achievement.png b/client-export/textures/TypeIcon-Achievement.png
new file mode 100644
index 0000000..0cf1a20
Binary files /dev/null and b/client-export/textures/TypeIcon-Achievement.png differ
diff --git a/client-export/textures/TypeIcon-Boss.png b/client-export/textures/TypeIcon-Boss.png
new file mode 100644
index 0000000..223e34f
Binary files /dev/null and b/client-export/textures/TypeIcon-Boss.png differ
diff --git a/client-export/textures/TypeIcon-Currency.png b/client-export/textures/TypeIcon-Currency.png
new file mode 100644
index 0000000..e7f9a1c
Binary files /dev/null and b/client-export/textures/TypeIcon-Currency.png differ
diff --git a/client-export/textures/TypeIcon-Custom.png b/client-export/textures/TypeIcon-Custom.png
new file mode 100644
index 0000000..ac45174
Binary files /dev/null and b/client-export/textures/TypeIcon-Custom.png differ
diff --git a/client-export/textures/TypeIcon-Done.png b/client-export/textures/TypeIcon-Done.png
new file mode 100644
index 0000000..46dfc34
Binary files /dev/null and b/client-export/textures/TypeIcon-Done.png differ
diff --git a/client-export/textures/TypeIcon-Dungeon.png b/client-export/textures/TypeIcon-Dungeon.png
new file mode 100644
index 0000000..0d5e9e2
Binary files /dev/null and b/client-export/textures/TypeIcon-Dungeon.png differ
diff --git a/client-export/textures/TypeIcon-Item.png b/client-export/textures/TypeIcon-Item.png
new file mode 100644
index 0000000..8ab337a
Binary files /dev/null and b/client-export/textures/TypeIcon-Item.png differ
diff --git a/client-export/textures/TypeIcon-Level.png b/client-export/textures/TypeIcon-Level.png
new file mode 100644
index 0000000..5ff3dba
Binary files /dev/null and b/client-export/textures/TypeIcon-Level.png differ
diff --git a/client-export/textures/TypeIcon-Locked.png b/client-export/textures/TypeIcon-Locked.png
new file mode 100644
index 0000000..9b517f6
Binary files /dev/null and b/client-export/textures/TypeIcon-Locked.png differ
diff --git a/client-export/textures/TypeIcon-Profession.png b/client-export/textures/TypeIcon-Profession.png
new file mode 100644
index 0000000..4d2c78f
Binary files /dev/null and b/client-export/textures/TypeIcon-Profession.png differ
diff --git a/client-export/textures/TypeIcon-Quest.png b/client-export/textures/TypeIcon-Quest.png
new file mode 100644
index 0000000..7eed4cb
Binary files /dev/null and b/client-export/textures/TypeIcon-Quest.png differ
diff --git a/client-export/textures/TypeIcon-QuestChain.png b/client-export/textures/TypeIcon-QuestChain.png
new file mode 100644
index 0000000..7eed4cb
Binary files /dev/null and b/client-export/textures/TypeIcon-QuestChain.png differ
diff --git a/client-export/textures/TypeIcon-Raid.png b/client-export/textures/TypeIcon-Raid.png
new file mode 100644
index 0000000..223e34f
Binary files /dev/null and b/client-export/textures/TypeIcon-Raid.png differ
diff --git a/client-export/textures/TypeIcon-Reputation.png b/client-export/textures/TypeIcon-Reputation.png
new file mode 100644
index 0000000..b0800b8
Binary files /dev/null and b/client-export/textures/TypeIcon-Reputation.png differ
diff --git a/client-export/textures/sheet.html b/client-export/textures/sheet.html
new file mode 100644
index 0000000..f6ffcb4
--- /dev/null
+++ b/client-export/textures/sheet.html
@@ -0,0 +1,263 @@
+
+
+
+
+ PlayerGuide — Texture Sheet
+
+
+
+
+
+
+
PlayerGuide — лист текстур
+
33 PNG-файла, готовы к конвертации в BLP. Шахматный фон под превью = прозрачность.
+
+
+
+
Демонстрация (как это смотрится в карточке)
+
+
+
+
+
Пройти Кузню Крови
+
Цитадель Адского Пламени • рек. уровень 61—64
+
+
+
+
+ 0 / 1
+
+
+
+
+
+
+
Подготовка к Нордсколу
+
Этап V из VII · 62% завершено
+
+
+
+
+
+
+
+
+
+
+
Бейджи этапов
+
+
+
+
Прогресс-бар
+
+
+
+
Карточка
+
+
+
+
Декор
+
+
+
+
Обложки рекомендаций (биомы)
+
+
+
+
Иконки типов целей
+
+
+
+
Иконки статусов
+
+
+
+
Кнопки
+
+
+
+
+
+
diff --git a/docs/player-guide-requirements.md b/docs/player-guide-requirements.md
new file mode 100644
index 0000000..0175282
--- /dev/null
+++ b/docs/player-guide-requirements.md
@@ -0,0 +1,448 @@
+# Player Guide Requirements
+
+## Goal
+
+Create a `Путеводитель` tab inside the existing Encounter Journal UI.
+
+The guide must show personal character progress calculated by `mod-individual-progress` and recommend the next relevant content: quests, dungeons, raids, bosses, requirements, activities, and rewards.
+
+This feature is not a third Encounter Journal instance type. It is a separate panel inside the same interface.
+
+## High-Level Architecture
+
+```text
+AzerothCore / mod-individual-progress
+ -> calculates player progress
+ -> builds a guide payload
+
+AIO / MoonWell bridge
+ -> sends guide data to the client
+
+MoonWellClient / EncounterJournal
+ -> receives the payload
+ -> stores it in C_PlayerGuide
+ -> renders the Player Guide tab
+```
+
+## Client Components
+
+Add separate client-side files:
+
+```text
+EncounterJournal/Utils/C_PlayerGuide.lua
+EncounterJournal/Custom_EncounterJournal/PlayerGuide.lua
+EncounterJournal/Custom_EncounterJournal/PlayerGuide.xml
+```
+
+Responsibilities:
+
+```text
+C_PlayerGuide.lua
+- stores current guide data
+- exposes a small UI-facing API
+- receives server payloads
+- requests refreshes from the server
+
+PlayerGuide.lua
+- renders guide data
+- refreshes objective rows
+- handles clicks on objectives/recommendations
+
+PlayerGuide.xml
+- defines the guide panel
+- defines static frames, headers, scroll area, row templates
+```
+
+Register these files in `MoonWellClient.toc` before `Custom_EncounterJournal.lua`.
+
+## Encounter Journal Tab
+
+Add a new top-level tab near `Подземелья` and `Рейды`:
+
+```text
+Путеводитель | Подземелья | Рейды | Комплекты
+```
+
+The tab must live in:
+
+```text
+EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.xml
+```
+
+Expected XML shape:
+
+```xml
+
+```
+
+If the guide tab is inserted before existing tabs, anchors for `DungeonTab`, `RaidTab`, and `LootJournalTab` must be adjusted.
+
+Add a localized string:
+
+```lua
+MW_PLAYER_GUIDE = "Путеводитель"
+```
+
+## Tab Selection Behavior
+
+When the guide tab is selected:
+
+```text
+- hide instance cards
+- hide Encounter Journal detail panel
+- hide suggested content panel
+- hide loot journal panel
+- hide or disable the expansion/tier dropdown unless explicitly needed
+- show PlayerGuideFrame
+```
+
+When any other top-level tab is selected:
+
+```text
+- hide PlayerGuideFrame
+```
+
+Do not route this tab through:
+
+```lua
+EJ_GetInstanceByIndex(index, isRaid)
+```
+
+That API is only for dungeon/raid instance lists.
+
+## Client API
+
+Create:
+
+```lua
+C_PlayerGuide = C_PlayerGuide or {}
+```
+
+Required methods:
+
+```lua
+C_PlayerGuide.SetData(data)
+C_PlayerGuide.GetStageInfo()
+C_PlayerGuide.GetNumObjectives()
+C_PlayerGuide.GetObjectiveInfo(index)
+C_PlayerGuide.GetNumRecommendations()
+C_PlayerGuide.GetRecommendationInfo(index)
+C_PlayerGuide.GetNumRewards()
+C_PlayerGuide.GetRewardInfo(index)
+C_PlayerGuide.RequestRefresh()
+```
+
+Minimum behavior:
+
+```text
+SetData(data)
+- validate payload is a table
+- replace current data
+- fire/trigger a UI refresh if the guide panel is visible
+
+GetStageInfo()
+- returns stageID, stageName, stageDescription, progress
+
+GetObjectiveInfo(index)
+- returns a normalized objective record or unpacked objective fields
+
+RequestRefresh()
+- asks the server to resend the current payload
+```
+
+## Server Payload
+
+The server should send one normalized payload per character.
+
+Minimum shape:
+
+```lua
+{
+ version = 1,
+ characterGuid = 123,
+
+ stageID = 10,
+ stageName = "Подготовка к Нордсколу",
+ stageDescription = "Завершите ключевые шаги перед переходом дальше.",
+ progress = 40,
+
+ objectives = {
+ {
+ id = 1,
+ type = "level",
+ title = "Достигнуть 68 уровня",
+ description = "",
+ completed = true,
+ progress = 68,
+ required = 68,
+ targetID = 68,
+ order = 1,
+ },
+ {
+ id = 2,
+ type = "quest",
+ title = "Завершить цепочку Темного портала",
+ description = "",
+ completed = false,
+ progress = 3,
+ required = 8,
+ targetID = 10119,
+ order = 2,
+ },
+ {
+ id = 3,
+ type = "dungeon",
+ title = "Пройти Кузню Крови",
+ description = "",
+ completed = false,
+ progress = 0,
+ required = 1,
+ targetID = 256,
+ instanceID = 256,
+ order = 3,
+ },
+ },
+
+ recommendations = {
+ {
+ id = 1,
+ type = "dungeon",
+ title = "Кузня Крови",
+ description = "Подходит для текущего этапа.",
+ instanceID = 256,
+ priority = 100,
+ },
+ },
+
+ rewards = {
+ {
+ type = "item",
+ itemID = 12345,
+ count = 1,
+ },
+ },
+}
+```
+
+## Objective Types
+
+Support at least:
+
+```text
+level
+quest
+quest_chain
+dungeon
+raid
+boss
+achievement
+reputation
+profession
+item
+currency
+custom
+```
+
+Every objective should use the common fields:
+
+```text
+id
+type
+title
+description
+completed
+progress
+required
+targetID
+order
+```
+
+Optional type-specific fields:
+
+```text
+questID
+questChainID
+instanceID
+encounterID
+achievementID
+factionID
+professionID
+itemID
+currencyID
+```
+
+## Objective Click Behavior
+
+Recommended behavior:
+
+```text
+quest
+- show quest link or quest hint if available
+
+dungeon
+- open Encounter Journal on instanceID
+
+raid
+- open Encounter Journal on instanceID
+
+boss
+- open Encounter Journal on encounterID
+
+item
+- show item tooltip
+
+achievement
+- show achievement UI/link
+
+custom
+- show text-only detail or request a server action
+```
+
+If a target cannot be opened, the UI should fail quietly and keep the guide visible.
+
+## AIO Contract
+
+Use a separate handler namespace:
+
+```text
+MoonWellPlayerGuide
+```
+
+Server to client:
+
+```lua
+SetData(payload)
+UpdateObjective(objective)
+SetStage(stagePayload)
+Notify(message)
+```
+
+Client to server:
+
+```lua
+RequestRefresh()
+RequestTrackObjective(objectiveID)
+RequestOpenTarget(objectiveID)
+```
+
+Minimum MVP only needs:
+
+```lua
+SetData(payload)
+RequestRefresh()
+```
+
+## AzerothCore / mod-individual-progress Requirements
+
+`mod-individual-progress` must:
+
+```text
+- determine the player's current progression stage
+- calculate objective completion state
+- calculate objective progress values
+- build the guide payload
+- send the payload on login
+- send updates when progress changes
+- respond to explicit client refresh requests
+```
+
+Recommended update events:
+
+```text
+login
+level up
+quest accepted
+quest completed
+quest rewarded
+achievement earned
+boss kill
+dungeon completed
+reputation changed
+profession changed
+item acquired, if item objectives are used
+```
+
+## UI Requirements
+
+MVP UI:
+
+```text
+- guide tab
+- stage title
+- stage description
+- total progress percentage
+- objective list
+- completed/incomplete visual state
+- recommendation list
+- manual refresh button
+```
+
+Later UI:
+
+```text
+- categories
+- filters: all / active / completed
+- tracked objective pinning
+- reward preview
+- requirement tooltips
+- direct "Open in Journal" buttons
+- server notifications
+```
+
+## Non-Goals
+
+Do not:
+
+```text
+- store guide progress in JOURNALINSTANCE
+- make the guide a third dungeon/raid instance category
+- overload EJ_GetInstanceByIndex(index, isRaid)
+- depend on Sirus-only globals or realm constants
+- block the old dungeon/raid Encounter Journal if guide data is missing
+```
+
+## MVP Implementation Order
+
+1. Add the `Путеводитель` tab.
+2. Add an empty `PlayerGuideFrame`.
+3. Add `C_PlayerGuide.lua` with static test data.
+4. Render the stage title and three test objectives.
+5. Wire tab switching and hide/show behavior.
+6. Add AIO `MoonWellPlayerGuide.SetData`.
+7. Send test payload from the server.
+8. Replace static data with real `mod-individual-progress` data.
+9. Add click behavior for dungeon/raid/boss objectives.
+10. Add polish: progress bar, icons, rewards, filters.
+
+## Validation
+
+Client should tolerate missing or malformed fields:
+
+```text
+- missing payload -> show empty state
+- missing objectives -> show "no active objectives"
+- missing recommendations -> hide recommendations block
+- unknown objective type -> render as text-only custom objective
+- invalid instanceID/encounterID -> do not throw Lua errors
+```
+
+Server should validate:
+
+```text
+- objective ids are unique within the payload
+- order is stable
+- type is known or custom
+- progress <= required when required is present
+- dungeon/raid/boss targets exist in Encounter Journal data when used
+```
diff --git a/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/DragonUI/modules/micromenu.lua b/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/DragonUI/modules/micromenu.lua
index e8631c0..da7919f 100644
--- a/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/DragonUI/modules/micromenu.lua
+++ b/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/DragonUI/modules/micromenu.lua
@@ -69,25 +69,26 @@ local MainMenuBarBackpackButton = _G.MainMenuBarBackpackButton;
local HelpMicroButton = _G.HelpMicroButton;
local KeyRingButton = _G.KeyRingButton;
--- Button collections (dynamically set based on server)
-local MICRO_BUTTONS
+-- Button collections (rebuilt after addons create optional custom buttons).
+local function BuildMicroButtonList()
+ if isAscensionServer then
+ return {
+ _G.CharacterMicroButton,
+ _G.SpellbookMicroButton,
+ _G.TalentMicroButton,
+ _G.AchievementMicroButton,
+ _G.QuestLogMicroButton,
+ _G.SocialsMicroButton,
+ _G.LFDMicroButton,
+ _G.EncounterJournalMicroButton,
+ _G.PathToAscensionMicroButton,
+ _G.ChallengesMicroButton,
+ _G.MainMenuMicroButton,
+ _G.HelpMicroButton
+ }
+ end
-if isAscensionServer then
- MICRO_BUTTONS = {
- _G.CharacterMicroButton,
- _G.SpellbookMicroButton,
- _G.TalentMicroButton,
- _G.AchievementMicroButton,
- _G.QuestLogMicroButton,
- _G.SocialsMicroButton,
- _G.LFDMicroButton,
- _G.PathToAscensionMicroButton,
- _G.ChallengesMicroButton,
- _G.MainMenuMicroButton,
- _G.HelpMicroButton
- }
-else
- MICRO_BUTTONS = {
+ return {
_G.CharacterMicroButton,
_G.SpellbookMicroButton,
_G.TalentMicroButton,
@@ -95,6 +96,7 @@ else
_G.QuestLogMicroButton,
_G.SocialsMicroButton,
_G.LFDMicroButton,
+ _G.EncounterJournalMicroButton,
_G.CollectionsMicroButton,
_G.PVPMicroButton,
_G.MainMenuMicroButton,
@@ -102,6 +104,7 @@ else
}
end
+local MICRO_BUTTONS = BuildMicroButtonList()
local bagslots = {_G.CharacterBag0Slot, _G.CharacterBag1Slot, _G.CharacterBag2Slot, _G.CharacterBag3Slot};
@@ -783,6 +786,8 @@ local function ApplyMicromenuSystem()
return
end
+ MICRO_BUTTONS = BuildMicroButtonList()
+
-- Store original states first
StoreOriginalMicroButtonStates()
@@ -911,6 +916,8 @@ local function ApplyMicromenuSystem()
or (_G.PVPParentFrame and _G.PVPParentFrame:IsVisible() and true or false)
or (_G.BattlefieldFrame and _G.BattlefieldFrame:IsVisible() and true or false)
or (_G.HonorFrame and _G.HonorFrame:IsVisible() and true or false)
+ elseif buttonName == "EncounterJournal" then
+ return (_G.EncounterJournal and _G.EncounterJournal:IsVisible() and true or false)
end
return pressed
@@ -919,6 +926,152 @@ local function ApplyMicromenuSystem()
-- ============================================================================
-- SECTION 5: SPECIALIZED BUTTON SETUP
-- ============================================================================
+ local function SetupEncounterJournalButton(button)
+ local iconTexture = 'Interface\\EncounterJournal\\UI-EJ-PortraitIcon'
+ local backgroundTexture = 'Interface\\AddOns\\DragonUI\\Textures\\Micromenu\\uimicromenu2x'
+ local buttonWidth, buttonHeight = button:GetSize()
+ local dx, dy = -1, 1
+ local offX, offY = button:GetPushedTextOffset()
+
+ if not button.DragonUIEncounterJournalIcon then
+ button.DragonUIEncounterJournalIcon = button:CreateTexture(nil, 'ARTWORK')
+ end
+
+ local icon = button.DragonUIEncounterJournalIcon
+ icon:SetTexture(iconTexture)
+ icon:SetTexCoord(0, 1, 0, 1)
+ icon:ClearAllPoints()
+ icon:SetPoint('CENTER', button, 'CENTER', 0, 0)
+ icon:SetSize(buttonWidth - 8, buttonWidth - 8)
+ icon:SetAlpha(1)
+ icon:Show()
+
+ local highlightTexture = button:GetHighlightTexture()
+ if highlightTexture then
+ highlightTexture:SetTexture(iconTexture)
+ highlightTexture:SetTexCoord(0, 1, 0, 1)
+ highlightTexture:ClearAllPoints()
+ highlightTexture:SetAllPoints(icon)
+ highlightTexture:SetBlendMode('ADD')
+ highlightTexture:SetAlpha(0.55)
+ end
+
+ if not button.DragonUIBackground then
+ local bg = button:CreateTexture(nil, 'BACKGROUND')
+ bg:SetTexture(backgroundTexture)
+ bg:SetSize(buttonWidth, buttonHeight + 1)
+ bg:SetTexCoord(0.0654297, 0.12793, 0.330078, 0.490234)
+ bg:SetPoint('CENTER', dx, dy)
+ button.DragonUIBackground = bg
+
+ local bgPushed = button:CreateTexture(nil, 'BACKGROUND')
+ bgPushed:SetTexture(backgroundTexture)
+ bgPushed:SetSize(buttonWidth, buttonHeight + 1)
+ bgPushed:SetTexCoord(0.0654297, 0.12793, 0.494141, 0.654297)
+ bgPushed:SetPoint('CENTER', dx + offX, dy + offY)
+ bgPushed:Hide()
+ button.DragonUIBackgroundPushed = bgPushed
+ else
+ button.DragonUIBackground:SetTexture(backgroundTexture)
+ button.DragonUIBackground:SetTexCoord(0.0654297, 0.12793, 0.330078, 0.490234)
+ button.DragonUIBackground:ClearAllPoints()
+ button.DragonUIBackground:SetPoint('CENTER', dx, dy)
+ button.DragonUIBackground:SetSize(buttonWidth, buttonHeight + 1)
+
+ if button.DragonUIBackgroundPushed then
+ button.DragonUIBackgroundPushed:SetTexture(backgroundTexture)
+ button.DragonUIBackgroundPushed:SetTexCoord(0.0654297, 0.12793, 0.494141, 0.654297)
+ button.DragonUIBackgroundPushed:ClearAllPoints()
+ button.DragonUIBackgroundPushed:SetPoint('CENTER', dx + offX, dy + offY)
+ button.DragonUIBackgroundPushed:SetSize(buttonWidth, buttonHeight + 1)
+ end
+ end
+
+ button.dragonUIState = button.dragonUIState or {}
+ button.dragonUIState.pushed = IsSpecialMicroButtonActive(button, "EncounterJournal")
+ button.dragonUILastState = button.dragonUIState.pushed
+ button.dragonUITimer = button.dragonUITimer or 0
+
+ button.HandleDragonUIState = function()
+ local state = button.dragonUIState
+ local hlTex = button:GetHighlightTexture()
+ if state and state.pushed then
+ if icon then
+ icon:ClearAllPoints()
+ icon:SetPoint('CENTER', button, 'CENTER', offX, offY)
+ icon:SetAlpha(0.7)
+ end
+ if button.DragonUIBackground then
+ button.DragonUIBackground:Hide()
+ end
+ if button.DragonUIBackgroundPushed then
+ button.DragonUIBackgroundPushed:Show()
+ end
+ if hlTex then
+ hlTex:ClearAllPoints()
+ hlTex:SetPoint('TOPLEFT', icon, 'TOPLEFT', 0, 0)
+ hlTex:SetPoint('BOTTOMRIGHT', icon, 'BOTTOMRIGHT', 0, 0)
+ end
+ else
+ if icon then
+ icon:ClearAllPoints()
+ icon:SetPoint('CENTER', button, 'CENTER', 0, 0)
+ icon:SetAlpha(1)
+ end
+ if button.DragonUIBackground then
+ button.DragonUIBackground:Show()
+ end
+ if button.DragonUIBackgroundPushed then
+ button.DragonUIBackgroundPushed:Hide()
+ end
+ if hlTex then
+ hlTex:ClearAllPoints()
+ hlTex:SetAllPoints(icon)
+ end
+ end
+ end
+
+ button:SetScript('OnUpdate', function(self, elapsed)
+ self.dragonUITimer = (self.dragonUITimer or 0) + elapsed
+ if self.dragonUITimer >= 0.1 then
+ self.dragonUITimer = 0
+ local currentState = IsSpecialMicroButtonActive(self, "EncounterJournal")
+ if currentState ~= self.dragonUILastState then
+ self.dragonUILastState = currentState
+ if self.dragonUIState then
+ self.dragonUIState.pushed = currentState
+ end
+ if self.HandleDragonUIState then
+ self.HandleDragonUIState()
+ end
+ end
+ end
+ end)
+
+ if not button.DragonUIStateHooks then
+ button:HookScript('OnMouseDown', function(self)
+ if self.dragonUIState then
+ self.dragonUIState.pushed = true
+ end
+ if self.HandleDragonUIState then
+ self.HandleDragonUIState()
+ end
+ end)
+ button:HookScript('OnMouseUp', function(self)
+ local currentState = IsSpecialMicroButtonActive(self, "EncounterJournal")
+ if self.dragonUIState then
+ self.dragonUIState.pushed = currentState
+ end
+ if self.HandleDragonUIState then
+ self.HandleDragonUIState()
+ end
+ end)
+ button.DragonUIStateHooks = true
+ end
+
+ button.HandleDragonUIState()
+ end
+
local function SetupPVPButton(button)
-- Mirror the Character button pattern:
-- Instead of fighting WoW's internal NormalTexture alpha management,
@@ -1582,6 +1735,8 @@ local function ApplyMicromenuSystem()
end
local function setupMicroButtons(xOffset)
+ MICRO_BUTTONS = BuildMicroButtonList()
+
local buttonxOffset = 0
local useGrayscale = addon.db.profile.micromenu.grayscale_icons
@@ -1705,9 +1860,11 @@ local function ApplyMicromenuSystem()
local isCharacterButton = (buttonName == "Character")
local isPVPButton = (buttonName == "PVP")
+ local isEncounterJournalButton = (buttonName == "EncounterJournal")
- local upCoords = not isCharacterButton and not isPVPButton and GetColoredTextureCoords(name, "Up") or nil
- local shouldUseGrayscale = useGrayscale or (not isPVPButton and not upCoords and not isCharacterButton)
+ local upCoords = not isCharacterButton and not isPVPButton and not isEncounterJournalButton and GetColoredTextureCoords(name, "Up") or nil
+ local shouldUseGrayscale = (useGrayscale and not isEncounterJournalButton) or
+ (not isPVPButton and not isEncounterJournalButton and not upCoords and not isCharacterButton)
if shouldUseGrayscale then
-- Grayscale icons
@@ -1741,6 +1898,8 @@ local function ApplyMicromenuSystem()
end
elseif isPVPButton then
SetupPVPButton(button)
+ elseif isEncounterJournalButton then
+ SetupEncounterJournalButton(button)
elseif isCharacterButton then
SetupCharacterButton(button)
else
@@ -2245,6 +2404,8 @@ end
return
end
+ MICRO_BUTTONS = BuildMicroButtonList()
+
local useGrayscale = addon.db.profile.micromenu.grayscale_icons
local configMode = useGrayscale and "grayscale" or "normal"
local config = addon.db.profile.micromenu[configMode]
diff --git a/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.lua b/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.lua
index d365e46..cddaae8 100644
--- a/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.lua
+++ b/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.lua
@@ -1,4 +1,5 @@
-UIPanelWindows["EncounterJournal"] = { area = "left", pushable = 0, whileDead = 1, width = 830, xOffset = "15", yOffset = "-10"}
+UIPanelWindows["EncounterJournal"] = { area = "left", pushable = 0, whileDead = 1, width = 830, xOffset = "15", yOffset =
+"-10" }
--FILE CONSTANTS
local HEADER_INDENT = 15;
@@ -49,19 +50,19 @@ local rolesByFlag = {
local EJ_Tabs = {};
-EJ_Tabs[1] = {frame="overviewScroll", button="overviewTab"};
-EJ_Tabs[2] = {frame="lootScroll", button="lootTab"};
-EJ_Tabs[3] = {frame="detailsScroll", button="bossTab"};
+EJ_Tabs[1] = { frame = "overviewScroll", button = "overviewTab" };
+EJ_Tabs[2] = { frame = "lootScroll", button = "lootTab" };
+EJ_Tabs[3] = { frame = "detailsScroll", button = "bossTab" };
local EJ_section_openTable = {};
-local EJ_LINK_INSTANCE = 0;
-local EJ_LINK_ENCOUNTER = 1;
-local EJ_LINK_SECTION = 3;
+local EJ_LINK_INSTANCE = 0;
+local EJ_LINK_ENCOUNTER = 1;
+local EJ_LINK_SECTION = 3;
-local EJ_DIFFICULTIES = {
+local EJ_DIFFICULTIES = {
{ size = "5", prefix = PLAYER_DIFFICULTY1, difficultyID = 1, difficultyMask = 1 },
{ size = "5", prefix = PLAYER_DIFFICULTY2, difficultyID = 2, difficultyMask = 2 },
{ size = "5", prefix = PLAYER_DIFFICULTY3, difficultyID = 3, difficultyMask = 4 },
@@ -71,7 +72,7 @@ local EJ_DIFFICULTIES = {
{ size = "25", prefix = PLAYER_DIFFICULTY2, difficultyID = 4, difficultyMask = 8 },
}
-local EJ_TIER_DATA =
+local EJ_TIER_DATA =
{
[1] = { backgroundAtlas = "UI-EJ-Classic", r = 1.0, g = 0.8, b = 0.0 },
[2] = { backgroundAtlas = "UI-EJ-BurningCrusade", r = 0.6, g = 0.8, b = 0.0 },
@@ -80,30 +81,30 @@ local EJ_TIER_DATA =
[5] = { backgroundAtlas = "UI-EJ-MistsofPandaria", r = 0.0, g = 0.6, b = 0.2 },
[6] = { backgroundAtlas = "UI-EJ-WarlordsofDraenor", r = 0.82, g = 0.55, b = 0.1 },
[7] = { backgroundAtlas = "UI-EJ-Legion", r = 1.0, g = 0.8, b = 0.0 },
- [8] = { backgroundAtlas = "UI-EJ-BattleforAzeroth", expansionLevel = LE_EXPANSION_BATTLE_FOR_AZEROTH},
- [9] = { backgroundAtlas = "UI-EJ-Shadowlands", expansionLevel = LE_EXPANSION_SHADOWLANDS},
- [10] = { backgroundAtlas = "UI-EJ-Dragonflight", expansionLevel = LE_EXPANSION_DRAGONFLIGHT},
- [11] = { backgroundAtlas = "UI-EJ-TheWarWithin", expansionLevel = LE_EXPANSION_WAR_WITHIN},
- [12] = { backgroundAtlas = "UI-EJ-Midnight", expansionLevel = LE_EXPANSION_MIDNIGHT},
+ [8] = { backgroundAtlas = "UI-EJ-BattleforAzeroth", expansionLevel = LE_EXPANSION_BATTLE_FOR_AZEROTH },
+ [9] = { backgroundAtlas = "UI-EJ-Shadowlands", expansionLevel = LE_EXPANSION_SHADOWLANDS },
+ [10] = { backgroundAtlas = "UI-EJ-Dragonflight", expansionLevel = LE_EXPANSION_DRAGONFLIGHT },
+ [11] = { backgroundAtlas = "UI-EJ-TheWarWithin", expansionLevel = LE_EXPANSION_WAR_WITHIN },
+ [12] = { backgroundAtlas = "UI-EJ-Midnight", expansionLevel = LE_EXPANSION_MIDNIGHT },
}
-EJButtonMixin = {}
+EJButtonMixin = {}
function EJButtonMixin:OnLoad()
local l, t, _, b, r = self.UpLeft:GetTexCoord();
- self.UpLeft:SetTexCoord(l, l + (r-l)/2, t, b);
+ self.UpLeft:SetTexCoord(l, l + (r - l) / 2, t, b);
l, t, _, b, r = self.UpRight:GetTexCoord();
- self.UpRight:SetTexCoord(l + (r-l)/2, r, t, b);
+ self.UpRight:SetTexCoord(l + (r - l) / 2, r, t, b);
l, t, _, b, r = self.DownLeft:GetTexCoord();
- self.DownLeft:SetTexCoord(l, l + (r-l)/2, t, b);
+ self.DownLeft:SetTexCoord(l, l + (r - l) / 2, t, b);
l, t, _, b, r = self.DownRight:GetTexCoord();
- self.DownRight:SetTexCoord(l + (r-l)/2, r, t, b);
+ self.DownRight:SetTexCoord(l + (r - l) / 2, r, t, b);
l, t, _, b, r = self.HighLeft:GetTexCoord();
- self.HighLeft:SetTexCoord(l, l + (r-l)/2, t, b);
+ self.HighLeft:SetTexCoord(l, l + (r - l) / 2, t, b);
l, t, _, b, r = self.HighRight:GetTexCoord();
- self.HighRight:SetTexCoord(l + (r-l)/2, r, t, b);
+ self.HighRight:SetTexCoord(l + (r - l) / 2, r, t, b);
end
function EJButtonMixin:OnMouseDown(button)
@@ -178,7 +179,7 @@ end
function EncounterJournal_OnLoad(self)
EncounterJournalTitleText:SetText(ADVENTURE_JOURNAL);
- SetPortraitToTexture(EncounterJournalPortrait,"Interface\\EncounterJournal\\UI-EJ-PortraitIcon");
+ SetPortraitToTexture(EncounterJournalPortrait, "Interface\\EncounterJournal\\UI-EJ-PortraitIcon");
self:RegisterCustomEvent("EJ_LOOT_DATA_RECIEVED");
self:RegisterCustomEvent("EJ_DIFFICULTY_UPDATE");
self:RegisterCustomEvent("SEARCH_DB_LOADED");
@@ -189,6 +190,8 @@ function EncounterJournal_OnLoad(self)
SetParentFrameLevel(self.encounter)
SetParentFrameLevel(self.encounter.info)
+ self.instanceSelect.guideTab.id = self.instanceSelect.guideTab:GetID()
+ self.instanceSelect.guideTab:SetText(MW_PLAYER_GUIDE)
self.instanceSelect.suggestTab.id = self.instanceSelect.suggestTab:GetID()
self.instanceSelect.dungeonsTab.id = self.instanceSelect.dungeonsTab:GetID()
self.instanceSelect.raidsTab.id = self.instanceSelect.raidsTab:GetID()
@@ -206,7 +209,7 @@ function EncounterJournal_OnLoad(self)
if self.instanceSelect.Tabs then
for _, tab in ipairs(self.instanceSelect.Tabs) do
- tab:SetWidth(max(tab:GetTextWidth()+20, 70))
+ tab:SetWidth(max(tab:GetTextWidth() + 20, 70))
tab.selectedGlow:Hide()
end
end
@@ -238,13 +241,13 @@ function EncounterJournal_OnLoad(self)
HybridScrollFrame_CreateButtons(self.searchResults.scrollFrame, "EncounterSearchLGTemplate", 0, 0);
local homeData = {
- name = NAVIGATIONBAR_HOME,
+ name = ENCOUNTER_JOURNAL_NAVIGATION_HOME or NAVIGATIONBAR_HOME,
OnClick = function()
if self.instanceSelect.selectedTab then
EJ_ContentTab_Select(self.instanceSelect.selectedTab);
NavBar_Reset(self.navBar)
else
- EJSuggestFrame_OpenFrame();
+ EJPlayerGuide_OpenFrame();
end
end,
}
@@ -261,15 +264,15 @@ function EncounterJournal_OnLoad(self)
-- check if tabs are active
local dungeonInstanceID = EJ_GetInstanceByIndex(1, false);
- if( not dungeonInstanceID ) then
+ if (not dungeonInstanceID) then
instanceSelect.dungeonsTab.grayBox:Show();
end
local raidInstanceID = EJ_GetInstanceByIndex(1, true);
- if( not raidInstanceID ) then
+ if (not raidInstanceID) then
instanceSelect.raidsTab.grayBox:Show();
end
- -- set the suggestion panel frame to open by default
- EJSuggestFrame_OpenFrame();
+ -- open the player guide by default
+ EJPlayerGuide_OpenFrame();
self.tab1:SetFrameLevel(1)
self.tab2:SetFrameLevel(1)
@@ -332,7 +335,7 @@ end
function EncounterJournal_DisableTierDropDown(removeText)
UIDropDownMenu_DisableDropDown(EncounterJournal.instanceSelect.tierDropDown);
- if ( removeText ) then
+ if (removeText) then
UIDropDownMenu_SetText(EncounterJournal.instanceSelect.tierDropDown, nil);
else
local tierName = EJ_GetTierInfo(EJ_GetCurrentTier());
@@ -341,10 +344,10 @@ function EncounterJournal_DisableTierDropDown(removeText)
end
function EncounterJournal_HasChangedContext(instanceID, instanceType, difficultyID)
- if ( instanceType == "none" ) then
+ if (instanceType == "none") then
-- we've gone from a dungeon to the open world
return EncounterJournal.lastInstance ~= nil;
- elseif ( instanceID ~= 0 and (instanceID ~= EncounterJournal.lastInstance or EncounterJournal.lastDifficulty ~= difficultyID) ) then
+ elseif (instanceID ~= 0 and (instanceID ~= EncounterJournal.lastInstance or EncounterJournal.lastDifficulty ~= difficultyID)) then
-- dungeon or difficulty has changed
return true;
end
@@ -352,17 +355,17 @@ function EncounterJournal_HasChangedContext(instanceID, instanceType, difficulty
end
function EncounterJournal_ResetDisplay(instanceID, instanceType, difficultyID)
- if ( instanceType == "none" ) then
+ if (instanceType == "none") then
EncounterJournal.lastInstance = nil;
EncounterJournal.lastDifficulty = nil;
- EJSuggestFrame_OpenFrame();
+ EJPlayerGuide_OpenFrame();
else
EJ_ContentTab_SelectAppropriateInstanceTab(instanceID);
EncounterJournal_DisplayInstance(instanceID);
EncounterJournal.lastInstance = instanceID;
-- try to set difficulty to current instance difficulty
- if ( EJ_IsValidInstanceDifficulty(difficultyID) ) then
+ if (EJ_IsValidInstanceDifficulty(difficultyID)) then
EJ_SetDifficulty(difficultyID);
end
EncounterJournal.lastDifficulty = difficultyID;
@@ -373,7 +376,7 @@ function EncounterJournal_OnShow(self)
C_EncounterJournal.OnOpen();
PanelTemplates_SetTab(self, 1)
--- MainMenuMicroButton_HideAlert(EncounterJournalMicroButton);
+ -- MainMenuMicroButton_HideAlert(EncounterJournalMicroButton);
MicroButtonPulseStop(EncounterJournalMicroButton);
UpdateMicroButtons();
@@ -385,12 +388,12 @@ function EncounterJournal_OnShow(self)
--automatically navigate to the current dungeon if you are in one;
local instanceID = EJ_GetCurrentInstance();
local _, instanceType, difficultyID = GetInstanceInfo();
- if ( instanceID and EncounterJournal_HasChangedContext(instanceID, instanceType, difficultyID) ) then
+ if (instanceID and EncounterJournal_HasChangedContext(instanceID, instanceType, difficultyID)) then
EncounterJournal_ResetDisplay(instanceID, instanceType, difficultyID);
end
local tierData = GetEJTierData(EJ_GetCurrentTier());
- if ( instanceSelect.suggestTab:IsEnabled() ~= 1 or EncounterJournal.suggestFrame:IsShown() ) then
+ if (instanceSelect.suggestTab:IsEnabled() ~= 1 or EncounterJournal.suggestFrame:IsShown()) then
tierData = GetEJTierData(EJSuggestTab_GetPlayerTierIndex());
end
instanceSelect.bg:SetAtlas(tierData.backgroundAtlas, true);
@@ -414,7 +417,7 @@ end
function EncounterJournal_OnHide(self)
C_EncounterJournal.OnClose();
UpdateMicroButtons();
- PlaySound("igCharacterInfoClose");
+ PlaySound("igCharacterInfoClose");
self.searchBox:SetText("")
EJ_EndSearch();
@@ -471,7 +474,7 @@ end
function EncounterJournal_OnEvent(self, event, ...)
if event == "SERVICE_DATA_UPDATE"
- or (event == "CUSTOM_CHALLENGE_DEACTIVATED" and select(2, ...) == Enum.HardcoreDeathReason.RESTORE)
+ or (event == "CUSTOM_CHALLENGE_DEACTIVATED" and select(2, ...) == Enum.HardcoreDeathReason.RESTORE)
then
EncounterJournal_InitTab(self)
elseif event == "EJ_LOOT_DATA_RECIEVED" then
@@ -529,7 +532,8 @@ function EncounterJournal_UpdateDifficulty(newDifficultyID, noRefresh)
if selectedEntry then
if selectedEntry.size ~= "5" then
- EncounterJournal.encounter.info.difficulty:SetFormattedText("(%s) %s", selectedEntry.size, selectedEntry.prefix);
+ EncounterJournal.encounter.info.difficulty:SetFormattedText("(%s) %s", selectedEntry.size,
+ selectedEntry.prefix);
else
EncounterJournal.encounter.info.difficulty:SetText(selectedEntry.prefix);
end
@@ -548,7 +552,7 @@ function EncounterJournal_GetCreatureButton(index)
local button = self.creatureButtons[index];
if (not button) then
button = CreateFrame("BUTTON", nil, self, "EncounterCreatureButtonTemplate");
- button:SetPoint("TOPLEFT", self.creatureButtons[index-1], "BOTTOMLEFT", 0, 8);
+ button:SetPoint("TOPLEFT", self.creatureButtons[index - 1], "BOTTOMLEFT", 0, 8);
self.creatureButtons[index] = button;
end
return button;
@@ -558,7 +562,7 @@ local infiniteLoopPolice = false; --design might make a tier that has no instanc
local function EncounterJournal_UpdateInstanceListScrollRange(instanceCount)
local scrollFrame = EncounterJournal.instanceSelect.scroll;
local scrollChild = scrollFrame.child;
- local scrollBar = scrollFrame.ScrollBar or _G[scrollFrame:GetName().."ScrollBar"];
+ local scrollBar = scrollFrame.ScrollBar or _G[scrollFrame:GetName() .. "ScrollBar"];
local rows = math.ceil((instanceCount or 0) / EJ_NUM_INSTANCE_PER_ROW);
local childHeight = 375;
@@ -600,12 +604,14 @@ end
local function EncounterJournal_UpdateBossListScrollRange(bossCount)
local scrollFrame = EncounterJournal.encounter.info.bossesScroll;
local scrollChild = scrollFrame.child;
- local scrollBar = scrollFrame.ScrollBar or _G[scrollFrame:GetName().."ScrollBar"];
+ local scrollBar = scrollFrame.ScrollBar or _G[scrollFrame:GetName() .. "ScrollBar"];
local baseHeight = scrollFrame:GetHeight() or 382;
local contentHeight = baseHeight;
if bossCount and bossCount > 0 then
- contentHeight = math.max(baseHeight, BOSS_BUTTON_FIRST_OFFSET + bossCount * BOSS_BUTTON_HEIGHT + math.max(bossCount - 1, 0) * BOSS_BUTTON_SECOND_OFFSET + 8);
+ contentHeight = math.max(baseHeight,
+ BOSS_BUTTON_FIRST_OFFSET + bossCount * BOSS_BUTTON_HEIGHT +
+ math.max(bossCount - 1, 0) * BOSS_BUTTON_SECOND_OFFSET + 8);
end
scrollChild:SetHeight(contentHeight);
@@ -644,7 +650,7 @@ function EncounterJournal_ListInstances()
if not instanceID and not infiniteLoopPolice then
--disable this tab and select the other one.
infiniteLoopPolice = true;
- if ( showRaid ) then
+ if (showRaid) then
instanceSelect.raidsTab.grayBox:Show();
EJ_ContentTab_Select(instanceSelect.dungeonsTab.id);
else
@@ -656,17 +662,19 @@ function EncounterJournal_ListInstances()
infiniteLoopPolice = false;
while instanceID do
- local instanceButton = scrollFrame["instance"..index];
+ local instanceButton = scrollFrame["instance" .. index];
if not instanceButton then -- create button
- instanceButton = CreateFrame("BUTTON", scrollFrame:GetParent():GetName().."instance"..index, scrollFrame, "EncounterInstanceButtonTemplate");
- if ( EncounterJournal.localizeInstanceButton ) then
+ instanceButton = CreateFrame("BUTTON", scrollFrame:GetParent():GetName() .. "instance" .. index, scrollFrame,
+ "EncounterInstanceButtonTemplate");
+ if (EncounterJournal.localizeInstanceButton) then
EncounterJournal.localizeInstanceButton(instanceButton);
end
- scrollFrame["instance"..index] = instanceButton;
- if mod(index-1, EJ_NUM_INSTANCE_PER_ROW) == 0 then
- instanceButton:SetPoint("TOP", scrollFrame["instance"..(index-EJ_NUM_INSTANCE_PER_ROW)], "BOTTOM", 0, -15);
+ scrollFrame["instance" .. index] = instanceButton;
+ if mod(index - 1, EJ_NUM_INSTANCE_PER_ROW) == 0 then
+ instanceButton:SetPoint("TOP", scrollFrame["instance" .. (index - EJ_NUM_INSTANCE_PER_ROW)], "BOTTOM", 0,
+ -15);
else
- instanceButton:SetPoint("LEFT", scrollFrame["instance"..(index-1)], "RIGHT", 15, 0);
+ instanceButton:SetPoint("LEFT", scrollFrame["instance" .. (index - 1)], "RIGHT", 15, 0);
end
end
@@ -697,9 +705,11 @@ function EncounterJournal_ListInstances()
local currencyItemID = C_EncounterJournal.GetInstanceCurrencyReward(instanceID)
if currencyItemID then
- local currencyName, itemLink, quality, _, _, _, _, _, _, currencyIcon = C_Item.GetItemInfo(currencyItemID, nil, nil, true)
+ local currencyName, itemLink, quality, _, _, _, _, _, _, currencyIcon = C_Item.GetItemInfo(
+ currencyItemID, nil, nil, true)
SetItemButtonQuality(instanceButton.DropInfo.CurrencyItemButton, quality)
- instanceButton.DropInfo.CurrencyItemButton.Icon:SetTexture(currencyIcon or [[Interface\Icons\INV_Misc_QuestionMark]])
+ instanceButton.DropInfo.CurrencyItemButton.Icon:SetTexture(currencyIcon or
+ [[Interface\Icons\INV_Misc_QuestionMark]])
instanceButton.DropInfo.CurrencyItemButton.itemLink = itemLink
instanceButton.DropInfo.CurrencyItemButton:Show()
else
@@ -734,7 +744,7 @@ function EncounterJournal_ListInstances()
--No instances in the other tab
if not instanceText then
--disable the other tab.
- if ( showRaid ) then
+ if (showRaid) then
instanceSelect.dungeonsTab.grayBox:Show();
else
instanceSelect.raidsTab.grayBox:Show();
@@ -763,7 +773,7 @@ local function UpdateDifficultyVisibility()
-- As long as the current tab isn't the model tab, which always suppresses the difficulty, then update the shown state.
local info = EncounterJournal.encounter.info;
- info.difficulty:SetShown(shouldDisplayDifficulty--[[ and (info.tab ~= 4)]]);
+ info.difficulty:SetShown(shouldDisplayDifficulty --[[ and (info.tab ~= 4)]]);
UpdateDifficultyAnchoring(info.difficulty);
end
@@ -807,11 +817,12 @@ function EncounterJournal_DisplayInstance(instanceID, noButton)
self.instance.loreScroll.child.lore:SetWidth(313);
end
- self.instance.FindGroupButton.Text:SetText(EJ_InstanceIsRaid() and ENCOUNTER_JOURNAL_FIND_RAID or ENCOUNTER_JOURNAL_FIND_GROUP)
+ self.instance.FindGroupButton.Text:SetText(EJ_InstanceIsRaid() and ENCOUNTER_JOURNAL_FIND_RAID or
+ ENCOUNTER_JOURNAL_FIND_GROUP)
self.info.instanceButton.instanceID = instanceID;
--- self.info.instanceButton.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
--- self.info.instanceButton.icon:SetTexture(buttonImage);
+ -- self.info.instanceButton.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- self.info.instanceButton.icon:SetTexture(buttonImage);
buttonImage = buttonImage:lower():gsub("%.blp$", ""):gsub("(\\lfgframe)", "%1\\LFGIcon64")
local res = self.info.instanceButton.icon:SetTexture(buttonImage)
@@ -832,18 +843,21 @@ function EncounterJournal_DisplayInstance(instanceID, noButton)
local hasBossAbilities = false;
while bossID do
- bossButton = _G["EncounterJournalBossButton"..bossIndex];
- if not bossButton then -- create a new header;
- bossButton = CreateFrame("BUTTON", "EncounterJournalBossButton"..bossIndex, EncounterJournal.encounter.bossesFrame, "EncounterBossButtonTemplate");
- if bossIndex > 1 then
- bossButton:SetPoint("TOPLEFT", _G["EncounterJournalBossButton"..(bossIndex-1)], "BOTTOMLEFT", 0, -BOSS_BUTTON_SECOND_OFFSET);
- else
- bossButton:SetPoint("TOPLEFT", EncounterJournal.encounter.bossesFrame, "TOPLEFT", 0, -BOSS_BUTTON_FIRST_OFFSET);
- end
+ bossButton = _G["EncounterJournalBossButton" .. bossIndex];
+ if not bossButton then -- create a new header;
+ bossButton = CreateFrame("BUTTON", "EncounterJournalBossButton" .. bossIndex,
+ EncounterJournal.encounter.bossesFrame, "EncounterBossButtonTemplate");
+ if bossIndex > 1 then
+ bossButton:SetPoint("TOPLEFT", _G["EncounterJournalBossButton" .. (bossIndex - 1)], "BOTTOMLEFT", 0,
+ -BOSS_BUTTON_SECOND_OFFSET);
+ else
+ bossButton:SetPoint("TOPLEFT", EncounterJournal.encounter.bossesFrame, "TOPLEFT", 0,
+ -BOSS_BUTTON_FIRST_OFFSET);
end
- EncounterJournal_ConfigureBossButtonScroll(bossButton);
+ end
+ EncounterJournal_ConfigureBossButtonScroll(bossButton);
- bossButton.link = link;
+ bossButton.link = link;
if IsGMAccount() then
local _, _, _, _, _, creatureID, encounterID = EJ_GetCreatureInfo(1, bossID)
bossButton:SetFormattedText("[%d][%d] %s", encounterID or 0, creatureID or 0, name)
@@ -858,16 +872,16 @@ function EncounterJournal_DisplayInstance(instanceID, noButton)
bossButton.creature:SetTexture(bossImage);
bossButton:UnlockHighlight();
- if ( not hasBossAbilities ) then
+ if (not hasBossAbilities) then
hasBossAbilities = rootSectionID > 0;
end
- bossIndex = bossIndex + 1;
- name, description, bossID, rootSectionID, link = EJ_GetEncounterInfoByIndex(bossIndex);
- end
- EncounterJournal_UpdateBossListScrollRange(bossIndex - 1);
+ bossIndex = bossIndex + 1;
+ name, description, bossID, rootSectionID, link = EJ_GetEncounterInfoByIndex(bossIndex);
+ end
+ EncounterJournal_UpdateBossListScrollRange(bossIndex - 1);
- EncounterJournal_SetTabEnabled(EncounterJournal.encounter.info.overviewTab, true);
+ EncounterJournal_SetTabEnabled(EncounterJournal.encounter.info.overviewTab, true);
--disable abilities tab, no boss selected
EncounterJournal_SetTabEnabled(EncounterJournal.encounter.info.bossTab, false);
@@ -880,7 +894,7 @@ function EncounterJournal_DisplayInstance(instanceID, noButton)
else
EJ_Tabs[1].frame = "detailsScroll";
EJ_Tabs[3].frame = "overviewScroll"; -- flip these so detailsScroll won't get hidden, overview will never be shown here
- if ( hasBossAbilities ) then
+ if (hasBossAbilities) then
self.info[EJ_Tabs[1].button].tooltip = ABILITIES;
else
self.info[EJ_Tabs[1].button].tooltip = OVERVIEW;
@@ -934,7 +948,7 @@ function EncounterJournal_DisplayEncounter(encounterID, noButton, scrollToEncoun
end
if rootSectionID == 0 then
--- EncounterJournal_SetTab(EncounterJournal.encounter.info.lootTab:GetID())
+ -- EncounterJournal_SetTab(EncounterJournal.encounter.info.lootTab:GetID())
end
if (EncounterJournal.encounterID == encounterID) then
@@ -975,13 +989,14 @@ function EncounterJournal_DisplayEncounter(encounterID, noButton, scrollToEncoun
bullet:ClearAllPoints();
bullet:SetPoint("TOPLEFT", self.overviewFrame.overviewDescription, "BOTTOMLEFT", 0, -9);
end
- self.overviewFrame.descriptionHeight = self.overviewFrame.loreDescription:GetHeight() + self.overviewFrame.overviewDescription:GetHeight() + bulletHeight + 42;
+ self.overviewFrame.descriptionHeight = self.overviewFrame.loreDescription:GetHeight() +
+ self.overviewFrame.overviewDescription:GetHeight() + bulletHeight + 42;
self.overviewFrame.rootOverviewSectionID = rootSectionID;
rootSectionID = EncounterJournal_GetRootAfterOverviews(rootSectionID);
overviewFound = true;
end
- self.infoFrame.description:SetWidth(self.infoFrame:GetWidth() -5);
+ self.infoFrame.description:SetWidth(self.infoFrame:GetWidth() - 5);
self.infoFrame.description:SetText(description);
self.infoFrame.descriptionHeight = self.infoFrame.description:GetHeight();
@@ -995,18 +1010,21 @@ function EncounterJournal_DisplayEncounter(encounterID, noButton, scrollToEncoun
local name, description, bossID, _, link = EJ_GetEncounterInfoByIndex(bossIndex);
local bossButton;
while bossID do
- bossButton = _G["EncounterJournalBossButton"..bossIndex];
- if not bossButton then -- create a new header;
- bossButton = CreateFrame("BUTTON", "EncounterJournalBossButton"..bossIndex, EncounterJournal.encounter.bossesFrame, "EncounterBossButtonTemplate");
- if bossIndex > 1 then
- bossButton:SetPoint("TOPLEFT", _G["EncounterJournalBossButton"..(bossIndex-1)], "BOTTOMLEFT", 0, -BOSS_BUTTON_SECOND_OFFSET);
- else
- bossButton:SetPoint("TOPLEFT", EncounterJournal.encounter.bossesFrame, "TOPLEFT", 0, -BOSS_BUTTON_FIRST_OFFSET);
- end
+ bossButton = _G["EncounterJournalBossButton" .. bossIndex];
+ if not bossButton then -- create a new header;
+ bossButton = CreateFrame("BUTTON", "EncounterJournalBossButton" .. bossIndex,
+ EncounterJournal.encounter.bossesFrame, "EncounterBossButtonTemplate");
+ if bossIndex > 1 then
+ bossButton:SetPoint("TOPLEFT", _G["EncounterJournalBossButton" .. (bossIndex - 1)], "BOTTOMLEFT", 0,
+ -BOSS_BUTTON_SECOND_OFFSET);
+ else
+ bossButton:SetPoint("TOPLEFT", EncounterJournal.encounter.bossesFrame, "TOPLEFT", 0,
+ -BOSS_BUTTON_FIRST_OFFSET);
end
- EncounterJournal_ConfigureBossButtonScroll(bossButton);
+ end
+ EncounterJournal_ConfigureBossButtonScroll(bossButton);
- bossButton.link = link;
+ bossButton.link = link;
if IsGMAccount() then
local _, _, _, _, _, creatureID, encounterID = EJ_GetCreatureInfo(1, bossID)
bossButton:SetFormattedText("[%d][%d] %s", encounterID or 0, creatureID or 0, name)
@@ -1027,26 +1045,27 @@ function EncounterJournal_DisplayEncounter(encounterID, noButton, scrollToEncoun
bossButton:UnlockHighlight();
end
- bossIndex = bossIndex + 1;
- name, description, bossID, _, link = EJ_GetEncounterInfoByIndex(bossIndex);
- end
- EncounterJournal_UpdateBossListScrollRange(bossIndex - 1);
+ bossIndex = bossIndex + 1;
+ name, description, bossID, _, link = EJ_GetEncounterInfoByIndex(bossIndex);
+ end
+ EncounterJournal_UpdateBossListScrollRange(bossIndex - 1);
- if selectedEncounterIndex and scrollToEncounter then
+ if selectedEncounterIndex and scrollToEncounter then
bossIndex = bossIndex - 1;
- local value, maxScrollRange = ScrollFrame_GetScrollValueForIndex(EncounterJournal.encounter.info.bossesScroll, selectedEncounterIndex, bossIndex, BOSS_BUTTON_HEIGHT, BOSS_BUTTON_SECOND_OFFSET)
+ local value, maxScrollRange = ScrollFrame_GetScrollValueForIndex(EncounterJournal.encounter.info.bossesScroll,
+ selectedEncounterIndex, bossIndex, BOSS_BUTTON_HEIGHT, BOSS_BUTTON_SECOND_OFFSET)
ScrollFrame_OnScrollRangeChanged(EncounterJournal.encounter.info.bossesScroll, 0, maxScrollRange);
EncounterJournal.encounter.info.bossesScroll.ScrollBar:SetValue(value);
end
-- Setup Creatures
local id, name, description, displayInfo, iconImage, creatureID;
- for i=1,MAX_CREATURES_PER_ENCOUNTER do
+ for i = 1, MAX_CREATURES_PER_ENCOUNTER do
id, name, description, displayInfo, iconImage, creatureID = EJ_GetCreatureInfo(i);
if id then
local button = EncounterJournal_GetCreatureButton(i);
- -- SetPortraitTexture(button.creature, displayInfo);
+ -- SetPortraitTexture(button.creature, displayInfo);
button.creature:SetPortrait(displayInfo)
button.name = name;
button.id = id;
@@ -1187,7 +1206,7 @@ end
function EncounterJournal_CleanBullets(self, start, keep)
if (not self.Bullets) then return end
- start = start or 1;
+ start = start or 1;
for i = start, #self.Bullets do
self.Bullets[i]:Hide();
if (not keep) then
@@ -1254,7 +1273,8 @@ local function EncounterJournal_UpdateDetailsScrollRange()
local _, _, _, _, anchorY = header:GetPoint();
local bottom = math.abs(anchorY or 0) + (header:GetHeight() or 0);
if header.description and header.description:IsShown() then
- bottom = bottom + EncounterJournal_UpdateSimpleHTMLHeight(header.description) + SECTION_DESCRIPTION_OFFSET;
+ bottom = bottom + EncounterJournal_UpdateSimpleHTMLHeight(header.description) +
+ SECTION_DESCRIPTION_OFFSET;
else
bottom = bottom + SECTION_BUTTON_OFFSET;
end
@@ -1289,7 +1309,7 @@ function EncounterJournal_SetBullets(object, description, hideBullets)
object.textString = description;
local height = (strlenutf8(description) / parentWidth) * characterHeight
object:SetHeight(height)
- -- object:SetHeight(object.Text:GetContentHeight());
+ -- object:SetHeight(object.Text:GetContentHeight());
EncounterJournal_CleanBullets(parent);
return;
end
@@ -1301,17 +1321,17 @@ function EncounterJournal_SetBullets(object, description, hideBullets)
object.textString = desc;
local height = (strlenutf8(desc) / parentWidth) * characterHeight
object:SetHeight(height)
- -- object:SetHeight(object.Text:GetContentHeight());
+ -- object:SetHeight(object.Text:GetContentHeight());
end
local bullets = {}
- for v in string.gmatch(description,"%$bullet;([^$]+)") do
+ for v in string.gmatch(description, "%$bullet;([^$]+)") do
tinsert(bullets, v);
end
local k = 1;
local skipped = 0;
- for j = 1,#bullets do
+ for j = 1, #bullets do
local text = bullets[j];
if (text and text ~= "") then
local bullet;
@@ -1326,8 +1346,8 @@ function EncounterJournal_SetBullets(object, description, hideBullets)
end
bullet:SetWidth(307)
bullet.Text:SetWidth(300 - 26)
- -- bullet:SetWidth(parent:GetWidth() - 13);
- -- bullet.Text:SetWidth(parentWidth - 26);
+ -- bullet:SetWidth(parent:GetWidth() - 13);
+ -- bullet.Text:SetWidth(parentWidth - 26);
end
bullet:ClearAllPoints();
if (k == 1) then
@@ -1337,7 +1357,7 @@ function EncounterJournal_SetBullets(object, description, hideBullets)
bullet:SetPoint("TOPLEFT", parent, "TOPLEFT", 13, -9 - object:GetHeight());
end
else
- bullet:SetPoint("TOP", parent.Bullets[k-1], "BOTTOM", 0, -8);
+ bullet:SetPoint("TOP", parent.Bullets[k - 1], "BOTTOM", 0, -8);
end
bullet.Text:SetText(text);
@@ -1345,7 +1365,7 @@ function EncounterJournal_SetBullets(object, description, hideBullets)
if (height ~= 0) then
bullet:SetHeight(height);
end
---[[
+ --[[
if (bullet.Text:GetContentHeight() ~= 0) then
bullet:SetHeight(bullet.Text:GetContentHeight());
end
@@ -1381,7 +1401,8 @@ end
function EncounterJournal_SetUpOverview(self, role, index)
local infoHeader;
if not self.overviews[index] then -- create a new header;
- infoHeader = CreateFrame("FRAME", "EncounterJournalOverviewInfoHeader"..index, EncounterJournal.encounter.overviewFrame, "EncounterInfoTemplate");
+ infoHeader = CreateFrame("FRAME", "EncounterJournalOverviewInfoHeader" .. index,
+ EncounterJournal.encounter.overviewFrame, "EncounterInfoTemplate");
infoHeader.description:Hide();
infoHeader.overviewDescription:Hide();
infoHeader.descriptionBG:Hide();
@@ -1414,8 +1435,8 @@ function EncounterJournal_SetUpOverview(self, role, index)
infoHeader:SetPoint("TOPLEFT", 0, -15 - self.descriptionHeight - SECTION_BUTTON_OFFSET);
infoHeader:SetPoint("TOPRIGHT", 0, -15 - self.descriptionHeight - SECTION_BUTTON_OFFSET);
else
- infoHeader:SetPoint("TOPLEFT", self.overviews[index-1], "BOTTOMLEFT", 0, -9);
- infoHeader:SetPoint("TOPRIGHT", self.overviews[index-1], "BOTTOMRIGHT", 0, -9);
+ infoHeader:SetPoint("TOPLEFT", self.overviews[index - 1], "BOTTOMLEFT", 0, -9);
+ infoHeader:SetPoint("TOPRIGHT", self.overviews[index - 1], "BOTTOMRIGHT", 0, -9);
end
infoHeader.description:Hide();
@@ -1427,10 +1448,11 @@ function EncounterJournal_SetUpOverview(self, role, index)
wipe(infoHeader.Bullets);
local title, description, siblingID, link, filteredByDifficulty, flag1
- local _, _, _, _, _, _, nextSectionID = EJ_GetSectionInfo(self.rootOverviewSectionID)
+ local _, _, _, _, _, _, nextSectionID = EJ_GetSectionInfo(self.rootOverviewSectionID)
while nextSectionID do
- title, description, _, _, _, siblingID, _, filteredByDifficulty, link, _, _, flag1 = EJ_GetSectionInfo(nextSectionID)
+ title, description, _, _, _, siblingID, _, filteredByDifficulty, link, _, _, flag1 = EJ_GetSectionInfo(
+ nextSectionID)
if (role == rolesByFlag[flag1] and not filteredByDifficulty) then
break
end
@@ -1454,7 +1476,6 @@ function EncounterJournal_SetUpOverview(self, role, index)
infoHeader:Show();
end
-
function EncounterJournal_ToggleHeaders(self, doNotShift)
local numAdded = 0;
local infoHeader, parentID, _;
@@ -1544,13 +1565,13 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
local listEnd = #usedHeaders;
- if self.myID then -- this is from a button click
- _, _, _, _, _, _, nextSectionID = EJ_GetSectionInfo(self.myID);
- parentID = self.myID;
- self.description:SetWidth(self:GetWidth() -20);
- EncounterJournal_UpdateSimpleHTMLHeight(self.description);
- hWidth = hWidth - HEADER_INDENT;
- else
+ if self.myID then -- this is from a button click
+ _, _, _, _, _, _, nextSectionID = EJ_GetSectionInfo(self.myID);
+ parentID = self.myID;
+ self.description:SetWidth(self:GetWidth() - 20);
+ EncounterJournal_UpdateSimpleHTMLHeight(self.description);
+ hWidth = hWidth - HEADER_INDENT;
+ else
--This sets the base encounter header
parentID = self.encounterID;
nextSectionID = self.rootSectionID;
@@ -1559,7 +1580,8 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
local pass
while nextSectionID do
- local title, description, headerType, abilityIcon, displayInfo, siblingID, nextNextSectionID, fileredByDifficulty, link, startsOpen, creatureEntry, flag1, flag2, flag3, flag4 = EJ_GetSectionInfo(nextSectionID)
+ local title, description, headerType, abilityIcon, displayInfo, siblingID, nextNextSectionID, fileredByDifficulty, link, startsOpen, creatureEntry, flag1, flag2, flag3, flag4 =
+ EJ_GetSectionInfo(nextSectionID)
if nextNextSectionID and nextNextSectionID ~= 0 then
local _, childSectionID = EJ_GetSectionPath(nextSectionID)
@@ -1576,7 +1598,8 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
elseif not fileredByDifficulty then
if #freeHeaders == 0 then -- create a new header;
headerCount = headerCount + 1; -- the is a file local
- infoHeader = CreateFrame("FRAME", "EncounterJournalInfoHeader"..headerCount, EncounterJournal.encounter.infoFrame, "EncounterInfoTemplate");
+ infoHeader = CreateFrame("FRAME", "EncounterJournalInfoHeader" .. headerCount,
+ EncounterJournal.encounter.infoFrame, "EncounterInfoTemplate");
infoHeader:Hide();
else
infoHeader = freeHeaders[#freeHeaders];
@@ -1584,18 +1607,18 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
end
numAdded = numAdded + 1;
- toggleTempList[#toggleTempList+1] = infoHeader;
+ toggleTempList[#toggleTempList + 1] = infoHeader;
infoHeader.button.link = link;
infoHeader.parentID = parentID;
infoHeader.myID = nextSectionID;
-- Spell names can show up in white, which clashes with the parchment, strip out white color codes.
- description = (description or ""):gsub("|cffffffff(.-)|r", "%1");
+ description = (description or ""):gsub("|cffffffff(.-)|r", "%1");
- infoHeader.button.title:SetText(title)
- if topLevelSection then
- infoHeader.button.title:SetFontObject("GameFontNormalMed3");
+ infoHeader.button.title:SetText(title)
+ if topLevelSection then
+ infoHeader.button.title:SetFontObject("GameFontNormalMed3");
else
infoHeader.button.title:SetFontObject("GameFontNormal");
end
@@ -1623,7 +1646,7 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
--Show Creature Portrait
if displayInfo ~= 0 then
- -- SetPortraitTexture(infoHeader.button.portrait.icon, displayInfo)
+ -- SetPortraitTexture(infoHeader.button.portrait.icon, displayInfo)
infoHeader.button.portrait.icon:SetPortrait(displayInfo)
infoHeader.button.portrait.name = title;
infoHeader.button.portrait.displayInfo = creatureEntry;
@@ -1645,27 +1668,30 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
if flag1 then
textRightAnchor = infoHeader.button.icon1
infoHeader.button.icon1:Show()
- infoHeader.button.icon1.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG"..flag1]
- infoHeader.button.icon1.tooltipText = _G["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION"..flag1]
+ infoHeader.button.icon1.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG" .. flag1]
+ infoHeader.button.icon1.tooltipText = _G["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION" .. flag1]
EncounterJournal_SetFlagIcon(infoHeader.button.icon1.icon, flag1)
if flag2 then
textRightAnchor = infoHeader.button.icon2
infoHeader.button.icon2:Show()
EncounterJournal_SetFlagIcon(infoHeader.button.icon2.icon, flag2)
- infoHeader.button.icon2.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG"..flag2]
- infoHeader.button.icon2.tooltipText = _G["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION"..flag2]
+ infoHeader.button.icon2.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG" .. flag2]
+ infoHeader.button.icon2.tooltipText = _G
+ ["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION" .. flag2]
if flag3 then
textRightAnchor = infoHeader.button.icon3
infoHeader.button.icon3:Show()
EncounterJournal_SetFlagIcon(infoHeader.button.icon3.icon, flag3)
- infoHeader.button.icon3.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG"..flag3]
- infoHeader.button.icon3.tooltipText = _G["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION"..flag3]
+ infoHeader.button.icon3.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG" .. flag3]
+ infoHeader.button.icon3.tooltipText = _G
+ ["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION" .. flag3]
if flag4 then
textRightAnchor = infoHeader.button.icon4
infoHeader.button.icon4:Show()
EncounterJournal_SetFlagIcon(infoHeader.button.icon4.icon, flag4)
- infoHeader.button.icon4.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG"..flag4]
- infoHeader.button.icon4.tooltipText = _G["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION"..flag4]
+ infoHeader.button.icon4.tooltipTitle = _G["ENCOUNTER_JOURNAL_SECTION_FLAG" .. flag4]
+ infoHeader.button.icon4.tooltipText = _G
+ ["ENCOUNTER_JOURNAL_SECTION_FLAG_DESCRIPTION" .. flag4]
end
end
end
@@ -1676,17 +1702,17 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
infoHeader.button.title:SetPoint("RIGHT", infoHeader.button, "RIGHT", -5, 0)
end
- infoHeader.index = nil;
- infoHeader:SetWidth(hWidth);
- EncounterJournal_SetHeaderDescription(infoHeader, description);
+ infoHeader.index = nil;
+ infoHeader:SetWidth(hWidth);
+ EncounterJournal_SetHeaderDescription(infoHeader, description);
- -- If this section has not be seen and should start open
- if EJ_section_openTable[infoHeader.myID] == nil and startsOpen then
+ -- If this section has not be seen and should start open
+ if EJ_section_openTable[infoHeader.myID] == nil and startsOpen then
EJ_section_openTable[infoHeader.myID] = true;
end
--toggleNested?
- if EJ_section_openTable[infoHeader.myID] then
+ if EJ_section_openTable[infoHeader.myID] then
infoHeader.expanded = false; -- setting false to expand it in EncounterJournal_ToggleHeaders
numAdded = numAdded + EncounterJournal_ToggleHeaders(infoHeader, true);
end
@@ -1700,12 +1726,12 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
if not doNotShift and numAdded > 0 then
--fix the usedlist
local startIndex = self.index or 0;
- for i=listEnd,startIndex+1,-1 do
- usedHeaders[i+numAdded] = usedHeaders[i];
- usedHeaders[i+numAdded].index = i + numAdded;
+ for i = listEnd, startIndex + 1, -1 do
+ usedHeaders[i + numAdded] = usedHeaders[i];
+ usedHeaders[i + numAdded].index = i + numAdded;
usedHeaders[i] = nil
end
- for i=1,numAdded do
+ for i = 1, numAdded do
usedHeaders[startIndex + i] = toggleTempList[i];
usedHeaders[startIndex + i].index = startIndex + i;
toggleTempList[i] = nil;
@@ -1713,7 +1739,8 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
end
if topLevelSection and usedHeaders[1] then
- usedHeaders[1]:SetPoint("TOPRIGHT", 0 , -8 - EncounterJournal.encounter.infoFrame.descriptionHeight - SECTION_BUTTON_OFFSET);
+ usedHeaders[1]:SetPoint("TOPRIGHT", 0,
+ -8 - EncounterJournal.encounter.infoFrame.descriptionHeight - SECTION_BUTTON_OFFSET);
end
if not doNotShift and #loopedSections ~= 0 then
@@ -1732,7 +1759,7 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
end
local spec, role;
---[[
+ --[[
spec = GetSpecialization();
if (spec) then
role = GetSpecializationRole(spec);
@@ -1759,13 +1786,13 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
local overview = self.overviews[i];
if (overview.sectionID == self.linkSection) then
overview.expanded = false;
- EncounterJournal_ToggleHeaders(overview);
+ EncounterJournal_ToggleHeaders(overview);
overview.cbCount = 0;
overview.button.glow.flashAnim:Play();
overview:SetScript("OnUpdate", EncounterJournal_FocusSectionCallback);
else
overview.expanded = true;
- EncounterJournal_ToggleHeaders(overview);
+ EncounterJournal_ToggleHeaders(overview);
overview.button.glow.flashAnim:Stop();
overview:SetScript("OnUpdate", nil);
end
@@ -1784,12 +1811,12 @@ function EncounterJournal_ToggleHeaders(self, doNotShift)
EJ_section_openTable[self.myID] = self.expanded;
end
- if not doNotShift then
- EncounterJournal_ShiftHeaders(self.index or 1);
- EncounterJournal_UpdateDetailsScrollRange();
+ if not doNotShift then
+ EncounterJournal_ShiftHeaders(self.index or 1);
+ EncounterJournal_UpdateDetailsScrollRange();
- --check to see if it is offscreen
- if self.index then
+ --check to see if it is offscreen
+ if self.index then
local scrollValue = EncounterJournal.encounter.info.detailsScroll.ScrollBar:GetValue();
local cutoff = EncounterJournal.encounter.info.detailsScroll:GetHeight() + scrollValue;
@@ -1818,20 +1845,21 @@ function EncounterJournal_ShiftHeaders(index)
end
local _, _, _, _, anchorY = usedHeaders[index]:GetPoint();
- for i=index,#usedHeaders-1 do
+ for i = index, #usedHeaders - 1 do
anchorY = anchorY - usedHeaders[i]:GetHeight();
if usedHeaders[i].description:IsShown() then
- anchorY = anchorY - EncounterJournal_UpdateSimpleHTMLHeight(usedHeaders[i].description) - SECTION_DESCRIPTION_OFFSET;
+ anchorY = anchorY - EncounterJournal_UpdateSimpleHTMLHeight(usedHeaders[i].description) -
+ SECTION_DESCRIPTION_OFFSET;
else
anchorY = anchorY - SECTION_BUTTON_OFFSET;
end
- usedHeaders[i+1]:SetPoint("TOPRIGHT", 0 , anchorY);
+ usedHeaders[i + 1]:SetPoint("TOPRIGHT", 0, anchorY);
end
end
function EncounterJournal_ResetHeaders()
- for key,_ in pairs(EJ_section_openTable) do
+ for key, _ in pairs(EJ_section_openTable) do
EJ_section_openTable[key] = nil;
end
@@ -1863,7 +1891,7 @@ function EncounterJournal_FocusSectionCallback(self)
if self.cbCount > 0 then
local _, _, _, _, anchorY = self:GetPoint();
anchorY = abs(anchorY);
- anchorY = anchorY - EncounterJournal.encounter.info.detailsScroll:GetHeight()/2
+ anchorY = anchorY - EncounterJournal.encounter.info.detailsScroll:GetHeight() / 2
EncounterJournal.encounter.info.detailsScroll.ScrollBar:SetValue(anchorY)
self:SetScript("OnUpdate", nil);
end
@@ -1873,8 +1901,9 @@ end
function EncounterJournal_MoveSectionUpdate(self)
if self.frameCount > 0 then
local _, _, _, _, anchorY = self:GetPoint();
- local height = min(EJ_MAX_SECTION_MOVE, self:GetHeight() + self.description:GetHeight() + SECTION_DESCRIPTION_OFFSET);
- local scrollValue = abs(anchorY) - (EncounterJournal.encounter.info.detailsScroll:GetHeight()-height);
+ local height = min(EJ_MAX_SECTION_MOVE,
+ self:GetHeight() + self.description:GetHeight() + SECTION_DESCRIPTION_OFFSET);
+ local scrollValue = abs(anchorY) - (EncounterJournal.encounter.info.detailsScroll:GetHeight() - height);
EncounterJournal.encounter.info.detailsScroll.ScrollBar:SetValue(scrollValue);
self:SetScript("OnUpdate", nil);
end
@@ -1885,14 +1914,14 @@ function EncounterJournal_ClearChildHeaders(self, doNotShift)
local usedHeaders = EncounterJournal.encounter.usedHeaders;
local freeHeaders = EncounterJournal.encounter.freeHeaders;
local numCleared = 0
- for key,header in pairs(usedHeaders) do
+ for key, header in pairs(usedHeaders) do
if header.parentID == self.myID then
if header.expanded then
numCleared = numCleared + EncounterJournal_ClearChildHeaders(header, true)
end
header:Hide();
usedHeaders[key] = nil;
- freeHeaders[#freeHeaders+1] = header;
+ freeHeaders[#freeHeaders + 1] = header;
numCleared = numCleared + 1;
end
end
@@ -1924,26 +1953,26 @@ function EncounterJournal_ClearDetails()
local freeHeaders = EncounterJournal.encounter.freeHeaders;
local usedHeaders = EncounterJournal.encounter.usedHeaders;
- for key,used in pairs(usedHeaders) do
+ for key, used in pairs(usedHeaders) do
used:Hide();
usedHeaders[key] = nil;
- freeHeaders[#freeHeaders+1] = used;
+ freeHeaders[#freeHeaders + 1] = used;
end
local clearDisplayInfo = true;
EncounterJournal_HideCreatures(clearDisplayInfo);
local bossIndex = 1
- local bossButton = _G["EncounterJournalBossButton"..bossIndex];
+ local bossButton = _G["EncounterJournalBossButton" .. bossIndex];
while bossButton do
bossButton:Hide();
bossIndex = bossIndex + 1;
- bossButton = _G["EncounterJournalBossButton"..bossIndex];
+ bossButton = _G["EncounterJournalBossButton" .. bossIndex];
end
--- EncounterJournal.searchResults:Hide();
--- EncounterJournal_HideSearchPreview();
--- EncounterJournal.searchBox:ClearFocus();
+ -- EncounterJournal.searchResults:Hide();
+ -- EncounterJournal_HideSearchPreview();
+ -- EncounterJournal.searchBox:ClearFocus();
end
function EncounterJournal_TabClicked(self, button)
@@ -2011,7 +2040,7 @@ end
function EncounterJournal_SetLootButton(item)
local itemID, encounterID, name, icon, slot, armorType, link = EJ_GetLootInfoByIndex(item.index);
- if ( name ) then
+ if (name) then
item.name:SetText(name);
item.icon:SetTexture(icon);
item.slot:SetText(slot);
@@ -2024,7 +2053,8 @@ function EncounterJournal_SetLootButton(item)
SetItemButtonQuality(item, quality, itemID)
if (quality > LE_ITEM_QUALITY_COMMON and BAG_ITEM_QUALITY_COLORS[quality]) then
- item.name:SetTextColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g, BAG_ITEM_QUALITY_COLORS[quality].b)
+ item.name:SetTextColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g,
+ BAG_ITEM_QUALITY_COLORS[quality].b)
end
else
item.name:SetText(RETRIEVING_ITEM_INFO);
@@ -2100,8 +2130,8 @@ function EncounterJournal_LootCalcScroll(offset)
buttonHeight = INSTANCE_LOOT_BUTTON_HEIGHT;
end
- local index = floor(offset/buttonHeight)
- return index, offset - (index*buttonHeight);
+ local index = floor(offset / buttonHeight)
+ return index, offset - (index * buttonHeight);
end
function EncounterJournal_Loot_OnUpdate(self)
@@ -2138,8 +2168,8 @@ end
function EncounterJournal_SetFlagIcon(texture, index)
local iconSize = 32;
- local columns = 256/iconSize;
- local rows = 64/iconSize;
+ local columns = 256 / iconSize;
+ local rows = 64 / iconSize;
-- Mythic flag should use heroic Icon
if (index == 12) then
@@ -2147,10 +2177,10 @@ function EncounterJournal_SetFlagIcon(texture, index)
end
local l = mod(index, columns) / columns;
- local r = l + (1/columns);
- local t = floor(index/columns) / rows;
- local b = t + (1/rows);
- texture:SetTexCoord(l,r,t,b);
+ local r = l + (1 / columns);
+ local t = floor(index / columns) / rows;
+ local b = t + (1 / rows);
+ texture:SetTexCoord(l, r, t, b);
end
function EncounterJournal_Refresh(self)
@@ -2173,7 +2203,7 @@ end
function EncounterJournal_UpdateScrollPos(self, visibleIndex)
local buttons = self.buttons
- local height = math.max(0, math.floor(self.buttonHeight * (visibleIndex - (#buttons)/2)))
+ local height = math.max(0, math.floor(self.buttonHeight * (visibleIndex - (#buttons) / 2)))
HybridScrollFrame_SetOffset(self, height)
self.scrollBar:SetValue(height)
end
@@ -2199,13 +2229,13 @@ function EncounterJournal_GetSearchDisplay(index)
else
typeText = ENCOUNTER_JOURNAL_ABILITY;
end
- path = EJ_GetInstanceInfo(instanceID).." > "..EJ_GetEncounterInfo(encounterID);
+ path = EJ_GetInstanceInfo(instanceID) .. " > " .. EJ_GetEncounterInfo(encounterID);
elseif stype == EJ_STYPE_ITEM then
itemID, _, name, icon = EJ_GetLootInfo(id)
typeText = ENCOUNTER_JOURNAL_ITEM;
- path = EJ_GetInstanceInfo(instanceID).." > "..EJ_GetEncounterInfo(encounterID);
+ path = EJ_GetInstanceInfo(instanceID) .. " > " .. EJ_GetEncounterInfo(encounterID);
elseif stype == EJ_STYPE_CREATURE then
- for i=1,MAX_CREATURES_PER_ENCOUNTER do
+ for i = 1, MAX_CREATURES_PER_ENCOUNTER do
local cId, cName, _, cDisplayInfo = EJ_GetCreatureInfo(i, encounterID);
if cId == id then
name = cName
@@ -2215,7 +2245,7 @@ function EncounterJournal_GetSearchDisplay(index)
end
icon = "Interface\\EncounterJournal\\UI-EJ-GenericSearchCreature"
typeText = CREATURE
- path = EJ_GetInstanceInfo(instanceID).." > "..EJ_GetEncounterInfo(encounterID);
+ path = EJ_GetInstanceInfo(instanceID) .. " > " .. EJ_GetEncounterInfo(encounterID);
end
return name, icon, path, typeText, displayInfo, itemID, stype, itemLink;
end
@@ -2253,11 +2283,12 @@ function EncounterJournal_SearchUpdate()
local numResults = EJ_GetNumSearchResults();
- for i = 1,#results do
+ for i = 1, #results do
result = results[i];
index = offset + i;
if index <= numResults then
- local name, icon, path, typeText, displayInfo, itemID, stype, itemLink = EncounterJournal_GetSearchDisplay(index);
+ local name, icon, path, typeText, displayInfo, itemID, stype, itemLink = EncounterJournal_GetSearchDisplay(
+ index);
if stype == EJ_STYPE_INSTANCE then
result.icon:SetTexCoord(0.16796875, 0.51171875, 0.03125, 0.71875);
else
@@ -2270,7 +2301,7 @@ function EncounterJournal_SearchUpdate()
result.icon:SetTexture(icon);
result.link = itemLink;
if displayInfo and displayInfo > 0 then
- -- SetPortraitTexture(result.icon, displayInfo);
+ -- SetPortraitTexture(result.icon, displayInfo);
result.icon:SetPortrait(displayInfo)
end
result:SetID(index);
@@ -2301,7 +2332,8 @@ function EncounterJournal_ShowFullSearch()
return;
end
- EncounterJournal.searchResults.TitleText:SetFormattedText(ENCOUNTER_JOURNAL_SEARCH_RESULTS, EncounterJournal.searchBox:GetText(), numResults);
+ EncounterJournal.searchResults.TitleText:SetFormattedText(ENCOUNTER_JOURNAL_SEARCH_RESULTS,
+ EncounterJournal.searchBox:GetText(), numResults);
EncounterJournal.searchResults:Show();
EncounterJournal_SearchUpdate();
EncounterJournal.searchResults.scrollFrame.scrollBar:SetValue(0);
@@ -2417,7 +2449,8 @@ function EncounterJournal_UpdateSearchPreview()
for index = 1, EJ_NUM_SEARCH_PREVIEWS do
local button = EncounterJournal.searchBox.searchPreview[index];
if index <= numResults then
- local name, icon, path, typeText, displayInfo, itemID, stype, itemLink = EncounterJournal_GetSearchDisplay(index);
+ local name, icon, path, typeText, displayInfo, itemID, stype, itemLink = EncounterJournal_GetSearchDisplay(
+ index);
if stype == EJ_STYPE_INSTANCE then
button.icon:SetTexCoord(0.16796875, 0.51171875, 0.03125, 0.71875)
else
@@ -2428,7 +2461,7 @@ function EncounterJournal_UpdateSearchPreview()
button.icon:SetTexture(icon);
button.link = itemLink;
if displayInfo and displayInfo > 0 then
- -- SetPortraitTexture(button.icon, displayInfo);
+ -- SetPortraitTexture(button.icon, displayInfo);
button.icon:SetPortrait(displayInfo)
end
button:SetID(index);
@@ -2464,7 +2497,7 @@ function EncounterJournal_UpdateSearchPreview()
end
function EncounterJournal_FixSearchPreviewBottomBorder()
--- EncounterJournal.searchBox.showAllResults:SetShown(EJ_GetNumSearchResults() >= EJ_SHOW_ALL_SEARCH_RESULTS_INDEX)
+ -- EncounterJournal.searchBox.showAllResults:SetShown(EJ_GetNumSearchResults() >= EJ_SHOW_ALL_SEARCH_RESULTS_INDEX)
local lastShownButton = nil;
if EncounterJournal.searchBox.showAllResults:IsShown() then
@@ -2481,8 +2514,10 @@ function EncounterJournal_FixSearchPreviewBottomBorder()
end
if lastShownButton ~= nil then
- EncounterJournal.searchBox.searchPreviewContainer.botRightCorner:SetPoint("BOTTOM", lastShownButton, "BOTTOM", 0, -8);
- EncounterJournal.searchBox.searchPreviewContainer.botLeftCorner:SetPoint("BOTTOM", lastShownButton, "BOTTOM", 0, -8);
+ EncounterJournal.searchBox.searchPreviewContainer.botRightCorner:SetPoint("BOTTOM", lastShownButton, "BOTTOM", 0,
+ -8);
+ EncounterJournal.searchBox.searchPreviewContainer.botLeftCorner:SetPoint("BOTTOM", lastShownButton, "BOTTOM", 0,
+ -8);
else
EncounterJournal_HideSearchPreview();
end
@@ -2650,7 +2685,7 @@ function EncounterJournal_OpenJournal(difficultyID, instanceID, encounterID, sec
if (EncounterJournal_CheckForOverview(sectionID)) then
EncounterJournal.encounter.overviewFrame.linkSection = sectionID;
else
- local sectionPath = {EJ_GetSectionPath(sectionID)};
+ local sectionPath = { EJ_GetSectionPath(sectionID) };
for _, id in pairs(sectionPath) do
EJ_section_openTable[id] = true;
end
@@ -2668,7 +2703,7 @@ function EncounterJournal_OpenJournal(difficultyID, instanceID, encounterID, sec
local itemIndex = EJ_GetLootInfoIndexByItemID(itemID)
if not itemIndex then
if not EJ_IsItemAllowedByClassFilter(itemID)
- or not EJ_IsItemAllowedBySlotFilter(itemID)
+ or not EJ_IsItemAllowedBySlotFilter(itemID)
then
EncounterJournal_UpdateScrollPos(EncounterJournal.encounter.info.lootScroll, 1)
EJ_SetLootFilter(0)
@@ -2691,10 +2726,9 @@ function EncounterJournal_OpenJournal(difficultyID, instanceID, encounterID, sec
end
end
end
-
end
elseif tierIndex then
- EncounterJournal_TierDropDown_Select(EncounterJournal, tierIndex+1);
+ EncounterJournal_TierDropDown_Select(EncounterJournal, tierIndex + 1);
else
EncounterJournal_ListInstances();
end
@@ -2723,16 +2757,16 @@ function EncounterJournal_DifficultyInit(self, level)
end
function EJ_HideInstances(index)
- if ( not index ) then
+ if (not index) then
index = 1;
end
local scrollChild = EncounterJournal.instanceSelect.scroll.child;
- local instanceButton = scrollChild["instance"..index];
+ local instanceButton = scrollChild["instance" .. index];
while instanceButton do
instanceButton:Hide();
index = index + 1;
- instanceButton = scrollChild["instance"..index];
+ instanceButton = scrollChild["instance" .. index];
end
end
@@ -2742,7 +2776,7 @@ function EJSuggestTab_GetPlayerTierIndex()
local minDiff = MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_LEVEL_CURRENT];
for tierId, tierLevel in pairs(MAX_PLAYER_LEVEL_TABLE) do
local diff = tierLevel - playerLevel;
- if ( diff > 0 and diff < minDiff ) then
+ if (diff > 0 and diff < minDiff) then
expansionId = tierId;
minDiff = diff;
end
@@ -2754,13 +2788,39 @@ function EJ_ContentTab_OnClick(self)
EJ_ContentTab_Select(self.id);
end
+local function EJ_ContentTab_RaiseTabsAbovePlayerGuide()
+ local instanceSelect = EncounterJournal and EncounterJournal.instanceSelect;
+ if not instanceSelect then
+ return;
+ end
+
+ local baseLevel = instanceSelect:GetFrameLevel();
+ if PlayerGuideFrame then
+ PlayerGuideFrame:SetFrameLevel(baseLevel + 1);
+ end
+
+ local tabLevel = baseLevel + 12;
+ if instanceSelect.Tabs then
+ for _, tab in ipairs(instanceSelect.Tabs) do
+ tab:SetFrameLevel(tabLevel);
+ if tab.grayBox then
+ tab.grayBox:SetFrameLevel(tabLevel + 1);
+ end
+ end
+ end
+
+ if instanceSelect.tierDropDown then
+ instanceSelect.tierDropDown:SetFrameLevel(tabLevel);
+ end
+end
+
function EJ_ContentTab_Select(id)
local instanceSelect = EncounterJournal.instanceSelect;
local selectedTab = nil;
for i = 1, #instanceSelect.Tabs do
local tab = instanceSelect.Tabs[i];
- if ( tab.id ~= id ) then
+ if (tab.id ~= id) then
tab:Enable();
tab:GetFontString():SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
tab.selectedGlow:Hide();
@@ -2775,7 +2835,7 @@ function EJ_ContentTab_Select(id)
-- Setup background
local tierData;
- if ( id == instanceSelect.suggestTab.id ) then
+ if (id == instanceSelect.suggestTab.id) then
tierData = GetEJTierData(EJSuggestTab_GetPlayerTierIndex());
elseif id == instanceSelect.LootJournalTab.id then
tierData = GetEJTierData(1)
@@ -2787,44 +2847,60 @@ function EJ_ContentTab_Select(id)
EncounterJournal.encounter:Hide();
EncounterJournal.instanceSelect:Show();
- if ( id == instanceSelect.suggestTab.id ) then
+ if (id == instanceSelect.suggestTab.id) then
EJ_HideInstances();
EJ_HideLootJournalPanel();
+ EJ_HidePlayerGuidePanel();
instanceSelect.scroll:Hide();
EncounterJournal.suggestFrame:Show();
- if ( not instanceSelect.dungeonsTab.grayBox:IsShown() or not instanceSelect.raidsTab.grayBox:IsShown() ) then
+ if (not instanceSelect.dungeonsTab.grayBox:IsShown() or not instanceSelect.raidsTab.grayBox:IsShown()) then
EncounterJournal_DisableTierDropDown(true);
else
EncounterJournal_EnableTierDropDown();
end
- elseif ( id == instanceSelect.LootJournalTab.id ) then
+ elseif (id == instanceSelect.guideTab.id) then
EJ_HideInstances();
EJ_HideSuggestPanel();
+ EJ_HideLootJournalPanel();
+ instanceSelect.scroll:Hide();
+ EncounterJournal_DisableTierDropDown(true);
+ instanceSelect.tierDropDown:Hide();
+ if PlayerGuideFrame then
+ EJ_ContentTab_RaiseTabsAbovePlayerGuide();
+ PlayerGuideFrame:Show();
+ EJ_ContentTab_RaiseTabsAbovePlayerGuide();
+ end
+ elseif (id == instanceSelect.LootJournalTab.id) then
+ EJ_HideInstances();
+ EJ_HideSuggestPanel();
+ EJ_HidePlayerGuidePanel();
instanceSelect.scroll:Hide();
EncounterJournal_DisableTierDropDown(true);
EJ_ShowLootJournalPanel();
- elseif ( id == instanceSelect.dungeonsTab.id or id == instanceSelect.raidsTab.id ) then
+ elseif (id == instanceSelect.dungeonsTab.id or id == instanceSelect.raidsTab.id) then
EJ_HideNonInstancePanels();
instanceSelect.scroll:Show();
EncounterJournal_ListInstances();
EncounterJournal_EnableTierDropDown();
end
PlaySound("igMainMenuOptionCheckBoxOn");
- EncounterJournal.TutorialButton:SetShown(id == instanceSelect.suggestTab.id or id == instanceSelect.dungeonsTab.id or id == instanceSelect.raidsTab.id)
+ EncounterJournal.TutorialButton:SetShown(id == instanceSelect.suggestTab.id or id == instanceSelect.dungeonsTab.id or
+ id == instanceSelect.raidsTab.id)
EventRegistry:TriggerEvent("EncounterJournal.SetTab", id)
end
function EJ_ContentTab_SelectAppropriateInstanceTab(instanceID)
local isRaid = EJ_InstanceIsRaidByID(instanceID);
- local desiredTabID = isRaid and EncounterJournal.instanceSelect.raidsTab:GetID() or EncounterJournal.instanceSelect.dungeonsTab:GetID();
+ local desiredTabID = isRaid and EncounterJournal.instanceSelect.raidsTab:GetID() or
+ EncounterJournal.instanceSelect.dungeonsTab:GetID();
EJ_ContentTab_Select(desiredTabID);
end
function EJ_HideSuggestPanel()
local instanceSelect = EncounterJournal.instanceSelect;
local suggestTab = instanceSelect.suggestTab;
- if ( not suggestTab:IsEnabled() == 1 or EncounterJournal.suggestFrame:IsShown() ) then
+ if (not suggestTab:IsEnabled() == 1 or EncounterJournal.suggestFrame:IsShown()) then
suggestTab:Enable();
suggestTab:GetFontString():SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
suggestTab.selectedGlow:Hide();
@@ -2843,10 +2919,10 @@ function EJ_HideSuggestPanel()
end
function EJ_HideLootJournalPanel()
- if ( EncounterJournal.LootJournal ) then
+ if (EncounterJournal.LootJournal) then
EncounterJournal.LootJournal:Hide();
end
- if ( EncounterJournal.LootJournalItems ) then
+ if (EncounterJournal.LootJournalItems) then
EncounterJournal.LootJournalItems:Hide();
end
end
@@ -2856,9 +2932,19 @@ function EJ_ShowLootJournalPanel()
activeLootPanel:Show();
end
+function EJ_HidePlayerGuidePanel()
+ if PlayerGuideFrame then
+ PlayerGuideFrame:Hide()
+ end
+ if EncounterJournal and EncounterJournal.instanceSelect and EncounterJournal.instanceSelect.tierDropDown then
+ EncounterJournal.instanceSelect.tierDropDown:Show()
+ end
+end
+
function EJ_HideNonInstancePanels()
EJ_HideSuggestPanel();
EJ_HideLootJournalPanel();
+ EJ_HidePlayerGuidePanel();
end
function EJTierDropDown_Initialize(self, level)
@@ -2866,7 +2952,7 @@ function EJTierDropDown_Initialize(self, level)
local numTiers = EJ_GetNumTiers();
local currTier = EJ_GetCurrentTier();
- for i=1,numTiers do
+ for i = 1, numTiers do
info.text = EJ_GetTierInfo(i);
info.func = EncounterJournal_TierDropDown_Select
info.checked = i == currTier;
@@ -2909,7 +2995,7 @@ function EncounterJournal_RefreshSlotFilterText(self)
if slotFilter ~= NO_INV_TYPE_FILTER then
for slotIndex = 1, C_EncounterJournal.GetNumSlotFilters() do
local invType, invTypeName, equipSlot = C_EncounterJournal.GetSlotFilterInfo(slotIndex)
- if ( invType == slotFilter ) then
+ if (invType == slotFilter) then
text = invTypeName;
break;
end
@@ -2948,7 +3034,7 @@ function EncounterJournal_InitLootFilter(self, level)
local classDisplayName, classTag, classID;
local info = UIDropDownMenu_CreateInfo();
info.keepShownOnClick = nil;
---[[
+ --[[
info.text = EJ_FILTER_ALL_CLASS;
info.checked = (filterClassID == NO_CLASS_FILTER);
info.arg1 = NO_CLASS_FILTER;
@@ -2988,7 +3074,6 @@ function EncounterJournal_InitLootSlotFilter(self, level)
end
end
-
----------------------------------------
--------------Nav Bar Func--------------
----------------------------------------
@@ -3035,22 +3120,22 @@ function EJSuggestFrame_OnLoad(self)
end
function EJSuggestFrame_OnEvent(self, event, ...)
- if ( event == "AJ_REFRESH_DISPLAY" ) then
+ if (event == "AJ_REFRESH_DISPLAY") then
if self:GetParent().selectedTab == EncounterJournal.instanceSelect.suggestTab.id then
EJSuggestFrame_RefreshDisplay();
local newAdventureNotice = ...;
- if ( newAdventureNotice ) then
--- EncounterJournalMicroButton:UpdateNewAdventureNotice();
+ if (newAdventureNotice) then
+ -- EncounterJournalMicroButton:UpdateNewAdventureNotice();
end
end
- elseif ( event == "AJ_REWARD_DATA_RECEIVED" ) then
+ elseif (event == "AJ_REWARD_DATA_RECEIVED") then
EJSuggestFrame_RefreshRewards()
end
end
function EJSuggestFrame_OnShow(self)
SetParentFrameLevel(self)
--- EncounterJournalMicroButton:ClearNewAdventureNotice();
+ -- EncounterJournalMicroButton:ClearNewAdventureNotice();
C_AdventureJournal.UpdateSuggestions();
EJSuggestFrame_RefreshDisplay();
@@ -3058,21 +3143,21 @@ function EJSuggestFrame_OnShow(self)
end
function EJSuggestFrame_NextSuggestion()
- if ( C_AdventureJournal.GetPrimaryOffset() < C_AdventureJournal.GetNumAvailableSuggestions()-1 ) then
- C_AdventureJournal.SetPrimaryOffset(C_AdventureJournal.GetPrimaryOffset()+1);
+ if (C_AdventureJournal.GetPrimaryOffset() < C_AdventureJournal.GetNumAvailableSuggestions() - 1) then
+ C_AdventureJournal.SetPrimaryOffset(C_AdventureJournal.GetPrimaryOffset() + 1);
PlaySound(SOUNDKIT.IG_ABILITY_PAGE_TURN);
end
end
function EJSuggestFrame_PrevSuggestion()
- if( C_AdventureJournal.GetPrimaryOffset() > 0 ) then
- C_AdventureJournal.SetPrimaryOffset(C_AdventureJournal.GetPrimaryOffset()-1);
+ if (C_AdventureJournal.GetPrimaryOffset() > 0) then
+ C_AdventureJournal.SetPrimaryOffset(C_AdventureJournal.GetPrimaryOffset() - 1);
PlaySound(SOUNDKIT.IG_ABILITY_PAGE_TURN);
end
end
-function EJSuggestFrame_OnMouseWheel( self, value )
- if ( value > 0 ) then
+function EJSuggestFrame_OnMouseWheel(self, value)
+ if (value > 0) then
EJSuggestFrame_PrevSuggestion();
else
EJSuggestFrame_NextSuggestion()
@@ -3084,10 +3169,15 @@ function EJSuggestFrame_OpenFrame()
NavBar_Reset(EncounterJournal.navBar);
end
+function EJPlayerGuide_OpenFrame()
+ EJ_ContentTab_Select(EncounterJournal.instanceSelect.guideTab.id);
+ NavBar_Reset(EncounterJournal.navBar);
+end
+
function EJSuggestFrame_UpdateRewards(suggestion)
- local rewardData = C_AdventureJournal.GetReward( suggestion.index );
+ local rewardData = C_AdventureJournal.GetReward(suggestion.index);
suggestion.reward.data = rewardData;
- if ( rewardData ) then
+ if (rewardData) then
if rewardData.isRewardList then
local numRewards = 0
@@ -3096,8 +3186,8 @@ function EJSuggestFrame_UpdateRewards(suggestion)
if itemRewardData then
local texture = itemRewardData.itemIcon or "Interface\\Icons\\achievement_guildperk_mobilebanking";
local rewardFrame = suggestion.rewardFrames[index]
- -- rewardFrame.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
- -- rewardFrame.icon:SetTexture(texture);
+ -- rewardFrame.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- rewardFrame.icon:SetTexture(texture);
SetPortraitToTexture(rewardFrame.icon, texture)
rewardFrame.data = rewardData
rewardFrame:Show()
@@ -3116,7 +3206,8 @@ function EJSuggestFrame_UpdateRewards(suggestion)
elseif numRewards > 2 then
offsetX = 4 + 11 * (numRewards - 2)
end
- suggestion.reward:SetPoint("BOTTOM", -((numRewards - 1) * suggestion.rewardFrames[2]:GetWidth() + offsetX) / 2, 53)
+ suggestion.reward:SetPoint("BOTTOM",
+ -((numRewards - 1) * suggestion.rewardFrames[2]:GetWidth() + offsetX) / 2, 53)
else
suggestion.reward:SetPoint("BOTTOM", 0, 53)
end
@@ -3126,12 +3217,12 @@ function EJSuggestFrame_UpdateRewards(suggestion)
end
local texture = rewardData.itemIcon or rewardData.currencyIcon or
- "Interface\\Icons\\achievement_guildperk_mobilebanking";
- if ( rewardData.isRewardTable ) then
+ "Interface\\Icons\\achievement_guildperk_mobilebanking";
+ if (rewardData.isRewardTable) then
texture = "Interface\\Icons\\achievement_guildperk_mobilebanking";
end
- -- suggestion.reward.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
- -- suggestion.reward.icon:SetTexture(texture);
+ -- suggestion.reward.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- suggestion.reward.icon:SetTexture(texture);
SetPortraitToTexture(suggestion.reward.icon, texture)
suggestion.reward:Show();
@@ -3147,19 +3238,19 @@ function EJSuggestFrame_UpdateRewards(suggestion)
end
AdventureJournal_LeftTitleFonts = {
- "DestinyFontHuge", -- 32pt font
- "QuestFont_Enormous", -- 30pt font
- "QuestFont_Super_Huge", -- 24pt font
- "QuestFont22", -- 24pt font
+ "DestinyFontHuge", -- 32pt font
+ "QuestFont_Enormous", -- 30pt font
+ "QuestFont_Super_Huge", -- 24pt font
+ "QuestFont22", -- 24pt font
};
local AdventureJournal_RightTitleFonts = {
- "QuestFont_Huge", -- 18pt font
- "Fancy16Font", -- 16pt font
+ "QuestFont_Huge", -- 18pt font
+ "Fancy16Font", -- 16pt font
};
local AdventureJournal_RightDescriptionFonts = {
- "SystemFont_Med1", -- 12pt font
+ "SystemFont_Med1", -- 12pt font
-- "SystemFont_Small", -- 10pt font
};
@@ -3176,15 +3267,15 @@ function EJSuggestFrame_RefreshDisplay()
-- hide all the display info
for i = 1, AJ_MAX_NUM_SUGGESTIONS do
- local suggestion = self["Suggestion"..i];
+ local suggestion = self["Suggestion" .. i];
suggestion.centerDisplay:Hide();
- if ( i == 1 ) then
+ if (i == 1) then
-- the left suggestion's button isn't on the centerDisplay frame
suggestion.button:Hide();
else
suggestion.centerDisplay.button:Hide();
end
- -- suggestion.reward:Hide();
+ -- suggestion.reward:Hide();
suggestion.icon:Hide();
suggestion.iconRing:Hide();
@@ -3194,7 +3285,7 @@ function EJSuggestFrame_RefreshDisplay()
end
-- setup the primary suggestion display
- if ( #self.suggestions > 0 ) then
+ if (#self.suggestions > 0) then
local suggestion = self.Suggestion1;
local data = self.suggestions[1];
@@ -3204,13 +3295,13 @@ function EJSuggestFrame_RefreshDisplay()
centerDisplay:SetHeight(suggestion:GetHeight());
centerDisplay:Show();
- -- centerDisplay.title:SetHeight(0);
- -- centerDisplay.description:SetHeight(0);
+ -- centerDisplay.title:SetHeight(0);
+ -- centerDisplay.description:SetHeight(0);
titleText:SetText(data.title);
descText:SetText(data.description);
-- find largest font that will not go past 2 lines
---[[
+ --[[
for i = 1, #AdventureJournal_LeftTitleFonts do
titleText:SetFontObject(AdventureJournal_LeftTitleFonts[i]);
local numLines = titleText:GetNumLines();
@@ -3234,33 +3325,35 @@ function EJSuggestFrame_RefreshDisplay()
centerDisplay.title:SetHeight(centerDisplay.title.text:GetHeight())
centerDisplay.description:SetHeight(centerDisplay.description.text:GetHeight())
- centerDisplay:SetHeight(math.min(180, centerDisplay.title:GetHeight() + 10 + centerDisplay.description:GetHeight()))
+ centerDisplay:SetHeight(math.min(180,
+ centerDisplay.title:GetHeight() + 10 + centerDisplay.description:GetHeight()))
- if ( data.buttonText and #data.buttonText > 0 ) then
- suggestion.button:SetText( data.buttonText );
+ if (data.buttonText and #data.buttonText > 0) then
+ suggestion.button:SetText(data.buttonText);
- local btnWidth = max( suggestion.button:GetTextWidth()+42, 150 );
- btnWidth = min( btnWidth, centerDisplay:GetWidth() );
- suggestion.button:SetWidth( btnWidth );
+ local btnWidth = max(suggestion.button:GetTextWidth() + 42, 150);
+ btnWidth = min(btnWidth, centerDisplay:GetWidth());
+ suggestion.button:SetWidth(btnWidth);
suggestion.button:Show();
end
suggestion.icon:Show();
suggestion.iconRing:Show();
- if ( data.iconPath ) then
- -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
- -- suggestion.icon:SetTexture(data.iconPath);
+ if (data.iconPath) then
+ -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- suggestion.icon:SetTexture(data.iconPath);
SetPortraitToTexture(suggestion.icon, data.iconPath)
else
- -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
- -- suggestion.icon:SetTexture(QUESTION_MARK_ICON);
+ -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- suggestion.icon:SetTexture(QUESTION_MARK_ICON);
SetPortraitToTexture(suggestion.icon, QUESTION_MARK_ICON)
end
suggestion.prevButton:SetEnabled(C_AdventureJournal.GetPrimaryOffset() > 0);
- suggestion.nextButton:SetEnabled(C_AdventureJournal.GetPrimaryOffset() < C_AdventureJournal.GetNumAvailableSuggestions()-1);
+ suggestion.nextButton:SetEnabled(C_AdventureJournal.GetPrimaryOffset() <
+ C_AdventureJournal.GetNumAvailableSuggestions() - 1);
- if ( titleText:IsTruncated() ) then
+ if (titleText:IsTruncated()) then
centerDisplay.title:SetScript("OnEnter", EJSuggestFrame_SuggestionTextOnEnter);
centerDisplay.title:SetScript("OnLeave", GameTooltip_Hide);
else
@@ -3276,13 +3369,13 @@ function EJSuggestFrame_RefreshDisplay()
end
-- setup secondary suggestions display
- if ( #self.suggestions > 1 ) then
+ if (#self.suggestions > 1) then
local minTitleIndex = 1;
local minDescIndex = 1;
for i = 2, #self.suggestions do
- local suggestion = self["Suggestion"..i];
- if ( not suggestion ) then
+ local suggestion = self["Suggestion" .. i];
+ if (not suggestion) then
break;
end
@@ -3295,7 +3388,7 @@ function EJSuggestFrame_RefreshDisplay()
-- find largest font that will not truncate the title
suggestion.centerDisplay.title.text:SetFontObject(AdventureJournal_RightTitleFonts[2]);
minTitleIndex = 2
---[[
+ --[[
for fontIndex = minTitleIndex, #AdventureJournal_RightTitleFonts do
suggestion.centerDisplay.title.text:SetFontObject(AdventureJournal_RightTitleFonts[fontIndex]);
minTitleIndex = fontIndex
@@ -3308,7 +3401,7 @@ function EJSuggestFrame_RefreshDisplay()
-- find largest font that will not go past 4 lines
suggestion.centerDisplay.description.text:SetFontObject(AdventureJournal_RightDescriptionFonts[1]);
minDescIndex = 1;
---[[
+ --[[
for fontIndex = minDescIndex, #AdventureJournal_RightDescriptionFonts do
suggestion.centerDisplay.description.text:SetFontObject(AdventureJournal_RightDescriptionFonts[fontIndex]);
minDescIndex = fontIndex;
@@ -3319,24 +3412,24 @@ function EJSuggestFrame_RefreshDisplay()
end
--]]
- if ( data.buttonText and #data.buttonText > 0 ) then
- suggestion.centerDisplay.button:SetText( data.buttonText );
+ if (data.buttonText and #data.buttonText > 0) then
+ suggestion.centerDisplay.button:SetText(data.buttonText);
- local btnWidth = max(suggestion.centerDisplay.button:GetTextWidth()+42, 116);
- btnWidth = min( btnWidth, suggestion.centerDisplay:GetWidth() );
- suggestion.centerDisplay.button:SetWidth( btnWidth );
+ local btnWidth = max(suggestion.centerDisplay.button:GetTextWidth() + 42, 116);
+ btnWidth = min(btnWidth, suggestion.centerDisplay:GetWidth());
+ suggestion.centerDisplay.button:SetWidth(btnWidth);
suggestion.centerDisplay.button:Show();
end
suggestion.icon:Show();
suggestion.iconRing:Show();
- if ( data.iconPath ) then
- -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
- -- suggestion.icon:SetTexture(data.iconPath);
+ if (data.iconPath) then
+ -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- suggestion.icon:SetTexture(data.iconPath);
SetPortraitToTexture(suggestion.icon, data.iconPath)
else
- -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
- -- suggestion.icon:SetTexture(QUESTION_MARK_ICON);
+ -- suggestion.icon:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask");
+ -- suggestion.icon:SetTexture(QUESTION_MARK_ICON);
SetPortraitToTexture(suggestion.icon, QUESTION_MARK_ICON)
end
@@ -3345,7 +3438,7 @@ function EJSuggestFrame_RefreshDisplay()
-- set the fonts to be the same for both right side sections
-- adjust the center display to keep the text centered
for i = 2, #self.suggestions do
- local suggestion = self["Suggestion"..i];
+ local suggestion = self["Suggestion" .. i];
suggestion.centerDisplay:SetHeight(suggestion:GetHeight());
local title = suggestion.centerDisplay.title;
@@ -3354,7 +3447,7 @@ function EJSuggestFrame_RefreshDisplay()
description.text:SetFontObject(AdventureJournal_RightDescriptionFonts[minDescIndex]);
local fontHeight = select(2, title.text:GetFont());
title:SetHeight(fontHeight);
---[[
+ --[[
local numLines = min(4, description.text:GetNumLines());
fontHeight = select(2, description.text:GetFont());
description:SetHeight(numLines * fontHeight);
@@ -3366,18 +3459,18 @@ function EJSuggestFrame_RefreshDisplay()
-- adjust the center display to keep the text centered
local top = title:GetTop();
local bottom = description:GetBottom();
- if ( suggestion.centerDisplay.button:IsShown() ) then
+ if (suggestion.centerDisplay.button:IsShown()) then
bottom = suggestion.centerDisplay.button:GetBottom();
end
- if ( title.text:IsTruncated() ) then
+ if (title.text:IsTruncated()) then
title:SetScript("OnEnter", EJSuggestFrame_SuggestionTextOnEnter);
title:SetScript("OnLeave", GameTooltip_Hide);
else
title:SetScript("OnEnter", nil);
title:SetScript("OnLeave", nil);
end
---[[
+ --[[
if ( description.text:IsTruncated() ) then
description:SetScript("OnEnter", EJSuggestFrame_SuggestionTextOnEnter);
description:SetScript("OnLeave", GameTooltip_Hide);
@@ -3393,7 +3486,7 @@ function EJSuggestFrame_RefreshDisplay()
-- fix SimpleHTML hyperlinks positions
for i = 1, AJ_MAX_NUM_SUGGESTIONS do
- local suggestion = self["Suggestion"..i];
+ local suggestion = self["Suggestion" .. i];
suggestion:Hide()
suggestion:Show()
end
@@ -3407,7 +3500,7 @@ end
function EJSuggestFrame_RefreshRewards()
for i = 1, AJ_MAX_NUM_SUGGESTIONS do
- local suggestion = EncounterJournal.suggestFrame["Suggestion"..i];
+ local suggestion = EncounterJournal.suggestFrame["Suggestion" .. i];
suggestion.reward:Hide();
EJSuggestFrame_UpdateRewards(suggestion);
end
@@ -3420,7 +3513,7 @@ end
function AdventureJournal_Reward_OnEnter(self)
local rewardData = self.data;
- if ( rewardData ) then
+ if (rewardData) then
if rewardData.isRewardList then
local reward = rewardData[self:GetID()]
if reward and reward.itemLink then
@@ -3441,31 +3534,35 @@ function AdventureJournal_Reward_OnEnter(self)
local suggestion = EncounterJournal.suggestFrame.suggestions[self:GetParent().index];
local rewardHeaderText = "";
- if ( rewardData.rewardDesc ) then
+ if (rewardData.rewardDesc) then
rewardHeaderText = rewardData.rewardDesc;
- elseif ( rewardData.isRewardTable ) then
- if ( not suggestion.hideDifficulty and suggestion.difficultyID and suggestion.difficultyID > 1 ) then
- local difficultyStr = EJ_DIFFICULTIES[suggestion.difficultyID] and EJ_DIFFICULTIES[suggestion.difficultyID].prefix or ""
- if( rewardData.itemLevel ) then
- rewardHeaderText = format(AJ_LFG_REWARD_DIFFICULTY_TEXT, suggestion.title, difficultyStr, rewardData.itemLevel);
- elseif ( rewardData.minItemLevel ) then
- rewardHeaderText = format(AJ_LFG_REWARD_DIFFICULTY_IRANGE_TEXT, suggestion.title, difficultyStr, rewardData.minItemLevel, rewardData.maxItemLevel);
+ elseif (rewardData.isRewardTable) then
+ if (not suggestion.hideDifficulty and suggestion.difficultyID and suggestion.difficultyID > 1) then
+ local difficultyStr = EJ_DIFFICULTIES[suggestion.difficultyID] and
+ EJ_DIFFICULTIES[suggestion.difficultyID].prefix or ""
+ if (rewardData.itemLevel) then
+ rewardHeaderText = format(AJ_LFG_REWARD_DIFFICULTY_TEXT, suggestion.title, difficultyStr,
+ rewardData.itemLevel);
+ elseif (rewardData.minItemLevel) then
+ rewardHeaderText = format(AJ_LFG_REWARD_DIFFICULTY_IRANGE_TEXT, suggestion.title, difficultyStr,
+ rewardData.minItemLevel, rewardData.maxItemLevel);
end
else
- if( rewardData.itemLevel ) then
+ if (rewardData.itemLevel) then
rewardHeaderText = format(AJ_LFG_REWARD_DEFAULT_TEXT, suggestion.title, rewardData.itemLevel);
- elseif ( rewardData.minItemLevel ) then
- rewardHeaderText = format(AJ_LFG_REWARD_DEFAULT_IRANGE_TEXT, suggestion.title, rewardData.minItemLevel, rewardData.maxItemLevel);
+ elseif (rewardData.minItemLevel) then
+ rewardHeaderText = format(AJ_LFG_REWARD_DEFAULT_IRANGE_TEXT, suggestion.title,
+ rewardData.minItemLevel, rewardData.maxItemLevel);
end
end
- if( rewardData.itemLink ) then
- rewardHeaderText = rewardHeaderText..AJ_SAMPLE_REWARD_TEXT;
+ if (rewardData.itemLink) then
+ rewardHeaderText = rewardHeaderText .. AJ_SAMPLE_REWARD_TEXT;
end
end
- if ( rewardData.itemLink and rewardData.currencyType ) then
- local itemName, _, quality = C_Item.GetItemInfo(rewardData.itemLink);
+ if (rewardData.itemLink and rewardData.currencyType) then
+ local itemName, _, quality = C_Item.GetItemInfo(rewardData.itemLink);
frame.Item1.text:SetText(itemName);
frame.Item1.text:Show();
frame.Item1.icon:SetTexture(rewardData.itemIcon);
@@ -3473,7 +3570,7 @@ function AdventureJournal_Reward_OnEnter(self)
frame.Item1:SetSize(256, 28);
frame.Item1:Show();
- if ( rewardData.itemQuantity and rewardData.itemQuantity > 1 ) then
+ if (rewardData.itemQuantity and rewardData.itemQuantity > 1) then
frame.Item1.Count:SetText(rewardData.itemQuantity);
frame.Item1.Count:Show();
else
@@ -3483,20 +3580,23 @@ function AdventureJournal_Reward_OnEnter(self)
SetItemButtonQuality(frame.Item1, quality, rewardData.itemLink);
if (quality > Enum.ItemQuality.Common and BAG_ITEM_QUALITY_COLORS[quality]) then
- frame.Item1.text:SetTextColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g, BAG_ITEM_QUALITY_COLORS[quality].b);
+ frame.Item1.text:SetTextColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g,
+ BAG_ITEM_QUALITY_COLORS[quality].b);
end
- local currencyName, _, quality, _, _, _, _, _, _, currencyIcon = C_Item.GetItemInfo(rewardData.currencyType, nil, nil, true)
+ local currencyName, _, quality, _, _, _, _, _, _, currencyIcon = C_Item.GetItemInfo(rewardData.currencyType,
+ nil, nil, true)
frame.Item2.icon:SetTexture(currencyIcon);
frame.Item2.text:SetText(currencyName);
frame.Item2:Show();
SetItemButtonQuality(frame.Item2, quality);
if (quality > Enum.ItemQuality.Common and BAG_ITEM_QUALITY_COLORS[quality]) then
- frame.Item2.text:SetTextColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g, BAG_ITEM_QUALITY_COLORS[quality].b);
+ frame.Item2.text:SetTextColor(BAG_ITEM_QUALITY_COLORS[quality].r, BAG_ITEM_QUALITY_COLORS[quality].g,
+ BAG_ITEM_QUALITY_COLORS[quality].b);
end
- if ( rewardData.currencyQuantity and rewardData.currencyQuantity > 1 ) then
+ if (rewardData.currencyQuantity and rewardData.currencyQuantity > 1) then
frame.Item2.Count:SetText(rewardData.currencyQuantity);
frame.Item2.Count:Show();
else
@@ -3506,7 +3606,7 @@ function AdventureJournal_Reward_OnEnter(self)
frame:SetWidth(256);
- if ( rewardHeaderText and rewardHeaderText ~= "" ) then
+ if (rewardHeaderText and rewardHeaderText ~= "") then
frame.headerText:SetText(rewardHeaderText);
frame.Item1:SetPoint("TOPLEFT", frame.headerText, "BOTTOMLEFT", 0, -16);
height = height + frame.headerText:GetHeight();
@@ -3517,7 +3617,7 @@ function AdventureJournal_Reward_OnEnter(self)
end
frame:SetHeight(height);
- elseif ( rewardData.itemLink or rewardData.currencyType ) then
+ elseif (rewardData.itemLink or rewardData.currencyType) then
frame.Item2:Hide();
frame.Item1:Show();
frame.Item1.text:Hide();
@@ -3525,14 +3625,14 @@ function AdventureJournal_Reward_OnEnter(self)
local tooltip = frame.Item1.tooltip;
tooltip:SetOwner(frame.Item1, "ANCHOR_NONE");
frame.Item1.UpdateTooltip = function() AdventureJournal_Reward_OnEnter(self) end;
- if ( rewardData.itemLink ) then
+ if (rewardData.itemLink) then
tooltip:SetHyperlink(rewardData.itemLink);
GameTooltip_ShowCompareItem(tooltip, frame.Item1.tooltip);
- local quality = select(3, C_Item.GetItemInfo(rewardData.itemLink));
+ local quality = select(3, C_Item.GetItemInfo(rewardData.itemLink));
SetItemButtonQuality(frame.Item1, quality, rewardData.itemLink);
- if ( rewardData.itemQuantity and rewardData.itemQuantity > 1 ) then
+ if (rewardData.itemQuantity and rewardData.itemQuantity > 1) then
frame.Item1.Count:SetText(rewardData.itemQuantity);
frame.Item1.Count:Show();
else
@@ -3541,14 +3641,14 @@ function AdventureJournal_Reward_OnEnter(self)
self:SetScript("OnUpdate", EncounterJournal_AJ_OnUpdate);
frame.Item1.icon:SetTexture(rewardData.itemIcon);
- elseif ( rewardData.currencyType ) then
+ elseif (rewardData.currencyType) then
tooltip:SetHyperlink(strconcat("item:", rewardData.currencyType));
local _, _, quality = C_Item.GetItemInfo(rewardData.currencyType, nil, nil, true);
SetItemButtonQuality(frame.Item1, quality);
- if ( rewardData.currencyQuantity and rewardData.currencyQuantity > 1 ) then
+ if (rewardData.currencyQuantity and rewardData.currencyQuantity > 1) then
frame.Item1.Count:SetText(rewardData.currencyQuantity);
frame.Item1.Count:Show();
else
@@ -3558,9 +3658,9 @@ function AdventureJournal_Reward_OnEnter(self)
frame.Item1.icon:SetTexture(rewardData.currencyIcon);
end
- frame:SetWidth(tooltip:GetWidth()+54);
+ frame:SetWidth(tooltip:GetWidth() + 54);
- if ( rewardHeaderText and rewardHeaderText ~= "" ) then
+ if (rewardHeaderText and rewardHeaderText ~= "") then
frame.headerText:SetText(rewardHeaderText);
frame.headerText:Show();
frame.Item1:SetPoint("TOPLEFT", frame.headerText, "BOTTOMLEFT", 0, -16);
@@ -3572,10 +3672,10 @@ function AdventureJournal_Reward_OnEnter(self)
tooltip:SetPoint("TOPLEFT", frame.Item1.icon, "TOPRIGHT", 0, 10);
tooltip:Show();
- frame.Item1:SetSize(tooltip:GetWidth()+44, tooltip:GetHeight());
+ frame.Item1:SetSize(tooltip:GetWidth() + 44, tooltip:GetHeight());
local height = tooltip:GetHeight() + 6;
- if ( frame.headerText:IsShown() ) then
+ if (frame.headerText:IsShown()) then
height = height + frame.headerText:GetHeight() + 14;
end
if (rewardData.isRewardTable) then
@@ -3585,14 +3685,14 @@ function AdventureJournal_Reward_OnEnter(self)
end
frame:SetHeight(height);
- elseif ( rewardHeaderText and rewardHeaderText ~= "" ) then
- -- frame:SetWidth(256);
+ elseif (rewardHeaderText and rewardHeaderText ~= "") then
+ -- frame:SetWidth(256);
frame.Item1:Hide();
frame.Item2:Hide();
frame.headerText:SetText(rewardHeaderText);
- frame:SetWidth(frame.headerText:GetStringWidth()+22); -- add padding for tooltip border
- frame:SetHeight(frame.headerText:GetStringHeight()+20); -- add padding for tooltip border
+ frame:SetWidth(frame.headerText:GetStringWidth() + 22); -- add padding for tooltip border
+ frame:SetHeight(frame.headerText:GetStringHeight() + 20); -- add padding for tooltip border
frame.headerText:Show();
else
return;
@@ -3622,16 +3722,16 @@ end
function AdventureJournal_Reward_OnMouseDown(self)
local index = self:GetParent().index;
local data = EncounterJournal.suggestFrame.suggestions[index];
- if ( data.ej_instanceID ) then
+ if (data.ej_instanceID) then
EncounterJournal_DisplayInstance(data.ej_instanceID);
-- try to set difficulty to current instance difficulty
- if ( EJ_IsValidInstanceDifficulty(data.difficultyID) ) then
+ if (EJ_IsValidInstanceDifficulty(data.difficultyID)) then
EJ_SetDifficulty(data.difficultyID);
end
-- select the loot tab
EncounterJournal.encounter.info[EJ_Tabs[2].button]:Click();
- elseif ( data.isRandomDungeon ) then
+ elseif (data.isRandomDungeon) then
EJ_ContentTab_Select(EncounterJournal.instanceSelect.dungeonsTab.id);
EncounterJournal_TierDropDown_Select(nil, data.expansionLevel);
end
@@ -3645,7 +3745,7 @@ function EncounterJournalBossButton_OnClick(self)
return;
end
local _, _, _, rootSectionID = EJ_GetEncounterInfo(self.encounterID);
- if ( rootSectionID == 0 ) then
+ if (rootSectionID == 0) then
EncounterJournal_SetTab(EncounterJournal.encounter.info.lootTab:GetID());
end
EncounterJournal_DisplayEncounter(self.encounterID);
@@ -3708,7 +3808,8 @@ function EncounterInstanceButtonRequirements_OnEnter(self)
for index, requirement in ipairs(self.requirements) do
GameTooltip_AddBlankLineToTooltip(GameTooltip)
- local difficultyPrefix, difficultySize, difficultyMask = EJ_GetDifficultyInfo(requirement.difficultyID, requirement.isRaid)
+ local difficultyPrefix, difficultySize, difficultyMask = EJ_GetDifficultyInfo(requirement.difficultyID,
+ requirement.isRaid)
local difficultyStr
if difficultyPrefix then
difficultyStr = string.format("(%s) %s", difficultySize, difficultyPrefix)
@@ -3716,15 +3817,23 @@ function EncounterInstanceButtonRequirements_OnEnter(self)
difficultyStr = requirement.difficultyID
end
- GameTooltip_AddNormalLine(GameTooltip, string.format(EJ_INSTANCE_REQUIREMENT_DIFFICULTY, HIGHLIGHT_FONT_COLOR:WrapTextInColorCode(difficultyStr)), true)
+ GameTooltip_AddNormalLine(GameTooltip,
+ string.format(EJ_INSTANCE_REQUIREMENT_DIFFICULTY, HIGHLIGHT_FONT_COLOR:WrapTextInColorCode(difficultyStr)),
+ true)
if requirement.minLevel and requirement.maxLevel then
- local completed = WithinRange(UnitLevel("player"), requirement.minLevel or 1, requirement.maxLevel or MAX_PLAYER_LEVEL)
+ local completed = WithinRange(UnitLevel("player"), requirement.minLevel or 1,
+ requirement.maxLevel or MAX_PLAYER_LEVEL)
local color = completed and GREEN_FONT_COLOR or HIGHLIGHT_FONT_COLOR
if requirement.minLevel == requirement.maxLevel then
- GameTooltip_AddNormalLine(GameTooltip, string.format(EJ_INSTANCE_REQUIREMENT_LEVEL, color:WrapTextInColorCode(requirement.maxLevel)), true)
+ GameTooltip_AddNormalLine(GameTooltip,
+ string.format(EJ_INSTANCE_REQUIREMENT_LEVEL, color:WrapTextInColorCode(requirement.maxLevel)),
+ true)
else
- GameTooltip_AddNormalLine(GameTooltip, string.format(EJ_INSTANCE_REQUIREMENT_LEVEL_RANGE, color:WrapTextInColorCode(requirement.minLevel), color:WrapTextInColorCode(requirement.maxLevel)), true)
+ GameTooltip_AddNormalLine(GameTooltip,
+ string.format(EJ_INSTANCE_REQUIREMENT_LEVEL_RANGE,
+ color:WrapTextInColorCode(requirement.minLevel),
+ color:WrapTextInColorCode(requirement.maxLevel)), true)
end
end
@@ -3732,7 +3841,9 @@ function EncounterInstanceButtonRequirements_OnEnter(self)
local avgItemLevelEquipped = GetAverageItemLevel()
local completed = avgItemLevelEquipped >= requirement.itemLevel
local color = completed and GREEN_FONT_COLOR or HIGHLIGHT_FONT_COLOR
- GameTooltip_AddNormalLine(GameTooltip, string.format(EJ_INSTANCE_REQUIREMENT_ITEM_LEVEL, color:WrapTextInColorCode(requirement.itemLevel)), true)
+ GameTooltip_AddNormalLine(GameTooltip,
+ string.format(EJ_INSTANCE_REQUIREMENT_ITEM_LEVEL, color:WrapTextInColorCode(requirement.itemLevel)),
+ true)
end
if requirement.quests then
@@ -3757,7 +3868,8 @@ function EncounterInstanceButtonRequirements_OnEnter(self)
if requirement.achievements then
GameTooltip_AddNormalLine(GameTooltip, EJ_INSTANCE_REQUIREMENT_ACHIEVEMENTS, true)
for achievementIndex, achievementID in ipairs(requirement.achievements) do
- local id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(achievementID)
+ local id, name, points, completed, month, day, year, description, flags, icon = GetAchievementInfo(
+ achievementID)
if IsGMAccount() then
name = string.format("%s [%d]", name, achievementID)
end
@@ -3814,7 +3926,8 @@ local factionData = {
}
function LootJournal_CanOpenItemByEntry(itemID, checkFaction)
- local _itemID, encounterID, name, icon, equipSlot, itemSubType, link, itemType, difficultyID, factionID = EJ_GetLootInfo(itemID)
+ local _itemID, encounterID, name, icon, equipSlot, itemSubType, link, itemType, difficultyID, factionID =
+ EJ_GetLootInfo(itemID)
local canOpened = false
if encounterID then
@@ -3838,7 +3951,8 @@ function LootJournal_OpenItemByEntry(itemID)
return
end
- local _itemID, encounterID, name, icon, equipSlot, itemSubType, link, itemType, difficultyID, factionID = EJ_GetLootInfo(itemID)
+ local _itemID, encounterID, name, icon, equipSlot, itemSubType, link, itemType, difficultyID, factionID =
+ EJ_GetLootInfo(itemID)
if encounterID then
local _, _, _, _, _, instanceID = EJ_GetEncounterInfo(encounterID)
if instanceID then
diff --git a/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.xml b/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.xml
index 93db5b8..9b0152d 100644
--- a/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.xml
+++ b/src/Data/ruRU/patch-ruRU-5/Interface/AddOns/MoonWellClient/EncounterJournal/Custom_EncounterJournal/Custom_EncounterJournal.xml
@@ -2107,7 +2107,7 @@
-