This is a working version of ImprovedTitleizer that works with my current version of LibScrollableMenu
Search for "Added:" (no quotes) to find changes I made.
It makes use of Icons and the "new" flag.
I have not spent enough time with this to know what all needs to be done with the "new" flag but I posted my ideas on that in line .
--[[
==============================================
Addon header information
==============================================
--]]
local ImprovedTitleizer = {}
ImprovedTitleizer.Name = "ImprovedTitleizer"
ImprovedTitleizer.DisplayName = "ImprovedTitleizer"
ImprovedTitleizer.Author = "tomstock"
ImprovedTitleizer.Version = "1.5"
ImprovedTitleizer.Debug = true
ImprovedTitleizer.logger = nil
--[[
==============================================
Setup LibDebugLogger as an optional dependency
==============================================
--]]
if LibDebugLogger and ImprovedTitleizer.Debug then
ImprovedTitleizer.logger = LibDebugLogger.Create(ImprovedTitleizer.Name)
ImprovedTitleizer.logger:Info("Loaded logger")
end
local AVA_SORT_BY_RANK =
{
["name"] = {},
["rank"] = {tiebreaker = "name", isNumeric = true},
}
--[[
==============================================
Utility Functions
spairs - For sorting keys in an array
==============================================
--]]
local function spairs(t, order)
-- collect the keys
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
--[[
==============================================
Manual Categorization
--ID = Achievement ID
--Rank = Sort override
==============================================
--]]
local AchievmentIdsCategories =
{
{
Name=GetString(SI_AVA_MENU_ALLIANCE_WAR_GROUP), --Alliance War
Entries=
{
{ID=92,Rank=1}, --Volunteer --Alliance War Volunteer
{ID=93,Rank=2}, --Recruit --Alliance War Recruit
{ID=94,Rank=3}, --Tyro --Alliance War Tyro
{ID=95,Rank=4}, --Legionary --Alliance War Legionary
{ID=96,Rank=5}, --Veteran --Alliance War Veteran
{ID=97,Rank=6}, --Corporal --Alliance War Corporal
{ID=98,Rank=7}, --Sergeant --Alliance War Sergeant
{ID=706,Rank=8}, --First Sergeant --Alliance War First Sergeant
{ID=99,Rank=9}, --Lieutenant --Alliance War Lieutenant
{ID=100,Rank=10}, --Captain --Alliance War Captain
{ID=101,Rank=11}, --Major --Alliance War Major
{ID=102,Rank=12}, --Centurion --Alliance War Centurion
{ID=103,Rank=13}, --Colonel --Alliance War Colonel
{ID=104,Rank=14}, --Tribune --Alliance War Tribune
{ID=105,Rank=15}, --Brigadier --Alliance War Brigadier
{ID=106,Rank=16}, --Prefect --Alliance War Prefect
{ID=107,Rank=17}, --Praetorian --Alliance War Praetorian
{ID=108,Rank=18}, --Palatine --Alliance War Palatine
{ID=109,Rank=19}, --August Palatine --Alliance War August Palatine
{ID=110,Rank=20}, --Legate --Alliance War Legate
{ID=111,Rank=21}, --General --Alliance War General
{ID=112,Rank=22}, --Warlord --Alliance War Warlord
{ID=113,Rank=23}, --Grand Warlord --Alliance War Grand Warlord
{ID=114,Rank=24}, --Overlord --Alliance War Overlord
{ID=705,Rank=25}, --Grand Overlord --Alliance War Grand Overlord
},
},
{
Name="Housing", --Housing
Entries=
{
{ID=1727}, --Clan Father --Clan <<player{Father/Mother}>>
{ID=1728}, --Lord --<<player{Lord/Lady}>>
{ID=1729}, --Councilor --Councilor
{ID=1730}, --Count --<<player{Count/Countess}>>
},
},
{
Name="Arena",
Entries=
{
{ID=992}, --Dragonstar Arena Champion --Dragonstar Arena Champion
{ID=1140}, --Boethiah's Scythe --Dragonstar Arena Conqueror
{ID=1304}, --Maelstrom Arena Champion --Maelstrom Arena Champion
{ID=1305}, --Stormproof --Maelstrom Arena Conqueror
{ID=1330}, --The Flawless Conqueror --Maelstrom Arena: Perfect Run
{ID=2362}, --Blackrose Condemner --Blackrose Prison Vanquisher
{ID=2363}, --Blackrose Executioner --Blackrose Prison Conqueror
{ID=2368}, --The Unchained --God of the Gauntlet
{ID=2908}, --Spiritblood Champion --Vateshran Hollows Conqueror
{ID=2912}, --Spirit Slayer --The Vateshran's Chosen
{ID=2913}, --of the Undying Song --Hero of the Unending Song
}
},
{
Name=GetString(SI_ACTIVITY_FINDER_CATEGORY_BATTLEGROUNDS), --Battlegrounds
Entries=
{
{ID=1895}, --Bloodletter --Pit Hero
{ID=1898}, --Relic Hunter --Grand Relic Hunter
{ID=1901}, --Relic Guardian --Grand Relic Guardian
{ID=1904}, --Standard-Bearer --Grand Standard-Bearer
{ID=1910}, --Conquering Hero --Conquering Hero
{ID=1913}, --Grand Champion --Grand Champion
{ID=1919}, --Relic Runner --Triple Threat
{ID=1954}, --Chaos Guardian --Chaos Guardian
{ID=1955}, --Chaos Champion --Chaos Champion
{ID=1907}, --Standard-Guardian --Grand Standard-Guardian
{ID=1915}, --Battleground Butcher --Battleground Butcher
{ID=1916}, --Tactician --Tactician
{ID=1918}, --Paragon --Paragon
{ID=1921}, --The Merciless --Quadruple Kill
{ID=1956}, --Chaos Keeper --Walk It Off
}
},
{
Name=GetString(SI_DUNGEON_FINDER_GENERAL_ACTIVITY_DESCRIPTOR), --Dungeon
Entries=
{
{ID=1159}, --Deadlands Adept --Deadlands Savvy
{ID=1538}, --Hist-Shadow --Shadows of the Hist Delver
{ID=1691}, --Bane of Beastmen --Bloodroot Forge Conqueror
{ID=1696}, --Forge Breaker --Tempered Tantrum
{ID=1699}, --Jarl Maker --Falkreath Hold Conqueror
{ID=1704}, --Thane of Falkreath --Taking the Bull by the Horns
{ID=1960}, --Blackmarrow's Bane --Fang Lair Conqueror
{ID=1965}, --Dovahkriid --Let Bygones Be Bygones
{ID=1976}, --Peak Scaler --Scalecaller Peak Conqueror
{ID=1981}, --Plague of Peryite --Breaker of Spells
{ID=2153}, --Silver Knight --Moon Hunter Keep Conqueror
{ID=2154}, --Alpha Predator --The Alpha Predator
{ID=2163}, --Huntmaster --March of Sacrifices Conqueror
{ID=2164}, --Hircine's Champion --Hircine's Champion
{ID=2266}, --Frozen Treasure Seeker --Frostvault Challenger
{ID=2275}, --Purified Devastator --Depths of Malatar Challenger
{ID=2417}, --Hollowfang Exsanguinator --Drunk on Power
{ID=2421}, --Chevalier --Moongrave Fane Challenger
{ID=2427}, --Z'en's Redeemer --Selene's Savior
{ID=2430}, --Guardian of the Green --Lair of Maarselok Challenger
{ID=2541}, --Witch Hunter --Cold-Blooded Killer
{ID=2546}, --Storm Foe --No Rest for the Wicked
{ID=2551}, --Sanctifier --Skull Smasher
{ID=2555}, --Bonecaller's Bane --In Defiance of Death
{ID=2701}, --True Genius --True Genius
{ID=2706}, --The Inedible --Thorn Remover
{ID=2710}, --Bane of Thorns --Bane of Thorns
{ID=2751}, --Dark Delver --Companion of Lyris Titanborn
{ID=2755}, --Pinnacle of Evolution --Triple Checked
{ID=2833}, --Flamechaser --Snuffed Out
{ID=2838}, --Ardent Bibliophile --Ardent Bibliophile
{ID=2843}, --Spark of Vengeance --Schemes Disrupted
{ID=2847}, --Subterranean Smasher --Subterranean Smasher
{ID=3018}, --Seeker of Artifacts --Prior Offenses
{ID=3023}, --of the Silver Rose --Bastion Breaker
{ID=3028}, --Incarnate --Unshaken
{ID=3032}, --The Dreaded --Battlespire's Best
{ID=3111}, --Coral Caretaker --Land, Air, and Sea Supremacy
{ID=3120}, --Privateer --Zero Regrets
{ID=3153}, --Gryphon Handler --Superior Pedigree
{ID=3154}, --Tide Turner --Shove Off
{ID=3224}, --Shipwright --Sans Spirit Support
{ID=3226}, --Aerie Ascender --Tentacless Triumph
{ID=3377}, --Earthen Root Avenger -- Earthen Root Avenger
{ID=3381}, --Invaders' Bane -- Invaders' Bane
{ID=3396}, --Breathless -- Breathless
{ID=3400}, --Fist of Tava -- Fist of Tava
{ID=3470}, --Telvanni Tormentor --Scourge of Sunnar
{ID=3474}, --Temporal Tempes --Temporal Tempest
{ID=3525}, --Earthen Root Champion --Earthen Root Enclave Champion
{ID=3526}, --Graven Deep Champion --Graven Deep Champion
{ID=3531}, --Inflammable --Weaver's Bane
{ID=3535}, --Magnastylus in the Making --Curator's Champion
{ID=3617}, --Bal Sunnar Champion --Shadow Blessed
{ID=3618}, --Scrivener's Hall Champion --Scribe Savior
}
},
{
Name=GetString(SI_QUESTTYPE12), --Holiday Event
Entries={
{ID=1546}, --Sun's Dusk Reaper --An Unsparing Harvest
{ID=1677}, --Magnanimous --Glory of Magnus
{ID=1716}, --Lord of Misrule --<<player{Lord/Lady}>> of Misrule
{ID=1723}, --Royal Jester --Royal Jester
{ID=1892}, --Star-Made Knight --Star-Made Knight
{ID=2453}, --Tin Soldier --The Upper Crust
{ID=2458}, --Empieror --Messy Business
{ID=2587}, --Witch --Wicked Writ Witch
}
},
{
Name=GetString(SI_QUESTTYPE17), --Tales of Tribute
Entries={
{ID=3349,Rank=1}, --Roister's Club Initiate --Roister's Club Initiate
{ID=3350,Rank=2}, --Roister's Club Trainee --Roister's Club Trainee
{ID=3351,Rank=3}, --Roister's Club Novice --Roister's Club Novice
{ID=3352,Rank=4}, --Roister's Club Regular --Roister's Club Regular
{ID=3353,Rank=5}, --Roister's Club Adept --Roister's Club Adept
{ID=3354,Rank=6}, --Roister's Club Expert --Roister's Club Expert
{ID=3355,Rank=7}, --Roister's Club Veteran --Roister's Club Veteran
{ID=3356,Rank=8}, --Roister's Club Master --Roister's Club Master
{ID=3342,Rank=9}, --Cardsharp --Ebony Roister
{ID=3340,Rank=10}, --Club Contender --Quicksilver Roister
{ID=3339,Rank=11}, --High-Stakes Gambler --Voidsteel Roister
{ID=3338,Rank=12}, --Game-Baron --Rubedite Roister
{ID=3325,Rank=13}, --Club Virtuoso --Tribute Tactician
}
},
{
Name=GetString(SI_GUILDACTIVITYATTRIBUTEVALUE6), --Questing
Entries={
{ID=61}, --Covenant Hero --Hero of the Daggerfall Covenant
{ID=617}, --Pact Hero --Hero of the Ebonheart Pact
{ID=618}, --Dominion Hero --Hero of the Aldmeri Dominion
{ID=628}, --Tamriel Hero --Tamriel Expert Adventurer
{ID=1248}, --Hero of Wrothgar --Hero of Wrothgar
{ID=1260}, --Kingmaker --Kingmaker
{ID=1868}, --Savior of Morrowind --Savior of Morrowind
{ID=2049}, --Hero of Clockwork City --Hero of Clockwork City
{ID=2193}, --Savior of Summerset --Savior of Summerset
{ID=2210}, --Mystic --Psijic Sage
{ID=2325}, --Murkmire Prepper --Cyrodilic Collections Champion
{ID=2331}, --Hero of Murkmire --Hero of Murkmire
{ID=2509}, --Savior of Elsweyr --Savior of Elsweyr
{ID=2604}, --Guardian of Elsweyr --Bright Moons Over Elsweyr
{ID=2623}, --Hero of the Dragonguard --Hero of the Dragonguard
{ID=2712}, --Savior of Western Skyrim --Savior of Western Skyrim
{ID=2935}, --Champion of Markarth --Protector of Markarth
{ID=2939}, --Hero of Skyrim --A Bridge Between Kingdoms
{ID=2941}, --Guardian of the Reach --Savior of the Reach
{ID=3047}, --Savior of Blackwood --Savior of Blackwood
{ID=3145}, --Hero of Fargrave --Hero of Fargrave
{ID=3214}, --Cataclyst Breaker --Hopeful Rescuer
{ID=3217}, --Champion of the Deadlands --Eternal Optimist
{ID=3218}, --Hope's Hero --Friend to the Kalmur
{ID=3219}, --The Wretched --Spire Sleuth
{ID=3271}, --Savior of High Isle --Savior of High Isle
{ID=3501}, --Guardian of Galen --Savior of Galen
{ID=3512}, --Sower's Savior --Firesong Extinguisher
{ID=3556}, --Eye of the Queen --Buried Bequest
{ID=3671}, --Champion of Apocrypha -- Fate's Chosen
{ID=3674}, --Hero of Necrom --Hero of Necrom
}
},
{
Name=GetString(SI_GAMEPAD_SKILLS_SKY_SHARDS), --Skyshards
Entries={
{ID=2516}, --Craglorn Skyshard Hunter
{ID=2513}, --Dominion Skyshard Hunter
{ID=2514}, --Covenant Skyshard Hunter
{ID=2515}, --Pact Skyshard Hunter
{ID=2517}, --Cyrodiil Skyshard Hunter
}
},
{
Name=GetString(SI_BINDING_NAME_TOGGLE_SKILLS), --Skills
Entries={
{ID=494}, --Master Angler --Master Fisher
{ID=702}, --Master Wizard --Arch-Mage
{ID=703}, --Fighters Guild Victor --Fighters Guild Veteran
{ID=1383}, --Master Thief --A Cutpurse Above
{ID=2043}, --Undaunted --Truly Undaunted
{ID=2227}, --Grand Master Crafter --Grand Master Crafter
{ID=2230}, --Style Master --True Style Master
{ID=2523}, --Scoundrel --Thieves Guild Skill Master
{ID=2524}, --Assassin --Dark Brotherhood Skill Master
{ID=2588}, --Locksmith --Legerdemain Skill Master
{ID=2589}, --Siegemaster --Alliance War Skill Master
{ID=2638}, --Soul Mage Maven --Soul Magic Skill Master
{ID=2786}, --Sagacious Seer --Master of the Eye
{ID=2792}, --Expert Excavator --Master of the Spade
{ID=2805}, --Master Historian --Master Antiquarian
}
},
{
Name=GetString(SI_RAIDCATEGORY0), --Trials
Entries={
{ID=1391}, --Dro-m'Athra Destroyer --Maw of Lorkhaj: Moons' Champion
{ID=1462}, --Ophidian Overlord --Sanctum Ophidia Conqueror
{ID=1474}, --Shehai Shatterer --Hel Ra Citadel Conqueror
{ID=1503}, --Mageslayer --Aetherian Archive Conqueror
{ID=1808}, --Clockwork Confounder --Halls of Fabrication Completed
{ID=1810}, --Divayth Fyr's Coadjutor --Halls of Fabrication Conqueror
{ID=1836}, --The Dynamo --Dynamo
{ID=1837}, --Disassembly General --Stress Tested
{ID=1838}, --Tick-Tock Tormentor --Like Clockwork
{ID=2075}, --Immortal Redeemer --Asylum Sanctorium Redeemer
{ID=2076}, --Orderly --Asylum Sanctorium Completed
{ID=2077}, --Assistant Alienist --Asylum Sanctorium Conqueror
{ID=2079}, --Voice of Reason --Asylum Sanctorium Vanquisher
{ID=2087}, --Saintly Savior --Perfect Purification
{ID=2131}, --Cloudrest Hero --Cloudrest Completed
{ID=2133}, --Shadow Breaker --Cloudrest Conqueror
{ID=2136}, --Bringer of Light --Cloudrest Vanquisher
{ID=2139}, --Gryphon Heart --The Path to Alaxon
{ID=2140}, --Welkynar Liberator --Cloudrest Savior
{ID=2433}, --Sunspire Ascendant --Sunspire Completed
{ID=2435}, --Sunspire Saint --Sunspire Conqueror
{ID=2466}, --Extinguisher of Flames --Sunspire Vanquisher
{ID=2467}, --Godslayer --Godslayer of Sunspire
{ID=2468}, --Hand of Alkosh --Sunspire Dragonbreak
{ID=2732}, --Kyne's Chosen --Kyne's Aegis Completed
{ID=2734}, --Kyne's Will --Kyne's Aegis Conqueror
{ID=2739}, --Shield of the North --Kyne's Aegis Vanquisher
{ID=2740}, --Kyne's Wrath --Stainless Siege-breaker
{ID=2746}, --Dawnbringer --Kyne's Deliverance
{ID=2985}, --Defender of Rockgrove --Rockgrove Completed
{ID=2987}, --Ca-Uxith Warrior --Rockgrove Conqueror
{ID=3003}, --Planesbreaker --Soul Savior
{ID=3004}, --Daedric Bane --Xalvakka's Bane
{ID=3007}, --Xalvakka's Scourge --Rockgrove Vanquisher
{ID=3242}, --Dreadsails' Scourge --Dreadsail Reef Vanquisher
{ID=3244}, --Seaborne Slayer --Dreadsail Reef Conqueror
{ID=3248}, --Soul of the Squall --Fleet Queen's Foil
{ID=3249}, --Swashbuckler Supreme --Swashbuckler Supreme
{ID=3252}, --Hurricane Herald --Master Marine
{ID=3558}, --Sanity's Edge Vanquisher -- Sanity's Scourge
{ID=3560}, --Sanity's Edge Conqueror -- Sanity's Warrior
{ID=3564}, --Master of the Mind -- Dream Master
{ID=3565}, --Sane and Clearheaded -- Mindmender
{ID=3568}, --Tenacious Dreamer -- Tenacious Dreamer
}
}
}
--[[
==============================================
Used function documentation
==============================================
--]]
local AllTitles={}
--{TitleID=id, CategoryID=categoryId, CategoryName=categoryName,SubCategoryID=subCategory,SubCategoryName=subCategoryName,HasTitle=hasTitle}
local TitleMenu = {}
local GetNumAchievementCategories = GetNumAchievementCategories
--Usage: local numAchieveCategory = GetNumAchievementCategories()
local GetAchievementCategoryInfo = GetAchievementCategoryInfo
--Usage: local categoryName, numSubCategories, numAchievements, earnedPoints, totalPoints = GetAchievementCategoryInfo(categoryIndex)
local GetFirstAchievementInLine = GetFirstAchievementInLine
--Usage: local firstAchievementId = GetFirstAchievementInLine(achievementID)
local GetAchievementRewardTitle = GetAchievementRewardTitle
--Usage: local hasRewardTitle, titleName = GetAchievementRewardTitle(achievementId)
local GetNextAchievementInLine = GetNextAchievementInLine
--Usage: nextAchievementId = GetNextAchievementInLine(achievementId)
local GetAchievementSubCategoryInfo = GetAchievementSubCategoryInfo
--Usage: local subCategoryName, subNumAchievements = GetAchievementSubCategoryInfo(categoryIndex, subCategoryIndex)
local GetAchievementId = GetAchievementId
--Usage: local achievementId = GetAchievementId(categoryIndex, subcategoryIndex, achievementIndex)
local GetAchievementInfo = GetAchievementInfo
--Usage local name, description, points, icon, completed, date, time = GetAchievementInfo(achievementId)
-- ADDED: Titles could also be saved an an SV with a hold time for new status. That way they will remain in the Dropdown
-- as new for up to the hold time. Then, any added by the event will remain as new until mouse-over even after reload.
local newTitles = {}
local achievmentIdMap = {}
local GetTitle = GetTitle -- I want original titles
--Usage: local strTitle GetTitle(achievementId)
--[[
==============================================
[Re-]Creates the title array for use in the addon
Goes through each achievement to get title details
==============================================
--]]
local function InitializeTitles()
AllTitles = {}
--[[
==============================================
Gets title details for the specified achievement and adds to the array
==============================================
--]]
local function CheckAchievementsInLine(id, categoryId, categoryName, subCategory, subCategoryName)
--Go through every achievement looking for if a title exists for it.
local firstId = GetFirstAchievementInLine(id)
id = firstId > 0 and firstId or id
while id > 0 do
local hasTitle, title = GetAchievementRewardTitle(id)
if hasTitle then
-- ADDED: to create a map of all achievement Ids that are titles, to use as reference for the EVENT_ACHIEVEMENT_AWARDED
-- May also need to use more detail in finding titles based on achievements in the EVENT_ACHIEVEMENT_AWARDED and use
-- that info as the map
achievmentIdMap[id] = true
local achieveName = GetAchievementNameFromLink(GetAchievementLink(id))
local name, description, points, icon, completed, date, time = GetAchievementInfo(id)
-- Just used to test the new icon in LibScrollableMenu
-- if newTitles[name] == nil then newTitles[name] = true end
local playerHasTitle = false
local playerTitleIndex = -1
for j=1,GetNumTitles() do
if title == GetTitle(j) then
playerHasTitle = true
playerTitleIndex = j
break
end
end
table.insert(AllTitles,1,{AchievementID=id,TitleID=playerTitleIndex,Title=title,CategoryID=categoryId, CategoryName=categoryName,SubCategoryID=subCategory,SubCategoryName=subCategoryName,HasTitle=playerHasTitle,AchievementName=achieveName,AchievementDescription=description},1);
end
id = GetNextAchievementInLine(id)
end
end
for i=1,GetNumAchievementCategories() do
local categoryName, numSubCategories, numAchievements, earnedPoints, totalPoints = GetAchievementCategoryInfo(i)
for j=1,numAchievements do
CheckAchievementsInLine(GetAchievementId(i,nil,j), i, categoryName)
end
for j=1,numSubCategories do
local subCategoryName, subNumAchievements = GetAchievementSubCategoryInfo(i, j)
for k=1,subNumAchievements do
CheckAchievementsInLine(GetAchievementId(i,j,k), i, categoryName, j,subCategoryName)
end
end
end
for i,sub in pairs(AchievmentIdsCategories) do
if (sub.Name==GetString(SI_AVA_MENU_ALLIANCE_WAR_GROUP)) then
for j,rank in pairs(sub.Entries) do
rank.Icon=GetAvARankIcon(j*2)
end
end
end
ImprovedTitleizer.savedVariables.numTitles = GetNumTitles()
ImprovedTitleizer.savedVariables.titleDetails = AllTitles
end
--[[
==============================================
Contstruct the Title Menu array
==============================================
--]]
local function ConstructTitleMenu()
local LSM = LibScrollableMenu
local function SortHelper(item1, item2, sortKey, sortType, sortOrder)
return ZO_TableOrderingFunction(item1, item2, sortKey or "name", sortType or ZO_SORT_BY_NAME, sortOrder or ZO_SORT_ORDER_UP)
end
TitleMenu = {}
local subMenus={}
for i,sub in pairs(AchievmentIdsCategories) do
subMenus[sub.Name]={Entries={}}
end
for i,vTitle in pairs(AllTitles) do
if(vTitle.HasTitle) then
local titlePlaced = false
local toolTip = vTitle.AchievementName.."\n"..vTitle.CategoryName
if debug==true then
toolTip = toolTip.."\n"..vTitle.TitleID
end
for k, vCategory in pairs(AchievmentIdsCategories) do
for j,q in pairs(vCategory.Entries) do
if vTitle.AchievementID==q.ID then
if newTitles[vTitle.Title] then
vCategory.hasNew = true
end
-- ADDED:
local newEntry = {
name=vTitle.Title,
rank=q.Rank or 0,
icon = q.Icon,
callback=function() SelectTitle(vTitle.TitleID) end,
tooltip=toolTip,
isNew = newTitles[vTitle.Title] or nil
}
table.insert(subMenus[vCategory.Name].Entries, newEntry)
titlePlaced=true
end
end
end
if(titlePlaced==false) then
table.insert(TitleMenu,{name=vTitle.Title, rank = 0, callback=function() SelectTitle(vTitle.TitleID) end,tooltip=toolTip})
end
end
end
table.sort(TitleMenu, function(item1, item2) return SortHelper(item1, item2) end)
local i = 1
for header, titles in spairs(subMenus) do
if(table.getn(titles.Entries) > 0) then
table.sort(titles.Entries, function(item1, item2) return SortHelper(item1, item2, "rank",AVA_SORT_BY_RANK) end)
table.insert(TitleMenu, i, {name=header, entries=titles.Entries, isNew = titles.hasNew})
i = i + 1
end
end
-- add divider below "No Title" if there is more
if #TitleMenu > 0 then
table.insert(TitleMenu, 1, {name=LSM.DIVIDER})
i = i + 1
end
-- add divider below last submenu if there is more
if i <= #TitleMenu then
table.insert(TitleMenu, i, {name=LSM.DIVIDER})
end
end
--[[
==============================================
Adjust the UI
==============================================
--]]
local function SetupTitleEventManagement()
local LSM = LibScrollableMenu
local orgAddDropdownRow = STATS.AddDropdownRow
STATS.AddDropdownRow = function(self, rowName)
local control = orgAddDropdownRow(self, rowName)
control.combobox = control:GetNamedChild("Dropdown")
control.scrollHelper = LSM.ScrollableDropdownHelper:New(self.control, control, 16)
STATS_SCENE:RegisterCallback("StateChange", OnStateChange)
control.scrollHelper.OnShow = function() end --don't change parenting
local titlesRow = control
return control
end
local function UpdateTitleDropdownTitles(self, dropdown)
dropdown:ClearItems()
dropdown:AddItem(ZO_ComboBox:CreateItemEntry(GetString(SI_STATS_NO_TITLE), function() SelectTitle(nil) end), ZO_COMBOBOX_SUPRESS_UPDATE)
ConstructTitleMenu()
dropdown:AddItems(TitleMenu)
self:UpdateTitleDropdownSelection(dropdown)
end
-- Old function from before 8.2.5
-- New function gets the selected item by string value, new function selects by index (which is scambled due to the sorting)
function UpdateTitleDropdownSelection(self, dropdown)
local currentTitleIndex = GetCurrentTitleIndex()
if currentTitleIndex then
dropdown:SetSelectedItemText(zo_strformat(GetTitle(currentTitleIndex), GetRawUnitName("player")))
else
dropdown:SetSelectedItemText(GetString(SI_STATS_NO_TITLE))
end
end
if STATS and STATS.UpdateTitleDropdownTitles then
STATS.UpdateTitleDropdownTitles = UpdateTitleDropdownTitles
STATS.UpdateTitleDropdownSelection = UpdateTitleDropdownSelection
end
end
--[[
==============================================
Plugin Initialization - cache titles where possible, recreate when necessary
==============================================
--]]
local function OnLoad(eventCode, name)
if name ~= ImprovedTitleizer.Name then return end
ImprovedTitleizer.savedVariables = ZO_SavedVars:NewAccountWide("ImprovedTitleizerSavedVariables", 1, nil, {}) --Instead of nil you can also use GetWorldName() to save the SV server dependent
if ImprovedTitleizer.savedVariables.lastversion == nil or ImprovedTitleizer.savedVariables.lastversion ~= ImprovedTitleizer.Version then
if ImprovedTitleizer.logger ~= nil then ImprovedTitleizer.logger:Info("New version of addon installed, recreating.") end
InitializeTitles()
elseif ImprovedTitleizer.savedVariables.lastESOversion == nil or ImprovedTitleizer.savedVariables.lastversion ~= GetESOVersionString() then
if ImprovedTitleizer.logger ~= nil then ImprovedTitleizer.logger:Info("New version of ESO installed, recreating.") end
InitializeTitles()
elseif ImprovedTitleizer.savedVariables.numTitles == nil or ImprovedTitleizer.savedVariables.titleDetails == nil then
if ImprovedTitleizer.logger ~= nil then ImprovedTitleizer.logger:Info("New or corrupt saved variables, recreating.") end
InitializeTitles()
elseif ImprovedTitleizer.savedVariables.numTitles ~= GetNumTitles() then
if ImprovedTitleizer.logger ~= nil then ImprovedTitleizer.logger:Info("New titles exist, recreating.") end
InitializeTitles()
else
if ImprovedTitleizer.logger ~= nil then ImprovedTitleizer.logger:Info("Loading titles from saved variables.") end
AllTitles=ImprovedTitleizer.savedVariables.titleDetails
end
ImprovedTitleizer.savedVariables.lastversion = ImprovedTitleizer.Version
ImprovedTitleizer.savedVariables.lastESOversion = GetESOVersionString()
SetupTitleEventManagement()
EVENT_MANAGER:UnregisterForEvent(ImprovedTitleizer.Name, EVENT_ADD_ON_LOADED)
-- ADDED:
EVENT_MANAGER:RegisterForEvent("ImprovedTitleizer", EVENT_ACHIEVEMENT_AWARDED, function(_, name, points, id)
-- This seams to work.
if achievmentIdMap[id] then
newTitles[name] = true
-- I don't think we need to force any refresh here since the menu is not going to be open at the time
end
end)
-- ADDED:
LibScrollableMenu:RegisterCallback('NewStatusUpdated', function(data, entry)
-- This callback is fired on mouse-over of entries that were flagged as new.
if newTitles[data.name] then
newTitles[data.name] = nil
end
end)
end
--[[
==============================================
On new achievement, recreate the title list
==============================================
--]]
local function OnAchievementsAwarded(eventCode, name)
if ImprovedTitleizer.logger ~= nil then ImprovedTitleizer.logger:Info("New achievement awarded.") end
InitializeTitles()
SetupTitleEventManagement()
end
EVENT_MANAGER:RegisterForEvent(ImprovedTitleizer.Name, EVENT_ADD_ON_LOADED, OnLoad)
EVENT_MANAGER:RegisterForEvent(ImprovedTitleizer.Name, EVENT_ACHIEVEMENT_AWARDED, OnAchievementsAwarded)
IMPROVEDTITLEIZER = ImprovedTitleizer
--[[
==============================================
Slash Commands
==============================================
--]]
SLASH_COMMANDS["/refreshtitles"] = function()
InitializeTitles()
SetupTitleEventManagement()
end
This is a working version of ImprovedTitleizer that works with my current version of LibScrollableMenu Search for "Added:" (no quotes) to find changes I made. It makes use of Icons and the "new" flag. I have not spent enough time with this to know what all needs to be done with the "new" flag but I posted my ideas on that in line .