From fcd9ab23d1c4d90e5d5aa28fde41c20e5f11beec Mon Sep 17 00:00:00 2001 From: Lacustat Date: Thu, 29 Oct 2026 16:47:39 +0100 Subject: [PATCH] 0.1.180: Tooltip-Zusatzinfos in Core und Codex, unabhaengig vom Quest-Modul Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9 --- Core/TooltipCompare.lua | 258 ++++++++++++++++++++++++++++++++++++++ Core/TooltipInfo.lua | 250 ++++++++++++++++++++++++++++++++++++ Freewood-OctoWoW-Core.toc | 4 +- Locales.lua | 20 +++ 4 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 Core/TooltipCompare.lua create mode 100644 Core/TooltipInfo.lua diff --git a/Core/TooltipCompare.lua b/Core/TooltipCompare.lua new file mode 100644 index 0000000..c9011df --- /dev/null +++ b/Core/TooltipCompare.lua @@ -0,0 +1,258 @@ +-- Freewood-Core: Itemvergleich im Tooltip (Shift gedrueckt halten) +-- Ueber einem Item (Tasche, Chat-Link, Haendler, Auktion ...) mit gedruecktem Shift: Daneben erscheint das angelegte Item +-- desselben Platzes, und unten im Tooltip steht, was besser (+) oder schlechter (-) waere, was wegfaellt und was neu dazukommt +-- (auch Equip-/Benutzen-Effekte). Schalter: Tooltip-Einstellung "tipCompare". + +local FW = _G.Freewood +local T = FW and FW.Tooltips +if not FW or not T then + return +end + +local GREEN = { 0.35, 0.9, 0.35 } +local RED = { 0.95, 0.35, 0.35 } +local GREY = { 0.65, 0.65, 0.65 } + +-- Platz-Nummern (Inventar) je Item-Typ; zwei Eintraege = beide Plaetze vergleichen +local SLOTS = { + INVTYPE_HEAD = { 1 }, INVTYPE_NECK = { 2 }, INVTYPE_SHOULDER = { 3 }, INVTYPE_BODY = { 4 }, + INVTYPE_CHEST = { 5 }, INVTYPE_ROBE = { 5 }, INVTYPE_WAIST = { 6 }, INVTYPE_LEGS = { 7 }, + INVTYPE_FEET = { 8 }, INVTYPE_WRIST = { 9 }, INVTYPE_HAND = { 10 }, + INVTYPE_FINGER = { 11, 12 }, INVTYPE_TRINKET = { 13, 14 }, INVTYPE_CLOAK = { 15 }, + INVTYPE_WEAPON = { 16, 17 }, INVTYPE_2HWEAPON = { 16 }, INVTYPE_WEAPONMAINHAND = { 16 }, + INVTYPE_WEAPONOFFHAND = { 17 }, INVTYPE_SHIELD = { 17 }, INVTYPE_HOLDABLE = { 17 }, + INVTYPE_RANGED = { 18 }, INVTYPE_RANGEDRIGHT = { 18 }, INVTYPE_THROWN = { 18 }, INVTYPE_RELIC = { 18 }, + INVTYPE_TABARD = { 19 }, +} + +local function IDOf(link) + return type(link) == "string" and tonumber(link:match("item:(%d+)")) or nil +end + +------------------------------------------------------------------------ +-- Tooltip-Text lesen +------------------------------------------------------------------------ + +local scan +local function Scan() + if not scan then + scan = _G.CreateFrame("GameTooltip", "FreewoodScanTip", _G.UIParent, "GameTooltipTemplate") + scan:SetOwner(_G.UIParent, "ANCHOR_NONE") + end + return scan +end + +-- Zeilen eines Items (Link) oder des angelegten Platzes (slot) als Liste von Texten +local function Lines(link, slot) + local tip = Scan() + tip:ClearLines() + tip:SetOwner(_G.UIParent, "ANCHOR_NONE") + local ok + if slot then ok = pcall(tip.SetInventoryItem, tip, "player", slot) else ok = pcall(tip.SetHyperlink, tip, link) end + local out = {} + if not ok then return out end + for i = 1, tip:NumLines() do + local fs = _G["FreewoodScanTipTextLeft" .. i] + local t = fs and fs:GetText() + if type(t) == "string" and t ~= "" then out[#out + 1] = t end + end + return out +end + +local function Num(s) return tonumber((tostring(s):gsub(",", "."))) end + +-- Werte aus den Zeilen: stats[Name] = Zahl, extra[Name] = Zahl (Ruestung, Block, DPS), effects[Schluessel] = { text, zahl } +local function Parse(lines) + local stats, extra, effects = {}, {}, {} + for i, t in ipairs(lines) do + local clean = t:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "") + if i > 1 then + local sign, n, name = clean:match("^([%+%-])(%d+) (.+)$") + local dps = clean:match("%((%d+[%.,]?%d*) damage per second%)") or clean:match("%((%d+[%.,]?%d*) Schaden pro Sekunde%)") + local armor, aname = clean:match("^(%d+) ([^%d%(%)]+)$") + local prefix = clean:match("^(Equip:)") or clean:match("^(Use:)") or clean:match("^(Chance on hit:)") + or clean:match("^(Anlegen:)") or clean:match("^(Benutzen:)") or clean:match("^(Trefferchance:)") + if prefix then + local key = clean:gsub("%d+[%.,]?%d*", "#") + local first = clean:match("(%d+[%.,]?%d*)") + effects[key] = { text = clean, n = first and Num(first) or nil } + elseif sign and n and name and not name:find("^%(") then + stats[name] = (stats[name] or 0) + (sign == "-" and -1 or 1) * tonumber(n) + elseif dps then + extra["DPS"] = Num(dps) + elseif armor and aname and not clean:find("^%d+ %- %d+") then + extra[aname] = tonumber(armor) + end + end + end + return stats, extra, effects +end + +------------------------------------------------------------------------ +-- Unterschiede +------------------------------------------------------------------------ + +local function Fmt(d) + if math.abs(d - math.floor(d)) < 0.005 then return string.format("%+d", d) end + return string.format("%+.1f", d) +end + +-- Liste { text, farbe } der Unterschiede neu gegenueber alt +local function Diff(newLines, oldLines) + local ns, ne, nf = Parse(newLines) + local os, oe, of = Parse(oldLines) + local out = {} + local function Add(text, d) out[#out + 1] = { text, d >= 0 and GREEN or RED } end + -- Ruestung, Block, DPS + local keys = {} + for k in pairs(ne) do keys[k] = true end + for k in pairs(oe) do keys[k] = true end + local ek = {} + for k in pairs(keys) do ek[#ek + 1] = k end + table.sort(ek) + for _, k in ipairs(ek) do + local d = (ne[k] or 0) - (oe[k] or 0) + if math.abs(d) > 0.004 then Add(string.format("%s %s", Fmt(d), k), d) end + end + -- Werte + local sk = {} + for k in pairs(ns) do sk[k] = true end + for k in pairs(os) do sk[k] = true end + local names = {} + for k in pairs(sk) do names[#names + 1] = k end + table.sort(names) + for _, k in ipairs(names) do + local d = (ns[k] or 0) - (os[k] or 0) + if d ~= 0 then Add(string.format("%s %s", Fmt(d), k), d) end + end + -- Effekte + local ekeys = {} + for k in pairs(nf) do ekeys[#ekeys + 1] = k end + table.sort(ekeys) + for _, k in ipairs(ekeys) do + local n, o = nf[k], of[k] + if not o then + out[#out + 1] = { "+ " .. n.text, GREEN } + elseif n.n and o.n and n.n ~= o.n then + out[#out + 1] = { string.format("(%s) %s", Fmt(n.n - o.n), n.text), n.n > o.n and GREEN or RED } + end + end + local okeys = {} + for k in pairs(of) do okeys[#okeys + 1] = k end + table.sort(okeys) + for _, k in ipairs(okeys) do + if not nf[k] then out[#out + 1] = { "- " .. of[k].text, RED } end + end + return out +end + +------------------------------------------------------------------------ +-- Anzeige +------------------------------------------------------------------------ + +local cmpTips = {} +local function CmpTip(i) + if not cmpTips[i] then + cmpTips[i] = _G.CreateFrame("GameTooltip", "FreewoodCmpTip" .. i, _G.UIParent, "GameTooltipTemplate") + cmpTips[i]:SetFrameStrata("TOOLTIP") + if T.Hook then T.Hook(cmpTips[i]) end + end + return cmpTips[i] +end + +local function HideCmp() + for _, t in pairs(cmpTips) do t:Hide() end +end + +local function Place(tip, anchorTo, onLeft) + tip:ClearAllPoints() + if onLeft then tip:SetPoint("TOPRIGHT", anchorTo, "TOPLEFT", -2, 0) else tip:SetPoint("TOPLEFT", anchorTo, "TOPRIGHT", 2, 0) end +end + +local function Compare(tt, link) + local id = IDOf(link) + local info = id and FW.Util and FW.Util.GetItem and FW.Util.GetItem(id) + local slots = info and info.equipLoc and SLOTS[info.equipLoc] + if not slots then return end + local L = FW.L + local mine = Lines(link) + local shown, worn = 0, 0 + local screenR = _G.UIParent:GetRight() or 1024 + local ttR = tt:GetRight() or 0 + local onLeft = ttR + 260 > screenR -- kein Platz rechts: links daneben + local anchor = tt + for _, slot in ipairs(slots) do + local eq = _G.GetInventoryItemLink and _G.GetInventoryItemLink("player", slot) + local same = false + if eq and IDOf(eq) == id then + local ok, d0 = pcall(Diff, mine, Lines(eq, slot)) + same = (eq == link) or (ok and #d0 == 0) + end + if same then + worn = worn + 1 + if worn == 1 then + tt:AddLine(" ") + tt:AddLine(L.TIP_CMP_WORN, 0.4, 1, 0.4) + end + elseif eq then + shown = shown + 1 + local ct = CmpTip(shown) + ct:SetOwner(tt, "ANCHOR_NONE") + ct:SetInventoryItem("player", slot) + ct:AddLine(L.TIP_CMP_EQUIPPED, GREY[1], GREY[2], GREY[3]) + Place(ct, anchor, onLeft) + ct:Show() + anchor = ct + -- Unterschiede unten im Haupt-Tooltip + local eqName = eq:match("%[(.-)%]") or "?" + local d = Diff(mine, Lines(eq, slot)) + tt:AddLine(" ") + tt:AddLine(string.format(L.TIP_CMP_VS, eqName), 1, 0.82, 0) + if #d == 0 then + tt:AddLine(L.TIP_CMP_SAME, GREY[1], GREY[2], GREY[3]) + else + for _, e in ipairs(d) do tt:AddLine(e[1], e[2][1], e[2][2], e[2][3]) end + end + end + end + if shown == 0 and worn == 0 then + tt:AddLine(L.TIP_CMP_EMPTY, GREY[1], GREY[2], GREY[3]) + end +end + +-- vom Tooltip-Hook (TooltipInfo.lua) bei jedem Item aufgerufen +function T.CompareHook(tt, link) + if tt ~= _G.GameTooltip and tt ~= _G.ItemRefTooltip then return end + HideCmp() + local id = IDOf(link) + local info = id and FW.Util and FW.Util.GetItem and FW.Util.GetItem(id) + local equippable = info and info.equipLoc and SLOTS[info.equipLoc] + tt.fwCmpLink = equippable and link or nil + tt.fwShift = _G.IsShiftKeyDown and _G.IsShiftKeyDown() and true or false + if not equippable or T.Get("tipCompare") ~= true or not tt.fwShift then return end + pcall(Compare, tt, link) +end + +-- Shift waehrend des Ueberfahrens: Tooltip neu aufbauen, wenn sich der Zustand aendert +local watcher = _G.CreateFrame("Frame") +local acc = 0 +watcher:SetScript("OnUpdate", function(_, elapsed) + acc = acc + (elapsed or 0) + if acc < 0.1 then return end + acc = 0 + if T.Get("tipCompare") ~= true then return end + local shift = _G.IsShiftKeyDown and _G.IsShiftKeyDown() and true or false + for _, tt in ipairs({ _G.GameTooltip, _G.ItemRefTooltip }) do + if tt and tt.fwCmpLink and tt:IsShown() and tt.fwShift ~= shift then + local link = tt.fwCmpLink + tt.fwShift = shift -- gegen Schleifen: der Hook setzt es beim Neuaufbau ohnehin neu + pcall(tt.SetHyperlink, tt, link) + end + end +end) + +for _, tt in ipairs({ _G.GameTooltip, _G.ItemRefTooltip }) do + if tt and tt.HookScript then + tt:HookScript("OnHide", function() HideCmp() end) + end +end diff --git a/Core/TooltipInfo.lua b/Core/TooltipInfo.lua new file mode 100644 index 0000000..ea817e3 --- /dev/null +++ b/Core/TooltipInfo.lua @@ -0,0 +1,250 @@ +-- Freewood-Core: Zusatzinfos in Tooltips (Reiter "Einstellungen" -> "Tooltips") +-- tipVendor Haendlerpreis des Items (unabhaengig vom Auktionshaus-Scan) +-- tipQuest Quest-Fortschritt am Gegner oder Objekt unter der Maus +-- tipCompare Shift-Vergleich mit dem angelegten Item (TooltipCompare.lua) +-- Weitere Module haengen Zeilen an Gegner-Tooltips mit FW.Tooltips.AddUnitLine(function(tt, name, npcID) ... end). +-- Jeder Teil ist einzeln abschaltbar. Die Werte stehen in den Core-Einstellungen (FW.settings.tooltips). + +local FW = _G.Freewood +local T = FW and FW.Tooltips +if not FW or not T then + return +end + +local Tip = {} +T.Info = Tip + +local function On(key) return T.Get(key) == true end + +------------------------------------------------------------------------ +-- Hilfen +------------------------------------------------------------------------ + +function Tip.Money(c) + c = math.floor((c or 0) + 0.5) + if _G.GetCoinTextureString then + local ok, text = pcall(_G.GetCoinTextureString, c) + if ok and type(text) == "string" then return text end + end + local g, s, k = math.floor(c / 10000), math.floor(c / 100) % 100, c % 100 + if g > 0 then return string.format("%dg %ds %dc", g, s, k) end + if s > 0 then return string.format("%ds %dc", s, k) end + return string.format("%dc", k) +end + +local function ItemIDFromLink(link) + if type(link) ~= "string" then return nil end + return tonumber(link:match("item:(%d+)")) +end + +-- Stapelgroesse des Items unter der Maus (Taschenfeld), sonst 1. Nur wenn das Feld dasselbe Item enthaelt. +local function HoverCount(link) + local ok, count = pcall(function() + local f = _G.GetMouseFocus and _G.GetMouseFocus() + if not f then return 1 end + local parent = f.GetParent and f:GetParent() + if parent and parent.GetID and f.GetID and _G.GetContainerItemInfo and _G.GetContainerItemLink then + local bag, slot = parent:GetID(), f:GetID() + local l = _G.GetContainerItemLink(bag, slot) + if l and ItemIDFromLink(l) == ItemIDFromLink(link) then + local _, n = _G.GetContainerItemInfo(bag, slot) + if tonumber(n) and n > 1 then return n end + end + end + return 1 + end) + return ok and count or 1 +end + +------------------------------------------------------------------------ +-- Haendlerpreis +------------------------------------------------------------------------ + +local function AddVendor(tt, link) + if not On("tipVendor") or not tt or not tt.AddLine then return end + local id = ItemIDFromLink(link) + if not id then return end + if tt.fwVendID == id then return end + -- beim Haendler zeigt das Spiel den Preis selbst + if _G.MerchantFrame and _G.MerchantFrame.IsShown and _G.MerchantFrame:IsShown() then return end + local info = FW.Util and FW.Util.GetItem and FW.Util.GetItem(id) + local price = info and tonumber(info.sellPrice) or 0 + if price <= 0 then return end + tt.fwVendID = id + Tip.fired.vendor = Tip.fired.vendor + 1 + local L = FW.L + local n = tt == _G.GameTooltip and HoverCount(link) or 1 + if n > 1 then + tt:AddLine(string.format(L.TIP_VENDOR_STACK, Tip.Money(price), n, Tip.Money(price * n)), 1, 0.82, 0) + else + tt:AddLine(string.format(L.TIP_VENDOR, Tip.Money(price)), 1, 0.82, 0) + end +end + +------------------------------------------------------------------------ +-- Quest-Fortschritt am Gegner oder Objekt +------------------------------------------------------------------------ + +local logCache, logAt = nil, -10 +-- { { qid, title, objs = { { text, finished, kind } } } } fuer alle angenommenen Quests (1 s gemerkt) +local function LogObjectives() + local now = _G.GetTime and _G.GetTime() or 0 + if logCache and now - logAt < 1 then return logCache end + local out = {} + local QL = _G.C_QuestLog + local P = T.questProvider -- optional (Quest-Modul): AcceptedSet() und TargetsOf(qid) + if P and P.AcceptedSet and QL and QL.GetQuestObjectives then + for qid in pairs(P.AcceptedSet()) do + local ok, objs = pcall(QL.GetQuestObjectives, qid) + if ok and type(objs) == "table" and #objs > 0 then + local title + if QL.GetTitleForQuestID then + local ok2, t = pcall(QL.GetTitleForQuestID, qid) + if ok2 and type(t) == "string" then title = t end + end + local list = {} + for _, o in ipairs(objs) do + if type(o.text) == "string" and o.text ~= "" then + list[#list + 1] = { text = o.text, finished = o.finished and true or false, kind = o.type } + end + end + if #list > 0 then out[#out + 1] = { qid = qid, title = title or ("#" .. qid), objs = list } end + end + end + elseif _G.GetNumQuestLogEntries and _G.GetQuestLogTitle and _G.GetNumQuestLeaderBoards and _G.GetQuestLogLeaderBoard then + -- ohne Quest-Modul: normales Questlog (Ziele ueber die Questlog-Eintraege, ohne Quest-Nummer) + local n = _G.GetNumQuestLogEntries() or 0 + for i = 1, n do + local title, _, _, isHeader = _G.GetQuestLogTitle(i) + if title and not isHeader then + local list = {} + for j = 1, (_G.GetNumQuestLeaderBoards(i) or 0) do + local text, kind, done = _G.GetQuestLogLeaderBoard(j, i) + if type(text) == "string" and text ~= "" then + list[#list + 1] = { text = text, finished = done and true or false, kind = kind } + end + end + if #list > 0 then out[#out + 1] = { title = title, objs = list } end + end + end + end + table.sort(out, function(a, b) return a.title < b.title end) + logCache, logAt = out, now + return out +end + +-- Quests, die zu diesem Gegner oder Objekt gehoeren, mit den passenden Zielen +local function QuestLinesFor(name, npcID) + local out = {} + local lname = name and name:lower() or nil + local TM = T.questProvider + for _, q in ipairs(LogObjectives()) do + local hits = {} + local isTarget = npcID and q.qid and TM and TM.TargetsOf and TM.TargetsOf(q.qid)[npcID] or false + for _, o in ipairs(q.objs) do + local byName = lname and o.text:lower():find(lname, 1, true) ~= nil + local byDrop = isTarget and o.kind == "item" + if (byName or byDrop) then hits[#hits + 1] = o end + end + if #hits > 0 then out[#out + 1] = { title = q.title, objs = hits } end + end + return out +end + +local function AddQuest(tt, name, npcID) + if not On("tipQuest") or not tt or not tt.AddLine or not name then return end + if tt.fwQuestName == name then return end + local list = QuestLinesFor(name, npcID) + if #list == 0 then return end + tt.fwQuestName = name + Tip.fired.quest = Tip.fired.quest + 1 + for _, e in ipairs(list) do + tt:AddLine(e.title, 1, 0.82, 0) + for _, o in ipairs(e.objs) do + if o.finished then tt:AddLine(" " .. o.text, 0.4, 0.9, 0.4) else tt:AddLine(" " .. o.text, 1, 1, 1) end + end + end +end + +------------------------------------------------------------------------ +-- Anbindung an die Tooltips +------------------------------------------------------------------------ + +T.unitLines = T.unitLines or {} +function T.AddUnitLine(fn) T.unitLines[#T.unitLines + 1] = fn end +T.Money = Tip.Money + +local hooked = {} +Tip.fired = { item = 0, unit = 0, object = 0, vendor = 0, quest = 0 } +local function HookTooltip(tt) + if not tt or hooked[tt] or not tt.HookScript then return end + hooked[tt] = true + tt:HookScript("OnTooltipSetItem", function(self) + local ok, _, link = pcall(self.GetItem, self) + Tip.fired.item = Tip.fired.item + 1 + if ok and link then + pcall(AddVendor, self, link) + if T.CompareHook then pcall(T.CompareHook, self, link) end + self:Show() + end + end) + tt:HookScript("OnTooltipSetUnit", function(self) + local name, unit = self:GetUnit() + Tip.fired.unit = Tip.fired.unit + 1 + if not name then return end + local npcID + if unit then + local g = _G.UnitGUID and _G.UnitGUID(unit) + npcID = g and FW.Util and FW.Util.GetNpcID and FW.Util.GetNpcID(g) or nil + if _G.UnitIsPlayer and _G.UnitIsPlayer(unit) then return end + end + pcall(AddQuest, self, name, npcID) + for _, fn in ipairs(T.unitLines) do pcall(fn, self, name, npcID) end + self:Show() + end) + tt:HookScript("OnTooltipCleared", function(self) + self.fwVendID, self.fwQuestName, self.fwCmpLink, self.fwShift, self.fwDropID = nil, nil, nil, nil, nil + end) +end + +-- Objekte (Truhen, Kraeuter): der Tooltip hat nur den Namen in der ersten Zeile +local function HookObjects(tt) + if not tt or not tt.HookScript then return end + tt:HookScript("OnShow", function(self) + if self:GetUnit() or (self.GetItem and self:GetItem()) or self.fwQuestName then return end + local left = _G.GameTooltipTextLeft1 + local name = left and left:GetText() + if type(name) == "string" and name ~= "" and (_G.UnitExists and not _G.UnitExists("mouseover")) then + Tip.fired.object = Tip.fired.object + 1 + pcall(AddQuest, self, name, nil) + if self.fwQuestName then self:Show() end + end + end) +end + +local function Install() + HookTooltip(_G.GameTooltip) + HookTooltip(_G.ItemRefTooltip) + HookTooltip(_G.ShoppingTooltip1) + HookTooltip(_G.ShoppingTooltip2) + HookObjects(_G.GameTooltip) +end + +Install() +FW:On("QUEST_TIP_CHANGED", function() logCache = nil end, Tip) +FW:On("CODEX_CHANGED", function(_, kind) if kind == "quest" then logCache = nil end end, Tip) +FW:RegisterEvent("QUEST_LOG_UPDATE", function() logCache = nil end, Tip) + +-- /fwtip: Pruefung der Tooltip-Anbindung (wie oft die Hooks gefeuert haben) +_G.SLASH_FREEWOODTIP1 = "/fwtip" +_G.SlashCmdList = _G.SlashCmdList or {} +_G.SlashCmdList["FREEWOODTIP"] = function() + local f = Tip.fired + FW:Print(string.format("Tooltips: Item-Hook %dx, Gegner-Hook %dx, Objekt-Hook %dx; Haendlerzeile %dx, Quest-Zeilen %dx. HookScript: %s, TooltipDataProcessor: %s", + f.item, f.unit, f.object, f.vendor, f.quest, tostring(_G.GameTooltip and _G.GameTooltip.HookScript ~= nil), tostring(_G.TooltipDataProcessor ~= nil))) +end + +-- Optionen (die Codex-abhaengigen meldet das Codex-Modul selbst an) +T.RegisterOption("tipVendor", "TIP_OPT_VENDOR", { order = 10 }) +T.RegisterOption("tipQuest", "TIP_OPT_QUEST", { order = 20 }) +T.RegisterOption("tipCompare", "TIP_OPT_COMPARE", { order = 30, available = function() return T.CompareHook ~= nil end }) diff --git a/Freewood-OctoWoW-Core.toc b/Freewood-OctoWoW-Core.toc index e77d7ef..98d917d 100644 --- a/Freewood-OctoWoW-Core.toc +++ b/Freewood-OctoWoW-Core.toc @@ -3,7 +3,7 @@ ## Notes: Base addon of the Freewood family: data storage, UI kit, export/import and the main window. ## Notes-deDE: Basis-Addon der Freewood-Familie: Datenspeicher, UI-Bausteine, Export/Import und Hauptfenster. ## Author: Lacustat -## Version: 0.1.179 +## Version: 0.1.180 ## SavedVariables: FreewoodDB ## SavedVariablesPerCharacter: FreewoodCharDB @@ -17,5 +17,7 @@ UI\MainFrame.lua UI\MainWindow.lua UI\Tabs.lua Core\Tooltips.lua +Core\TooltipInfo.lua +Core\TooltipCompare.lua UI\Minimap.lua Core\Slash.lua diff --git a/Locales.lua b/Locales.lua index 52f481c..52ac620 100644 --- a/Locales.lua +++ b/Locales.lua @@ -40,6 +40,16 @@ FW.L = setmetatable({}, { }) FW:AddLocale("enUS", { + TIP_OPT_VENDOR = "Show vendor sell price (also without an auction scan)", + TIP_OPT_QUEST = "Show quest progress on creatures and objects (e.g. 3/10)", + TIP_OPT_COMPARE = "Hold Shift to compare with the equipped item", + TIP_VENDOR = "Vendor: %s", + TIP_VENDOR_STACK = "Vendor: %s each (stack of %d: %s)", + TIP_CMP_EQUIPPED = "(currently equipped)", + TIP_CMP_VS = "Compared to %s:", + TIP_CMP_SAME = "No difference in values", + TIP_CMP_EMPTY = "Nothing equipped in this slot", + TIP_CMP_WORN = "You are already wearing this item", TITLE = "Freewood", TAB_OVERVIEW = "Overview", @@ -122,6 +132,16 @@ FW:AddLocale("enUS", { }) FW:AddLocale("deDE", { + TIP_OPT_VENDOR = "Händlerpreis anzeigen (auch ohne Auktionshaus-Scan)", + TIP_OPT_QUEST = "Quest-Fortschritt an Gegnern und Objekten anzeigen (z. B. 3/10)", + TIP_OPT_COMPARE = "Shift gedrückt halten: mit angelegtem Item vergleichen", + TIP_VENDOR = "Händler: %s", + TIP_VENDOR_STACK = "Händler: %s pro Stück (Stapel mit %d: %s)", + TIP_CMP_EQUIPPED = "(aktuell angelegt)", + TIP_CMP_VS = "Gegenüber %s:", + TIP_CMP_SAME = "Kein Unterschied bei den Werten", + TIP_CMP_EMPTY = "In diesem Platz ist nichts angelegt", + TIP_CMP_WORN = "Dieses Item trägst du bereits", TITLE = "Freewood", TAB_OVERVIEW = "Übersicht",