hist = { name = "history", version = "beta-9", initialised = false, SV={}, L={}, me = {}, player = "", tz_offset =0, debug = false } local function log_truncate(max) --Limit log to max for _ = max, (#hist.SV.log-1) do table.remove(hist.SV.log,1) if hist.debug then d("Truncated log. Size now: " .. tostring(#hist.SV.log)) end end end local function log(text) table.insert(hist.SV.log,{["TimeStamp"]=GetTimeStamp(), ["text"] = text, ["Char"] = hist.player, }) end local function get_start () -- get better start date from Achievements -- Check Achievements local earliest_time = 0 local earliest_Achievement for id, ach in pairs(hist.me.ach) do if earliest_time == 0 then earliest_time = ach.time earliest_Achievement = id elseif earliest_time > ach.time then earliest_time = ach.time end end if earliest_time == 0 then -- No Achievements earliest_time = GetTimeStamp() end if hist.me.Created == nil then hist.me.Created = earliest_time elseif hist.me.Created > earliest_time then -- Quest was earlier, then reset to earlier if hist.debug then d("Start Time Reset for " .. hist.player) end log ("Start Time Reset.") hist.me.Created = earliest_time end end local function Achievement(_, name, points, id, link) local description local category_id = GetCategoryInfoFromAchievementId(id) local category_name =GetAchievementCategoryInfo(category_id) _,description,_,_,_,_,_= GetAchievementInfo(id) hist.me.ach[id]={ ["Category_ID"] = category_id, ["Category"] = category_name, ["time"] = GetTimeStamp(), ["points"] = points, ["name"] = zo_strformat(name), ["description"] = zo_strformat(description), ["link"] = link } if hist.debug then d("Achievement Awarded:.. ") d(hist.me.ach[id]) end end local function log_clear() hist.SV.log = {} log("Cleared") end function load_history() -- load up historic Achievements for Category 7 (Dungeons) log("Request to load historic Dungeon Achievements") local name,points,description,completed,adate,atime local cat local count = 0 for i = 1,1400 do name,description,points,_,completed,adate,atime= GetAchievementInfo(i) if completed then cat,_,_ =GetCategoryInfoFromAchievementId(i) -- if cat == 7 then if true then if hist.me.ach[i] == nil then -- log("Added historic achievement " ..i .. " " .. name) local category_id = GetCategoryInfoFromAchievementId(i) local category_name =GetAchievementCategoryInfo(category_id) hist.me.ach[i]={ ["Category_ID"] = category_id, ["Category"] = category_name, ["time"] = (luatz_esodate(adate .. " " .. atime)+ hist.tz_offset), ["points"] = points, ["name"] = zo_strformat(name), ["description"] = zo_strformat(description), ["link"] = GetAchievementLink(i) } count = count + 1 end end end end log("Added " .. tostring(count) .. " historic achievements.") end local function fix() -- fix links etc for any old data local description hist.me.ach_updates = nil log("Request to fix Achievement data") for i,_ in pairs(hist.me.ach) do _, description,_,_,_,_,_= GetAchievementInfo(i) local category_id = GetCategoryInfoFromAchievementId(i) local category_name =GetAchievementCategoryInfo(category_id) hist.me.ach[i]["Category_ID"] = category_id hist.me.ach[i]["Category"] = category_name hist.me.ach[i]["description"] = zo_strformat(description) hist.me.ach[i]["link"] = GetAchievementLink(i) end end local function new_map() local map = zo_strformat("<<C:1>>",GetMapName()) if hist.me.maps[map] == nil then hist.me.maps[map] = {} hist.me.maps[map].firstvisitdate = GetTimeStamp() if hist.debug then d("New Map: " .. map ) end log("New map: " .. map) end return map end local function Activated() hist.me.levels[hist.me.level].time = math.floor(GetSecondsPlayed() /60) local map = new_map() if hist.me.maps[map].visit == nil then hist.me.maps[map].visit = 1 else hist.me.maps[map].visit = hist.me.maps[map].visit +1 end end local function levelup(_, unitTag,_) if unitTag == "player" then local oldlevel = hist.me.level hist.me.level = GetUnitLevel("player") + GetUnitVeteranRank("player") log("Levelled up. Was " .. oldlevel .. " now " .. hist.me.level) hist.me.levels[hist.me.level] = { begin = GetTimeStamp(), time = 0, -- Accumulated time in Minutes Ach_Points = GetEarnedAchievementPoints(), deaths = 0 } local map = new_map() --Update Level data with map if hist.me.levels[hist.me.level].map == nil then hist.me.levels[hist.me.level].map = map local msg = "First Levelup in map " .. map log (msg) if hist.debug then d(msg) end end -- Duplication of info, but easier to work with if hist.me.maps[map].timeslevel == nil then hist.me.maps[map].timeslevel = 1 hist.me.maps[map].firstlevel = hist.me.level else hist.me.maps[map].timeslevel = hist.me.maps[map].timeslevel + 1 end if hist.debug then d("Hist: Leveled:.. ") d(hist.me.level) end else -- not "player" if hist.debug then d("Hist: Got Levelup Event, but not for me") d(unitTag) end end end local function gendertext() if (GetUnitGender("player") == GENDER_MALE) then return "M" end if (GetUnitGender("player") == GENDER_FEMALE) then return "F" end return "U" end local function setup_char() log("Set up: " .. hist.player ) hist.SV.data[hist.player] = {} -- initialise data for current char hist.me = hist.SV.data[hist.player] hist.me.Class = zo_strformat("<<C:1>>",GetUnitClass("player")) hist.me.Race = zo_strformat("<<C:1>>",GetUnitRace("player")) hist.me.Gender = gendertext() hist.me.level = GetUnitLevel("player") + GetUnitVeteranRank("player") hist.me.Alliance = zo_strformat("<<C:1>>",GetAllianceName(GetUnitAlliance("player"))) hist.me.ach={} hist.me.maps={} hist.me.levels = {} hist.me.levels[hist.me.level] = { begin = GetTimeStamp(), time = 0, -- Accumulated time in Minutes Ach_Points = GetEarnedAchievementPoints(), deaths = 0 } -- end of defaults load_history() get_start() end local function Dead() -- Per Level hist.me.levels[hist.me.level].deaths = hist.me.levels[hist.me.level].deaths +1 -- Per Map local map = new_map() --Update map data with Deaths if hist.me.maps[map].deaths == nil then hist.me.maps[map].deaths = 0 hist.me.maps[map].firstdeathlevel = hist.me.level local msg = "First Death in map " .. map log (msg) if hist.debug then d("First Death in map " ..map) end end hist.me.maps[map].deaths = hist.me.maps[map].deaths +1 if hist.me.maps[map].firstdeathdate == nil then hist.me.maps[map].firstdeathdate = GetTimeStamp() end end function hist.Initialise(_, addOnName) if (hist.name ~= addOnName) then return end -- find computed time difference. local now = GetTimeStamp() hist.datestr = GetDateStringFromTimestamp(now) hist.timestr = GetTimeString() hist.luatz_ts = luatz_esodate(hist.datestr .." " .. hist.timestr) hist.tz_offset = now - hist.luatz_ts hist.player = GetUnitName("player") local level = GetUnitLevel("player") + GetUnitVeteranRank("player") -- Load the saved variables hist.SV = ZO_SavedVars:NewAccountWide("History_SV", 1, nil, nil) if hist.SV.log == nil then hist.SV.log = {} elseif hist.SV.log[1]["TimeStamp"] == nil -- Remove Old Log Formats then log_clear() end if (hist.SV.data == nil ) then hist.SV.data = {} log("hist.SV.data created") end if (hist.SV.old == nil ) then hist.SV.old = {} log("hist.SV.old created") end if (hist.SV.start_version == nil ) then hist.SV.start_version = hist.version end hist.SV.this_version = hist.version if hist.SV.data[hist.player] == nil then setup_char() else -- data already there -- but is it for the same char? hist.me = hist.SV.data[hist.player] if hist.me.level == nil then -- fix if doesn't exist hist.me.level = level end if hist.me.levels == nil then hist.me.levels = {} end if hist.me.maps == nil then hist.me.maps = {} end if hist.debug then log("Begin Duplicate tests, Saved -- Calculated" ) -- log("Alliance test: " .. hist.me.Alliance .. " -- " .. zo_strformat("<<C:1>>",GetAllianceName(GetUnitAlliance("player")))) --- log("Race test: " .. hist.me.Race .. " -- " .. zo_strformat("<<C:1>>",GetUnitRace("player"))) -- log("Class test: " .. hist.me.Class .. " -- " .. zo_strformat("<<C:1>>",GetUnitClass("player"))) -- log("Gender test: " .. hist.me.Gender .. " -- " .. gendertext()) log("Level Lower: " .. hist.me.level .. " -- " .. level) end if hist.me.level > level -- hist.me.Alliance ~= zo_strformat(GetAllianceName(GetUnitAlliance("player"))) or -- hist.me.Race ~= zo_strformat("<<C:1>>",GetUnitRace("player")) or -- hist.me.Class ~= zo_strformat("<<C:1>>",GetUnitClass("player")) or -- hist.me["Gender"] ~= gendertext() or then -- must be different with same name local now = GetTimeStamp() log("Duplicate " .. hist.player .. " Detected, moving to old") hist.SV.old[now] = {} -- save old with timestamp hist.SV.old[now][hist.player] = {} hist.SV.old[now][hist.player] = hist.SV.data[hist.player] -- Saved hist.SV.data[hist.player] = nil -- Poof, gone setup_char() -- setup defaults hist.SV.data[hist.player].OverWrite = true end end -- Fix bad map var. if type(hist.me.levels[hist.me.level].map) == "table" then hist.me.levels[hist.me.level].map = nil d("History: Fixed bad map key.") log ("History: Fixed bad map key.") end if hist.debug then log_truncate(50) else log_truncate(20) end hist.SV.lang=GetCVar("language.2") -- For offline use hist.me["LoginTime"] = GetTimeStamp() if hist.me.logins == nil then hist.me.logins = 0 end hist.me.logins = hist.me.logins +1 -- count them. EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_ACHIEVEMENT_AWARDED, Achievement) EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_LEVEL_UPDATE, levelup) EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_VETERAN_RANK_UPDATE, levelup) EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_PLAYER_ACTIVATED, Activated) -- EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_PLAYER_DEACTIVATED, Activated) EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_PLAYER_DEAD, Dead) EVENT_MANAGER:RegisterForEvent(hist.name, EVEN_ZONE_CHANGED, new_map) hist.initialised = true end SLASH_COMMANDS["/histload"] = load_history SLASH_COMMANDS["/histfix"] = fix SLASH_COMMANDS["/histclear"] = log_clear SLASH_COMMANDS["/histstart"] = get_start EVENT_MANAGER:RegisterForEvent(hist.name, EVENT_ADD_ON_LOADED, hist.Initialise)