--[[ Return the timestamp from today's reset (specifically for craft writs) ]] function LeoAltholic.TodayReset() local diff = zo_floor(GetDiffBetweenTimeStamps(GetTimeStamp(), 1538200800) / 86400) return 1538200800 + (diff * 86400) end --[[ Return if the timestamp is after the today's reset. ]] function LeoAltholic.IsAfterReset(timestamp) return timestamp >= LeoAltholic.TodayReset() end --[[ Return if the timestamp is before the today's reset. ]] function LeoAltholic.IsBeforeReset(timestamp) return timestamp <= LeoAltholic.TodayReset() end --[[ Formats a time ]] function LeoAltholic.FormatTime(seconds, short, colorizeCountdown) if short == nil then short = false end local formats = { dhm = SI_TIME_FORMAT_DDHHMM_DESC_SHORT, day = SI_TIME_FORMAT_DAYS, hm = SI_TIME_FORMAT_HHMM_DESC_SHORT, hms = SI_TIME_FORMAT_HHMMSS_DESC_SHORT, hour = SI_TIME_FORMAT_HOURS, ms = SI_TIME_FORMAT_MMSS_DESC_SHORT, m = SI_TIME_FORMAT_MINUTES } if seconds and seconds > 0 then local ss = seconds % 60 local mm = math.floor(seconds / 60) local hh = math.floor(mm / 60) mm = mm % 60 local dn = math.floor(hh / 24) local hhdn = hh - (dn*24) local ssF = string.format("%02d", ss) local mmF = string.format("%02d", mm) local hhF = string.format("%02d", hh) local hhdnF = string.format("%02d", hhdn) local result = '' if dn > 0 then if short then result = ZO_CachedStrFormat(GetString(formats.day), dn) .." "..ZO_CachedStrFormat(GetString(formats.hour), hhdnF) else result = ZO_CachedStrFormat(GetString(formats.dhm), dn, hhdnF, mmF) end elseif hh > 0 then if short then result = ZO_CachedStrFormat(GetString(formats.hm), hhF, mmF) else result = ZO_CachedStrFormat(GetString(formats.hms), hhF, mmF, ssF) end elseif mm >= 0 then result = ZO_CachedStrFormat(GetString(formats.ms), mmF, ssF) end if colorizeCountdown == true then if seconds < 3600 then result = '|c'..LeoAltholic.color.hex.red..result..'|r' elseif seconds < 86400 then result = '|c'..LeoAltholic.color.hex.yellow..result..'|r' elseif seconds < 604800 then result = '|c'..LeoAltholic.color.hex.white..result..'|r' else result = '|c'..LeoAltholic.color.hex.green..result..'|r' end end return result else return '|cFF4020'..ZO_CachedStrFormat(GetString(formats.m), 0)..'|r' end end --[[ Return if the craft is done for the day for the charName (if not specified, the current character is used) ]] function LeoAltholic.IsWritDoneToday(craft, charName) if not charName then charName = LeoAltholic.CharName end local char = LeoAltholic.globalData.CharList[charName] if not char then return end for _, writ in pairs(char.quests.writs) do if craft == writ.craft then return writ.lastDone ~= nil and LeoAltholic.IsAfterReset(writ.lastDone) end end return false end function LeoAltholic.IsWritStartedToday(craft, charName) if not charName then charName = LeoAltholic.CharName end local char = LeoAltholic.globalData.CharList[charName] if not char then return end for _, writ in pairs(char.quests.writs) do if craft == writ.craft then return writ.lastStarted ~= nil and LeoAltholic.IsAfterReset(writ.lastStarted) end end return false end function LeoAltholic.HasStillResearchFor(craft, charName) if not charName then charName = LeoAltholic.CharName end local char = LeoAltholic.globalData.CharList[charName] if not char then return end for line = 1, GetNumSmithingResearchLines(craft) do local _, _, numTraits = GetSmithingResearchLineInfo(craft, line) for trait = 1, numTraits do if not char.research.done[craft][line][trait] then return true end end end end function LeoAltholic.CharKnowsTrait(craft, line, trait, charName) if not charName then charName = LeoAltholic.CharName end local char = LeoAltholic.globalData.CharList[charName] if not char then return end if not char.research.done then return false end if not char.research.done[craft] then return false end if not char.research.done[craft][line] then return false end if not char.research.done[craft][line][trait] then return false end return true end function LeoAltholic.GetNumTraitKnownPerLine(charName) local levels = {} for _,craft in pairs(LeoAltholic.craftResearch) do levels[craft] = {} for line = 1, GetNumSmithingResearchLines(craft) do levels[craft][line] = 0 local _, _, numTraits = GetSmithingResearchLineInfo(craft, line) for trait = 1, numTraits do if LeoAltholic.CharKnowsTrait(craft, line, trait, charName) then levels[craft][line] = levels[craft][line] + 1 end end end end return levels end --[[ Return the number of researching in progress, the total and the time of the first one to be completed (can be 0 or negative, indicating it's done) ]] function LeoAltholic.GetResearchCounters(craft, charName) if not charName then charName = LeoAltholic.CharName end local char = LeoAltholic.globalData.CharList[charName] if not char then return end local lowest = -1 if #char.research.doing[craft] > 0 then local research = char.research.doing[craft][1] lowest = research.doneAt end return #char.research.doing[craft], char.research.done[craft].max, lowest end local function copy(obj, seen) return obj -- major performance boost ... --[[if type(obj) ~= 'table' then return obj end if seen and seen[obj] then return seen[obj] end local s = seen or {} local res = setmetatable({}, getmetatable(obj)) s[obj] = res for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end return res]] end --[[ Return a copy of the complete table with all tracked chars. Structure soon. ]] function LeoAltholic.ExportCharacters(forceUpdate) LeoAltholic.GetCharacters(forceUpdate) local chars = copy(LeoAltholic.charList) return chars end --[[ Return all info on 1 char by name ]] function LeoAltholic.GetCharByName(name, forceUpdate) local chars = LeoAltholic.ExportCharacters(forceUpdate) for k, v in pairs(chars) do if v.bio.name == name then return v end end return nil end --[[ Return all info on the current char ]] function LeoAltholic.GetMyself() local myself = copy(LeoAltholic.globalData.CharList[LeoAltholic.CharName]) return myself end --[[ Return if a specific tab is visible ]] function LeoAltholic.IsTabVisible(tab) return LeoAltholic.hidden == false and LeoAltholic.globalData.activeTab == tab end