663 lines
24 KiB
Lua
663 lines
24 KiB
Lua
-- Freewood-OctoWoW-Pet: Tab "Begleiter" im Freewood-Fenster
|
|
-- Links die Liste der erfassten Begleiter, rechts Kennzahlen, Nahrung und Faehigkeiten.
|
|
-- Aufbau angelehnt an das Stitch-Design "Jaeger Begleiter" (Filter/Liste links, Details rechts).
|
|
|
|
local ADDON, NS = ...
|
|
|
|
local FW = _G.Freewood
|
|
local Pet = NS.Pet
|
|
if not FW or not Pet then
|
|
return
|
|
end
|
|
|
|
local UI = FW.UI
|
|
|
|
local LIST_W = 252
|
|
local ROW_H, ROW_GAP = 54, 6
|
|
local CARD_W, CARD_H, CARD_GAP = 176, 48, 10
|
|
local ABILITY_H = 30
|
|
|
|
local function FormatTime(t)
|
|
if type(t) ~= "number" or t <= 0 then
|
|
return "-"
|
|
end
|
|
return date("%d.%m.%Y %H:%M", t)
|
|
end
|
|
|
|
local function SortedKeys()
|
|
local keys = {}
|
|
for key in pairs(Pet.db.pets) do
|
|
keys[#keys + 1] = key
|
|
end
|
|
table.sort(keys, function(a, b)
|
|
if a == b then
|
|
return false
|
|
end
|
|
if a == Pet.activeKey then
|
|
return true
|
|
end
|
|
if b == Pet.activeKey then
|
|
return false
|
|
end
|
|
local ra, rb = Pet.db.pets[a], Pet.db.pets[b]
|
|
local ia, ib = ra.src == "import", rb.src == "import"
|
|
if ia ~= ib then
|
|
return not ia
|
|
end
|
|
local ua, ub = ra.updated or 0, rb.updated or 0
|
|
if ua ~= ub then
|
|
return ua > ub
|
|
end
|
|
return a < b
|
|
end)
|
|
return keys
|
|
end
|
|
|
|
local function Subtitle(rec)
|
|
return string.format("%s - %s", rec.family or "?", string.format(FW.L.PET_LEVEL, rec.level or 0))
|
|
end
|
|
|
|
------------------------------------------------------------------------
|
|
-- Zeile der Liste
|
|
------------------------------------------------------------------------
|
|
|
|
local function CreateListRow(parent, onSelect)
|
|
local row = CreateFrame("Button", nil, parent)
|
|
row:SetHeight(ROW_H)
|
|
|
|
row.bg = row:CreateTexture(nil, "BACKGROUND")
|
|
row.bg:SetAllPoints()
|
|
UI.AddBorder(row, "bronze", 0.6)
|
|
|
|
row.icon = row:CreateTexture(nil, "ARTWORK")
|
|
row.icon:SetSize(34, 34)
|
|
row.icon:SetPoint("LEFT", row, "LEFT", 8, 0)
|
|
row.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
|
|
row.name = UI.CreateLabel(row, "", { font = "heading", size = 13, color = "goldLight" })
|
|
row.name:SetPoint("TOPLEFT", row, "TOPLEFT", 52, -10)
|
|
row.name:SetWidth(LIST_W - 130)
|
|
row.name:SetWordWrap(false)
|
|
|
|
row.sub = UI.CreateLabel(row, "", { size = 11, color = "textDim" })
|
|
row.sub:SetPoint("TOPLEFT", row.name, "BOTTOMLEFT", 0, -6)
|
|
row.sub:SetWidth(LIST_W - 70)
|
|
row.sub:SetWordWrap(false)
|
|
|
|
row.chip = UI.CreateChip(row, "", "success")
|
|
row.chip:SetPoint("TOPRIGHT", row, "TOPRIGHT", -10, -9)
|
|
|
|
local function Refresh()
|
|
if row.selected then
|
|
row.bg:SetColorTexture(UI.Color("hover"))
|
|
UI.SetBorderColor(row, "gold")
|
|
elseif row.hover then
|
|
row.bg:SetColorTexture(UI.Color("hover", 0.7))
|
|
UI.SetBorderColor(row, "bronze")
|
|
else
|
|
row.bg:SetColorTexture(UI.Color("card"))
|
|
UI.SetBorderColor(row, "bronze", 0.6)
|
|
end
|
|
end
|
|
|
|
function row:SetSelected(selected)
|
|
self.selected = selected
|
|
Refresh()
|
|
end
|
|
|
|
row:SetScript("OnEnter", function()
|
|
row.hover = true
|
|
Refresh()
|
|
end)
|
|
row:SetScript("OnLeave", function()
|
|
row.hover = false
|
|
Refresh()
|
|
end)
|
|
row:SetScript("OnClick", function()
|
|
onSelect(row.key)
|
|
end)
|
|
|
|
Refresh()
|
|
return row
|
|
end
|
|
|
|
------------------------------------------------------------------------
|
|
-- Tab
|
|
------------------------------------------------------------------------
|
|
|
|
local function Build(content)
|
|
local L = FW.L
|
|
local f = CreateFrame("Frame", nil, content)
|
|
|
|
local rows, abilityRows, foodChips = {}, {}, {}
|
|
|
|
---------------- linke Spalte ----------------
|
|
local listTitle = UI.CreateLabel(f, L.PET_LIST_HEADER, { font = "heading", size = 14, color = "goldLight" })
|
|
listTitle:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
|
|
|
|
local listDivider = UI.CreateDivider(f)
|
|
listDivider:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -26)
|
|
listDivider:SetWidth(LIST_W)
|
|
|
|
local listScroll = UI.CreateScrollFrame(f)
|
|
listScroll:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -36)
|
|
listScroll:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 0)
|
|
listScroll:SetWidth(LIST_W)
|
|
|
|
local separator = f:CreateTexture(nil, "ARTWORK")
|
|
separator:SetColorTexture(UI.Color("bronze", 0.4))
|
|
separator:SetWidth(1)
|
|
separator:SetPoint("TOPLEFT", f, "TOPLEFT", LIST_W + 10, 0)
|
|
separator:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", LIST_W + 10, 0)
|
|
|
|
---------------- rechte Spalte ----------------
|
|
local detail = CreateFrame("Frame", nil, f)
|
|
detail:SetPoint("TOPLEFT", f, "TOPLEFT", LIST_W + 22, 0)
|
|
detail:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
|
|
|
|
local empty = UI.CreateLabel(f, L.PET_EMPTY, { size = 12, color = "textDim", justifyV = "TOP", justify = "LEFT" })
|
|
empty:SetPoint("TOPLEFT", f, "TOPLEFT", LIST_W + 22, -4)
|
|
empty:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -4)
|
|
empty:SetWordWrap(true)
|
|
|
|
local headIcon = CreateFrame("Frame", nil, detail)
|
|
headIcon:SetSize(48, 48)
|
|
headIcon:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, 0)
|
|
headIcon.tex = headIcon:CreateTexture(nil, "ARTWORK")
|
|
headIcon.tex:SetPoint("TOPLEFT", headIcon, "TOPLEFT", 2, -2)
|
|
headIcon.tex:SetPoint("BOTTOMRIGHT", headIcon, "BOTTOMRIGHT", -2, 2)
|
|
headIcon.tex:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
UI.AddBorder(headIcon, "gold", 1)
|
|
|
|
local nameLabel = UI.CreateLabel(detail, "", { font = "heading", size = 20, color = "goldLight" })
|
|
nameLabel:SetPoint("TOPLEFT", detail, "TOPLEFT", 60, 0)
|
|
nameLabel:SetWidth(380)
|
|
nameLabel:SetWordWrap(false)
|
|
|
|
local subLabel = UI.CreateLabel(detail, "", { size = 12, color = "textDim" })
|
|
subLabel:SetPoint("TOPLEFT", detail, "TOPLEFT", 60, -28)
|
|
|
|
local stateChip = UI.CreateChip(detail, "", "success")
|
|
stateChip:SetPoint("TOPRIGHT", detail, "TOPRIGHT", 0, -4)
|
|
|
|
local updatedLabel = UI.CreateLabel(detail, "", { size = 11, color = "textDim", justify = "RIGHT" })
|
|
updatedLabel:SetPoint("TOPRIGHT", detail, "TOPRIGHT", 0, -32)
|
|
updatedLabel:SetWidth(240)
|
|
|
|
local headDivider = UI.CreateDivider(detail)
|
|
headDivider:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, -58)
|
|
headDivider:SetPoint("TOPRIGHT", detail, "TOPRIGHT", 0, -58)
|
|
|
|
-- Kennzahlen
|
|
local cards = {}
|
|
local defs = {
|
|
{ key = "happiness", label = L.PET_HAPPINESS },
|
|
{ key = "loyalty", label = L.PET_LOYALTY },
|
|
{ key = "training", label = L.PET_TRAINING },
|
|
{ key = "health", label = L.PET_HEALTH },
|
|
{ key = "damage", label = L.PET_DAMAGE },
|
|
{ key = "armor", label = L.PET_ARMOR },
|
|
{ key = "ap", label = L.PET_AP },
|
|
{ key = "crit", label = L.PET_CRIT },
|
|
{ key = "move", label = L.PET_MOVE },
|
|
}
|
|
for i, def in ipairs(defs) do
|
|
local card = UI.CreateStatCard(detail, def.label, CARD_W, CARD_H)
|
|
UI.SetFont(card.value, "heading", 13)
|
|
local col = (i - 1) % 3
|
|
local rowIndex = math.floor((i - 1) / 3)
|
|
card:SetPoint("TOPLEFT", detail, "TOPLEFT", col * (CARD_W + CARD_GAP), -(68 + rowIndex * (CARD_H + CARD_GAP)))
|
|
-- Familienfaktor oben rechts auf der Karte
|
|
card.factor = UI.CreateLabel(card, "", { size = 10, color = "textDim", justify = "RIGHT", flags = "" })
|
|
card.factor:SetPoint("TOPRIGHT", card, "TOPRIGHT", -10, -8)
|
|
cards[def.key] = card
|
|
end
|
|
|
|
-- Widerstaende (Schulen 2 bis 6)
|
|
local RES_W, RES_GAP = 100, 12
|
|
local resDefs = {
|
|
{ school = 2, label = L.PET_RES_FIRE },
|
|
{ school = 3, label = L.PET_RES_NATURE },
|
|
{ school = 4, label = L.PET_RES_FROST },
|
|
{ school = 5, label = L.PET_RES_SHADOW },
|
|
{ school = 6, label = L.PET_RES_ARCANE },
|
|
}
|
|
local resCards = {}
|
|
for i, def in ipairs(resDefs) do
|
|
local card = UI.CreateStatCard(detail, def.label, RES_W, CARD_H)
|
|
UI.SetFont(card.value, "heading", 13)
|
|
card:SetPoint("TOPLEFT", detail, "TOPLEFT", (i - 1) * (RES_W + RES_GAP), -(68 + 3 * (CARD_H + CARD_GAP)))
|
|
resCards[def.school] = card
|
|
end
|
|
|
|
-- Tooltips: lesen den aktuell angezeigten Eintrag (current) beim Darueberfahren
|
|
local current
|
|
local function NoData()
|
|
return { L.PET_TIP_NODATA }
|
|
end
|
|
local function ArmorReduction(armor, level)
|
|
if type(PaperDollFrame_GetArmorReduction) == "function" then
|
|
local ok, v = pcall(PaperDollFrame_GetArmorReduction, armor, level)
|
|
if ok and type(v) == "number" then
|
|
return v
|
|
end
|
|
end
|
|
local r = armor / (armor + 400 + 85 * level) * 100
|
|
return math.min(75, r)
|
|
end
|
|
local function TipLines(key)
|
|
local rec = current
|
|
local lines = {}
|
|
if not rec then
|
|
return NoData()
|
|
end
|
|
if key == "health" then
|
|
lines = { L.PET_TIP_HEALTH_1, L.PET_TIP_HEALTH_2 }
|
|
elseif key == "armor" then
|
|
if not rec.armor then return NoData() end
|
|
lines = { string.format(L.PET_TIP_ARMOR_1, ArmorReduction(rec.armor, rec.level or 1)), L.PET_TIP_ARMOR_2 }
|
|
elseif key == "damage" then
|
|
if not (rec.dmgMin and rec.dmgMax) then return NoData() end
|
|
lines = { string.format(L.PET_TIP_DAMAGE_1, rec.dmgMin, rec.dmgMax) }
|
|
if rec.speed and rec.speed > 0 then
|
|
lines[#lines + 1] = string.format(L.PET_TIP_DAMAGE_2, rec.speed)
|
|
lines[#lines + 1] = string.format(L.PET_TIP_DAMAGE_3, (rec.dmgMin + rec.dmgMax) / 2 / rec.speed)
|
|
end
|
|
elseif key == "ap" then
|
|
if not rec.apBase then return NoData() end
|
|
local bonus = rec.apBonus or 0
|
|
lines = { string.format(L.PET_TIP_AP_1, rec.apBase, bonus, rec.apBase + bonus), L.PET_TIP_AP_2 }
|
|
elseif key == "crit" then
|
|
if not (rec.critMelee or rec.critSpell or rec.critRanged) then return NoData() end
|
|
if rec.critMelee then lines[#lines + 1] = string.format(L.PET_TIP_CRIT_1, rec.critMelee) end
|
|
if rec.critSpell then lines[#lines + 1] = string.format(L.PET_TIP_CRIT_2, rec.critSpell) end
|
|
if rec.critRanged then lines[#lines + 1] = string.format(L.PET_TIP_CRIT_3, rec.critRanged) end
|
|
lines[#lines + 1] = L.PET_TIP_CRIT_4
|
|
elseif key == "move" then
|
|
if not rec.runSpeed then return NoData() end
|
|
lines = { string.format(L.PET_TIP_MOVE_1, rec.runSpeed, math.floor(rec.runSpeed / 7 * 100 + 0.5)) }
|
|
end
|
|
return lines
|
|
end
|
|
local tipTitles = {
|
|
health = L.PET_TIP_HEALTH, armor = L.PET_TIP_ARMOR, damage = L.PET_TIP_DAMAGE,
|
|
ap = L.PET_TIP_AP, crit = L.PET_TIP_CRIT, move = L.PET_TIP_MOVE,
|
|
}
|
|
for key, title in pairs(tipTitles) do local key = key
|
|
UI.AttachTooltip(cards[key], title, function() return TipLines(key) end)
|
|
end
|
|
for school, card in pairs(resCards) do local school = school
|
|
UI.AttachTooltip(card, L.PET_TIP_RES, function()
|
|
local v = current and current.resist and current.resist[school]
|
|
if not v then return NoData() end
|
|
local pct = math.min(75, v / (math.max(1, current.level or 1) * 5) * 75)
|
|
return { string.format(L.PET_TIP_RES_1, v), string.format(L.PET_TIP_RES_2, pct), L.PET_TIP_RES_3 }
|
|
end)
|
|
end
|
|
|
|
-- Faktor als Text und Farbe: ueber 1 gold, unter 1 gedaempft, 1,00 neutral
|
|
local function SetFactor(card, factor)
|
|
if not factor then
|
|
card.factor:SetText("")
|
|
return
|
|
end
|
|
local color = "textDim"
|
|
if factor > 1.0001 then
|
|
color = "goldLight"
|
|
elseif factor < 0.9999 then
|
|
color = "danger"
|
|
end
|
|
card.factor:SetText(string.format("x%.2f", factor))
|
|
card.factor:SetTextColor(UI.Color(color))
|
|
end
|
|
|
|
-- Nahrung
|
|
local foodLabel = UI.CreateLabel(detail, L.PET_FOOD, { font = "heading", size = 13, color = "goldLight" })
|
|
foodLabel:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, -300)
|
|
local foodNone = UI.CreateLabel(detail, L.PET_FOOD_UNKNOWN, { size = 12, color = "textDim" })
|
|
foodNone:SetPoint("LEFT", foodLabel, "RIGHT", 14, 0)
|
|
|
|
-- Faehigkeiten
|
|
local abilityTitle = UI.CreateLabel(detail, L.PET_ABILITIES, { font = "heading", size = 14, color = "goldLight" })
|
|
abilityTitle:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, -336)
|
|
local abilityDivider = UI.CreateDivider(detail)
|
|
abilityDivider:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, -360)
|
|
abilityDivider:SetPoint("TOPRIGHT", detail, "TOPRIGHT", 0, -360)
|
|
|
|
local abilityScroll = UI.CreateScrollFrame(detail)
|
|
abilityScroll:SetPoint("TOPLEFT", detail, "TOPLEFT", 0, -368)
|
|
abilityScroll:SetPoint("BOTTOMRIGHT", detail, "BOTTOMRIGHT", 0, 42)
|
|
|
|
local abilityNote = UI.CreateLabel(abilityScroll.child, "", { size = 11, color = "textDim" })
|
|
|
|
-- Knoepfe
|
|
local status = UI.CreateLabel(detail, "", { size = 12 })
|
|
status:SetWidth(360)
|
|
|
|
local refreshButton = UI.CreateButton(detail, L.PET_REFRESH, 170, 28, function()
|
|
local ok, reason = Pet:Scan()
|
|
if ok then
|
|
status:SetText("|cff" .. UI.Hex("success") .. FW.L.PET_REFRESH_OK .. "|r")
|
|
else
|
|
local msg = FW.L.PET_REFRESH_FAIL
|
|
if reason == "nopet" then
|
|
msg = FW.L.PET_REFRESH_NOPET
|
|
elseif reason == "combat" then
|
|
msg = FW.L.PET_REFRESH_COMBAT
|
|
elseif reason == "error" or reason == "nodata" then
|
|
msg = FW.L.PET_REFRESH_ERROR
|
|
end
|
|
status:SetText("|cff" .. UI.Hex("danger") .. msg .. "|r")
|
|
end
|
|
end, "primary")
|
|
refreshButton:SetPoint("BOTTOMLEFT", detail, "BOTTOMLEFT", 0, 0)
|
|
|
|
local confirming = false
|
|
local deleteButton
|
|
deleteButton = UI.CreateButton(detail, L.PET_DELETE, 160, 28, function()
|
|
if confirming then
|
|
confirming = false
|
|
deleteButton:SetLabel(FW.L.PET_DELETE)
|
|
deleteButton:SetStyle("danger")
|
|
if Pet.selectedKey then
|
|
Pet:Delete(Pet.selectedKey)
|
|
end
|
|
else
|
|
confirming = true
|
|
deleteButton:SetLabel(FW.L.PET_DELETE_CONFIRM)
|
|
deleteButton:SetStyle("dangerActive")
|
|
C_Timer.After(3, function()
|
|
confirming = false
|
|
deleteButton:SetLabel(FW.L.PET_DELETE)
|
|
deleteButton:SetStyle("danger")
|
|
end)
|
|
end
|
|
end, "danger")
|
|
deleteButton:SetPoint("LEFT", refreshButton, "RIGHT", 8, 0)
|
|
|
|
status:SetPoint("LEFT", deleteButton, "RIGHT", 16, 0)
|
|
|
|
---------------- Inhalt fuellen ----------------
|
|
local HAPPINESS = {
|
|
[3] = { text = function() return FW.L.PET_HAPPY end, color = "success" },
|
|
[2] = { text = function() return FW.L.PET_CONTENT end, color = "goldLight" },
|
|
[1] = { text = function() return FW.L.PET_UNHAPPY end, color = "danger" },
|
|
}
|
|
|
|
local function ShowFoods(foods)
|
|
for _, chip in ipairs(foodChips) do
|
|
chip:Hide()
|
|
end
|
|
if type(foods) ~= "table" or #foods == 0 then
|
|
foodNone:Show()
|
|
return
|
|
end
|
|
foodNone:Hide()
|
|
local previous
|
|
for i, food in ipairs(foods) do
|
|
local chip = foodChips[i]
|
|
if not chip then
|
|
chip = UI.CreateChip(detail, food, "bronze")
|
|
foodChips[i] = chip
|
|
end
|
|
chip:SetText(food, "goldAntique")
|
|
chip:ClearAllPoints()
|
|
if previous then
|
|
chip:SetPoint("LEFT", previous, "RIGHT", 6, 0)
|
|
else
|
|
chip:SetPoint("LEFT", foodLabel, "RIGHT", 14, 0)
|
|
end
|
|
chip:Show()
|
|
previous = chip
|
|
end
|
|
end
|
|
|
|
local function ShowAbilities(rec)
|
|
local list = rec.abilities or {}
|
|
local others = rec.others or {}
|
|
|
|
for i, ability in ipairs(list) do
|
|
local row = abilityRows[i]
|
|
if not row then
|
|
row = UI.CreatePanel(abilityScroll.child, "card", "bronze")
|
|
row:SetHeight(ABILITY_H)
|
|
row.icon = row:CreateTexture(nil, "ARTWORK")
|
|
row.icon:SetSize(ABILITY_H - 8, ABILITY_H - 8)
|
|
row.icon:SetPoint("LEFT", row, "LEFT", 5, 0)
|
|
row.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
row.name = UI.CreateLabel(row, "", { size = 12 })
|
|
row.name:SetPoint("LEFT", row.icon, "RIGHT", 8, 0)
|
|
row.passive = UI.CreateLabel(row, "", { size = 10, color = "textDim", justify = "RIGHT" })
|
|
row.chip = UI.CreateChip(row, "", "goldLight")
|
|
row.chip:SetPoint("RIGHT", row, "RIGHT", -6, 0)
|
|
row.passive:SetPoint("RIGHT", row.chip, "LEFT", -8, 0)
|
|
abilityRows[i] = row
|
|
end
|
|
local y = (i - 1) * (ABILITY_H + 4)
|
|
row:ClearAllPoints()
|
|
row:SetPoint("TOPLEFT", abilityScroll.child, "TOPLEFT", 0, -y)
|
|
row:SetPoint("TOPRIGHT", abilityScroll.child, "TOPRIGHT", 0, -y)
|
|
row.name:SetText(ability.name or "?")
|
|
local tex
|
|
if ability.spellID then
|
|
if C_Spell and C_Spell.GetSpellTexture then
|
|
local ok, t = pcall(C_Spell.GetSpellTexture, ability.spellID)
|
|
tex = ok and t or nil
|
|
elseif GetSpellTexture then
|
|
local ok, t = pcall(GetSpellTexture, ability.spellID)
|
|
tex = ok and t or nil
|
|
end
|
|
end
|
|
row.icon:SetTexture(tex or "Interface\\Icons\\INV_Misc_QuestionMark")
|
|
row.passive:SetText(ability.passive and FW.L.PET_PASSIVE or "")
|
|
if ability.rank then
|
|
row.chip:SetText(string.format(FW.L.PET_RANK, ability.rank), "goldLight")
|
|
row.chip:Show()
|
|
else
|
|
row.chip:Hide()
|
|
end
|
|
row:Show()
|
|
end
|
|
for i = #list + 1, #abilityRows do
|
|
abilityRows[i]:Hide()
|
|
end
|
|
|
|
local y = #list * (ABILITY_H + 4)
|
|
local noteText
|
|
if #list == 0 then
|
|
noteText = FW.L.PET_NO_ABILITIES
|
|
elseif #others > 0 then
|
|
noteText = string.format(FW.L.PET_OTHERS, #others)
|
|
end
|
|
abilityNote:ClearAllPoints()
|
|
abilityNote:SetPoint("TOPLEFT", abilityScroll.child, "TOPLEFT", 4, -(y + 6))
|
|
abilityNote:SetText(noteText or "")
|
|
abilityScroll:SetContentHeight(y + 30)
|
|
end
|
|
|
|
local function ShowRecord(key, rec)
|
|
current = rec
|
|
local L2 = FW.L
|
|
nameLabel:SetText(rec.name or "?")
|
|
headIcon.tex:SetTexture(Pet.FamilyIcon and Pet.FamilyIcon(rec.family) or "Interface\\Icons\\Ability_Hunter_BeastTaming")
|
|
subLabel:SetText(Subtitle(rec))
|
|
updatedLabel:SetText(string.format(L2.PET_UPDATED, FormatTime(rec.updated or rec.importedAt)))
|
|
|
|
if key == Pet.activeKey then
|
|
stateChip:SetText(L2.PET_ACTIVE, "success")
|
|
stateChip:Show()
|
|
elseif rec.src == "import" then
|
|
stateChip:SetText(L2.PET_IMPORTED, "textDim")
|
|
stateChip:Show()
|
|
else
|
|
stateChip:Hide()
|
|
end
|
|
|
|
-- Zufriedenheit
|
|
local happy = HAPPINESS[rec.happiness or 0]
|
|
if happy then
|
|
local text = happy.text()
|
|
if rec.damagePct then
|
|
text = string.format("%s (%d%%)", text, rec.damagePct)
|
|
end
|
|
cards.happiness:SetValue(text, happy.color)
|
|
else
|
|
cards.happiness:SetValue("-", "textDim")
|
|
end
|
|
|
|
-- Treue
|
|
if rec.loyaltyText then
|
|
local plain = rec.loyaltyText:gsub("^%b()%s*", "")
|
|
local text = plain ~= "" and plain or rec.loyaltyText
|
|
if rec.loyaltyLevel then
|
|
text = rec.loyaltyLevel .. " - " .. text
|
|
end
|
|
cards.loyalty:SetValue(text)
|
|
else
|
|
cards.loyalty:SetValue("-", "textDim")
|
|
end
|
|
|
|
-- Trainingspunkte
|
|
if rec.trainingTotal then
|
|
local free = math.max(0, rec.trainingTotal - (rec.trainingSpent or 0))
|
|
cards.training:SetValue(string.format(L2.PET_TRAINING_VALUE, free, rec.trainingTotal))
|
|
else
|
|
cards.training:SetValue("-", "textDim")
|
|
end
|
|
|
|
-- Leben, Schaden (mit Tempo im Titel), Ruestung, dazu die Familienfaktoren
|
|
local mods = Pet.GetFamilyMods and Pet.GetFamilyMods(rec.family)
|
|
if rec.hpMax then
|
|
cards.health:SetValue(string.format("%d", rec.hpMax))
|
|
else
|
|
cards.health:SetValue("-", "textDim")
|
|
end
|
|
SetFactor(cards.health, mods and mods.hp)
|
|
if rec.dmgMin and rec.dmgMax then
|
|
cards.damage:SetValue(string.format("%d - %d", rec.dmgMin, rec.dmgMax))
|
|
else
|
|
cards.damage:SetValue("-", "textDim")
|
|
end
|
|
if rec.speed then
|
|
cards.damage:SetLabel(string.format("%s | %.1f s", L2.PET_DAMAGE, rec.speed))
|
|
else
|
|
cards.damage:SetLabel(L2.PET_DAMAGE)
|
|
end
|
|
SetFactor(cards.damage, mods and mods.dmg)
|
|
SetFactor(cards.armor, mods and mods.armor)
|
|
if rec.armor then
|
|
cards.armor:SetValue(string.format("%d", rec.armor))
|
|
else
|
|
cards.armor:SetValue("-", "textDim")
|
|
end
|
|
|
|
-- Zusatzwerte
|
|
if rec.apBase then
|
|
cards.ap:SetValue(string.format("%d", rec.apBase + (rec.apBonus or 0)))
|
|
else
|
|
cards.ap:SetValue("-", "textDim")
|
|
end
|
|
local crit = rec.critRanged or rec.critMelee
|
|
if crit then
|
|
cards.crit:SetValue(string.format("%.2f%%", crit))
|
|
else
|
|
cards.crit:SetValue("-", "textDim")
|
|
end
|
|
if rec.runSpeed then
|
|
cards.move:SetValue(string.format("%d%%", math.floor(rec.runSpeed / 7 * 100 + 0.5)))
|
|
else
|
|
cards.move:SetValue("-", "textDim")
|
|
end
|
|
for school, card in pairs(resCards) do
|
|
local v = rec.resist and rec.resist[school]
|
|
if v then
|
|
card:SetValue(string.format("%d", v))
|
|
else
|
|
card:SetValue("-", "textDim")
|
|
end
|
|
end
|
|
|
|
ShowFoods(rec.foods)
|
|
ShowAbilities(rec)
|
|
end
|
|
|
|
function f.Refresh()
|
|
local keys = SortedKeys()
|
|
|
|
if not Pet.selectedKey or not Pet.db.pets[Pet.selectedKey] then
|
|
Pet.selectedKey = (Pet.activeKey and Pet.db.pets[Pet.activeKey]) and Pet.activeKey or keys[1]
|
|
end
|
|
|
|
for i, key in ipairs(keys) do
|
|
local rec = Pet.db.pets[key]
|
|
local row = rows[i]
|
|
if not row then
|
|
row = CreateListRow(listScroll.child, function(selectedKey)
|
|
Pet.selectedKey = selectedKey
|
|
f.Refresh()
|
|
end)
|
|
rows[i] = row
|
|
end
|
|
row.key = key
|
|
local y = (i - 1) * (ROW_H + ROW_GAP)
|
|
row:ClearAllPoints()
|
|
row:SetPoint("TOPLEFT", listScroll.child, "TOPLEFT", 0, -y)
|
|
row:SetPoint("TOPRIGHT", listScroll.child, "TOPRIGHT", 0, -y)
|
|
row.name:SetText(rec.name or "?")
|
|
row.icon:SetTexture(Pet.FamilyIcon and Pet.FamilyIcon(rec.family) or "Interface\\Icons\\Ability_Hunter_BeastTaming")
|
|
row.sub:SetText(Subtitle(rec))
|
|
if key == Pet.activeKey then
|
|
row.chip:SetText(FW.L.PET_ACTIVE, "success")
|
|
row.chip:Show()
|
|
elseif rec.src == "import" then
|
|
row.chip:SetText(FW.L.PET_IMPORTED, "textDim")
|
|
row.chip:Show()
|
|
else
|
|
row.chip:Hide()
|
|
end
|
|
row:SetSelected(key == Pet.selectedKey)
|
|
row:Show()
|
|
end
|
|
for i = #keys + 1, #rows do
|
|
rows[i]:Hide()
|
|
end
|
|
listScroll:SetContentHeight(#keys * (ROW_H + ROW_GAP))
|
|
|
|
local rec = Pet.selectedKey and Pet.db.pets[Pet.selectedKey]
|
|
if rec then
|
|
empty:Hide()
|
|
detail:Show()
|
|
ShowRecord(Pet.selectedKey, rec)
|
|
refreshButton:SetButtonEnabled(UnitExists("pet") and true or false)
|
|
else
|
|
detail:Hide()
|
|
empty:Show()
|
|
end
|
|
end
|
|
|
|
FW:On("PET_UPDATED", function()
|
|
if f:IsVisible() then
|
|
f.Refresh()
|
|
end
|
|
end)
|
|
|
|
f.Refresh()
|
|
return f
|
|
end
|
|
|
|
UI:RegisterTab("pet", {
|
|
label = function()
|
|
return FW.L.PET_TAB
|
|
end,
|
|
order = 60,
|
|
build = Build,
|
|
onShow = function(f)
|
|
f.Refresh()
|
|
end,
|
|
})
|
|
|
|
SLASH_FREEWOODPET1 = "/fwpet"
|
|
SlashCmdList["FREEWOODPET"] = function()
|
|
UI:Toggle("pet")
|
|
end
|