diff --git a/Codex.lua b/Codex.lua index a8d4c5b..c79904f 100644 --- a/Codex.lua +++ b/Codex.lua @@ -4471,6 +4471,9 @@ function Codex:OnEnable() if self.Lookup then self.Lookup:Start() end + if self.Snapshot then + self.Snapshot:Start() + end end function Codex:OnDisable() @@ -4486,6 +4489,9 @@ function Codex:OnDisable() if self.Time then self.Time:Stop() end + if self.Snapshot then + self.Snapshot:Stop() + end if self.Roles then self.Roles:Stop() end diff --git a/CodexSnapshot.lua b/CodexSnapshot.lua new file mode 100644 index 0000000..dab59f0 --- /dev/null +++ b/CodexSnapshot.lua @@ -0,0 +1,153 @@ +-- Freewood-OctoWoW-Codex: Charakter-Schnappschuss +-- Holt die Liste der erledigten Quests vom Server (Chat-Befehl ".queststatuses", Antwort als Addon-Nachricht "TWQUEST") +-- und traegt sie in die gemerkten Abgaben des Charakters ein. Dadurch stimmt der Filter "erledigt" im Codex auch fuer Charaktere, +-- die schon lange spielen. Zusaetzlich entsteht je Charakter eine Datei (SavedVariablesPerCharacter: FreewoodSnapshot) +-- mit Name, Klasse, Stufe, EP und allen erledigten Quest-IDs, zum Hochladen im Levelplaner. +-- Im Spiel ungeprueft: Verhalten bei sehr langen Listen (Stufe 60) und ob der Server die Liste ohne Befehl schickt. + +local ADDON, NS = ... + +local FW = _G.Freewood +local Codex = NS and NS.Codex +if not FW or not Codex then + return +end + +local Snap = {} +NS.Snapshot = Snap +Codex.Snapshot = Snap + +local PREFIX = "TWQUEST" +local ASK_DELAY = 12 -- Sekunden nach dem Start, bis der Befehl gesendet wird +local MIN_GAP = 60 -- Mindestabstand zwischen zwei Abfragen +local WAIT = 20 -- so lange gilt eine Antwort als Antwort auf unsere Abfrage + +local lastAsk, started = 0, false + +local function Now() + return GetTime and GetTime() or time() +end + +local function Say(msg) + if FW.Print then FW:Print(msg) elseif _G.DEFAULT_CHAT_FRAME then _G.DEFAULT_CHAT_FRAME:AddMessage("|cffffd100Freewood|r " .. msg) end +end + +local function Iter(s, pat) + return (string.gmatch or string.gfind)(s, pat) +end + +local function Turned() + local key = Codex.Trust and Codex.Trust.SelfKey and Codex.Trust.SelfKey() or nil + local db = Codex.db + if not db or not key then return nil end + db.turned = db.turned or {} + db.turned[key] = db.turned[key] or {} + return db.turned[key] +end + +-- Schnappschuss schreiben (Stufe und EP immer frisch, erledigte Quests aus den gemerkten Abgaben) +function Snap:Write() + if not _G.UnitName then return end + local t = Turned() + local ids = {} + for id, v in pairs(t or {}) do + if v and tonumber(id) then table.insert(ids, tonumber(id)) end + end + table.sort(ids) + local parts = {} + for i = 1, table.getn(ids) do parts[i] = string.format("%.0f", ids[i]) end + local _, classToken = UnitClass("player") + local _, raceToken = UnitRace("player") + local old = _G.FreewoodSnapshot + _G.FreewoodSnapshot = { + format = 1, + name = UnitName("player"), + realm = GetRealmName and GetRealmName() or "", + class = classToken, + race = raceToken, + classId = Codex.PlayerClassID and Codex.PlayerClassID() or nil, + raceId = Codex.PlayerRaceID and Codex.PlayerRaceID() or nil, + level = UnitLevel("player"), + xp = UnitXP and UnitXP("player") or 0, + xpMax = UnitXPMax and UnitXPMax("player") or 0, + saved = time(), + serverList = old and old.serverList or nil, -- Zeitpunkt der letzten Serverantwort + count = table.getn(ids), + done = table.concat(parts, " "), + } +end + +-- Abfrage senden (hoechstens einmal je MIN_GAP) +function Snap:Ask(force) + local now = Now() + if not force and lastAsk > 0 and now - lastAsk < MIN_GAP then return false end + if not SendChatMessage then return false end + lastAsk = now + SendChatMessage(".queststatuses", "SAY") + return true +end + +function Snap:OnAddon(prefix, text, channel, sender) + if prefix ~= PREFIX or type(text) ~= "string" then return end + local t = Turned() + if not t then return end + local n, new = 0, 0 + for num in Iter(text, "%d+") do + local id = tonumber(num) + if id and id > 0 then + n = n + 1 + if not t[id] then t[id] = true new = new + 1 end + end + end + if n == 0 then return end + Snap.stats = { total = n, new = new, at = time() } + if new > 0 then + Codex.chainRev = (Codex.chainRev or 0) + 1 + if FW.Fire then FW:Fire("QUEST_TURNED_IN_LOCAL", 0) end + end + self:Write() + if _G.FreewoodSnapshot then _G.FreewoodSnapshot.serverList = time() end + if Snap.manual or (Now() - lastAsk) < WAIT then + Say(string.format(FW.L.CODEX_SNAP_GOT, n, new)) + Snap.manual = nil + end +end + +function Snap:OnLogout() + self:Write() +end + +function Snap:OnLevel() + self:Write() +end + +function Snap:Start() + if started then return end + started = true + FW:RegisterEvent("CHAT_MSG_ADDON", self.OnAddon, self) + FW:RegisterEvent("PLAYER_LOGOUT", self.OnLogout, self) + FW:RegisterEvent("PLAYER_LEVEL_UP", self.OnLevel, self) + if C_Timer and C_Timer.After then + C_Timer.After(ASK_DELAY, function() + Snap:Write() + Snap:Ask(false) + end) + end +end + +function Snap:Stop() + started = false + FW:UnregisterEvent("CHAT_MSG_ADDON", self) + FW:UnregisterEvent("PLAYER_LOGOUT", self) + FW:UnregisterEvent("PLAYER_LEVEL_UP", self) +end + +_G.SLASH_FWSNAP1 = "/fwsnap" +_G.SlashCmdList = _G.SlashCmdList or {} +_G.SlashCmdList["FWSNAP"] = function(msg) + Snap:Write() + Snap.manual = true + Snap:Ask(true) + local s = _G.FreewoodSnapshot + Say(string.format(FW.L.CODEX_SNAP_ASK, s and s.count or 0)) +end diff --git a/Freewood-OctoWoW-Codex.toc b/Freewood-OctoWoW-Codex.toc index 0dd4dc8..86d3703 100644 --- a/Freewood-OctoWoW-Codex.toc +++ b/Freewood-OctoWoW-Codex.toc @@ -3,8 +3,9 @@ ## Notes: Learns quests, creatures and drops while you play: who gives and takes a quest, rewards, objectives, drop chances. ## Notes-deDE: Lernt beim Spielen Quests, Kreaturen und Beute: wer eine Quest vergibt und annimmt, Belohnungen, Ziele, Drop-Chancen. ## Author: Lacustat -## Version: 0.1.212 +## Version: 0.1.213 ## Dependencies: Freewood-OctoWoW-Core +## SavedVariablesPerCharacter: FreewoodSnapshot ## OptionalDeps: Freewood-OctoWoW-CodexData, Freewood-OctoWoW-ForeverData Locales.lua @@ -16,6 +17,7 @@ CodexSeed.lua CodexRoles.lua CodexRecipes.lua CodexTime.lua +CodexSnapshot.lua CodexShare.lua CodexZones.lua CodexPath.lua diff --git a/Locales.lua b/Locales.lua index 7ed1458..e198cb3 100644 --- a/Locales.lua +++ b/Locales.lua @@ -7,6 +7,8 @@ if not FW then end FW:AddLocale("enUS", { + CODEX_SNAP_GOT = "Server list of completed quests received: %d quests, %d new. Snapshot saved (file FreewoodSnapshot, written at logout or /reload).", + CODEX_SNAP_ASK = "Asking the server for completed quests (known so far: %d). Reply follows in a moment.", CODEX_OPT_TIPDROPV = "Creature tooltip: average loot value (vendor)", CODEX_OPT_TIPDROPA = "Creature tooltip: average loot value (auction, needs Auction module)", CODEX_TIP_DROP_VENDOR = "Avg. loot (vendor): %s", @@ -564,6 +566,8 @@ FW:AddLocale("enUS", { }) FW:AddLocale("deDE", { + CODEX_SNAP_GOT = "Serverliste der erledigten Quests erhalten: %d Quests, davon %d neu. Schnappschuss gespeichert (Datei FreewoodSnapshot, geschrieben beim Abmelden oder /reload).", + CODEX_SNAP_ASK = "Frage beim Server die erledigten Quests ab (bisher bekannt: %d). Die Antwort kommt gleich.", CODEX_OPT_TIPDROPV = "Gegner-Tooltip: Ø Beutewert (Händler)", CODEX_OPT_TIPDROPA = "Gegner-Tooltip: Ø Beutewert (Auktion, braucht Auktionsmodul)", CODEX_TIP_DROP_VENDOR = "Ø Beute (Händler): %s",