------------------------------------------------------------------------------------------------- -- Load in global variables -- ------------------------------------------------------------------------------------------------- ArmoryStyleManager = { variableVersion = 1, color = { defaultText = GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_NORMAL) } } local name = "ArmoryStyleManager" local COLLECTIBLE_TYPES = { COLLECTIBLE_CATEGORY_TYPE_BODY_MARKING, COLLECTIBLE_CATEGORY_TYPE_COSTUME, COLLECTIBLE_CATEGORY_TYPE_FACIAL_ACCESSORY, COLLECTIBLE_CATEGORY_TYPE_FACIAL_HAIR_HORNS, COLLECTIBLE_CATEGORY_TYPE_HAIR, COLLECTIBLE_CATEGORY_TYPE_HAT, COLLECTIBLE_CATEGORY_TYPE_HEAD_MARKING, COLLECTIBLE_CATEGORY_TYPE_MOUNT, COLLECTIBLE_CATEGORY_TYPE_PERSONALITY, COLLECTIBLE_CATEGORY_TYPE_PIERCING_JEWELRY, COLLECTIBLE_CATEGORY_TYPE_POLYMORPH, COLLECTIBLE_CATEGORY_TYPE_SKIN, COLLECTIBLE_CATEGORY_TYPE_VANITY_PET } local ROLE_ICONS = { active = { [1] = "esoui/art/lfg/gamepad/lfg_roleicon_dps_down.dds", [4] = "esoui/art/lfg/gamepad/lfg_roleicon_healer_down.dds", [2] = "esoui/art/lfg/gamepad/lfg_roleicon_tank_down.dds", }, notActive = { [1] = "esoui/art/lfg/gamepad/lfg_roleicon_dps_up.dds", [4] = "esoui/art/lfg/gamepad/lfg_roleicon_healer_up.dds", [2] = "esoui/art/lfg/gamepad/lfg_roleicon_tank_up.dds", } } local GRASHOROG_ID = 9745 local ZUQOTH_ID = 10618 local defaultData = { builds = { [1] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [2] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [3] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [4] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [5] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [6] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [7] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [8] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [9] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } }, [10] = { locked = false, role = nil, roleActive = true, tabard = nil, collectibles = { [2] = 0, [3] = 0, [4] = 0, [9] = 0, [10] = 0, [11] = 0, [12] = 0, [13] = 0, [14] = 0, [15] = 0, [16] = 0, [17] = 0, [18] = 0 } } } } local BUTTON_PADDING_X = 10 local BUTTON_SIZE = 45 local CURSE_ICON = { [0] = nil, [1] = "esoui/art/armory/buildicons/buildicon_44.dds", [2] = "esoui/art/armory/buildicons/buildicon_45.dds" } local function CreateOverlay(parent, rel, relPoint, x, y, width, height, vAlign, hAlign) local overlay = WINDOW_MANAGER:CreateControl(nil, parent, CT_LABEL) overlay:SetInheritScale(false) overlay:SetDrawTier(DT_HIGH) overlay:SetDrawLayer(DL_OVERLAY) overlay:SetAnchor(rel, parent, relPoint, x, y) overlay:SetHorizontalAlignment(hAlign or TEXT_ALIGN_CENTER) overlay:SetVerticalAlignment(vAlign or TEXT_ALIGN_CENTER) return overlay end local function CreateButton(name, parent) local button = WINDOW_MANAGER:CreateControl(name, parent, CT_BUTTON) button:SetInheritScale(false) button:SetDrawTier(DT_HIGH) button:SetDrawLayer(DL_OVERLAY) button:SetMouseEnabled(true) button:SetState(BSTATE_NORMAL) button:SetHorizontalAlignment(TEXT_ALIGN_CENTER) button:SetVerticalAlignment(TEXT_ALIGN_CENTER) button:SetFont("ZoFontHeader") button:SetNormalTexture("ESOUI/art/miscellaneous/gamepad/gp_icon_locked32.dds") return button end local function isCurrentBuildLocked() local currentBuildIndex = ARMORY_KEYBOARD.selectedBuildIndex local currentBuildLocked = ArmoryStyleManager.savedVariables.builds[currentBuildIndex].locked return currentBuildLocked end local function RefreshUI() local selectedBuildIndex = ARMORY_KEYBOARD.selectedBuildIndex -- Set the Curse Text to nothing so we can replace the long string "Curse: Werewolf" with an icon ArmoryStyleManager.CurseOutfitRow:GetNamedChild("CurseType"):SetText("") -- Set the Outfit Label to be positioned next to the Mundus label ArmoryStyleManager.CurseOutfitRow:GetNamedChild("Outfit"):SetAnchor(LEFT, ArmoryStyleManager.CurseOutfitRow:GetNamedChild("CurseType"), RIGHT, -ZO_ARMORY_KEYBOARD_MISC_ROW_LABEL_OFFSET_X/2, 0) local textWidth = ArmoryStyleManager.CurseOutfitRow:GetNamedChild("Outfit"):GetTextWidth() + ArmoryStyleManager.Mundus:GetTextWidth() if ArmoryStyleManager.savedVariables.currentBuildIndex == nil then ARMORY_KEYBOARD.buildCountLabel:SetText(zo_strformat("Current Builds: <<1>>", GetNumUnlockedArmoryBuilds())) else ARMORY_KEYBOARD.buildCountLabel:SetText(zo_strformat("Current Build: <<1>>", GetArmoryBuildName(ArmoryStyleManager.savedVariables.currentBuildIndex))) end if not selectedBuildIndex then return false end local nextButtonToUpdate = 1 for index, control in ipairs(ArmoryStyleManager.UIButtons) do control:SetText("") end ArmoryStyleManager.UIButtons[1]:SetAnchor(LEFT, ArmoryStyleManager.UIContainer:GetNamedChild("Header"), LEFT, 295, 460) -- Show 4 buttons rather than 5 if the text will overlap if textWidth > 260 then ArmoryStyleManager.UIButtons[5].refreshed = true ArmoryStyleManager.UIButtons[1]:SetAnchor(LEFT, ArmoryStyleManager.UIContainer:GetNamedChild("Header"), LEFT, 350, 460) end function setNextButton(icon) control = ArmoryStyleManager.UIButtons[nextButtonToUpdate] control:SetText(zo_strformat("|t45:45:<<1>>|t|r", icon)) nextButtonToUpdate = nextButtonToUpdate + 1 end -- Vampire curseType = GetArmoryBuildCurseType(selectedBuildIndex) if curseType ~= 0 then setNextButton(CURSE_ICON[curseType]) end -- Polymorph local hasPoly = false if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_POLYMORPH] > 1 then hasPoly = true end if hasPoly then polyIcon = GetCollectibleIcon(ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_POLYMORPH]) setNextButton(polyIcon) end -- Skin if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_SKIN] > 1 and not hasPoly then skinIcon = GetCollectibleIcon(ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_SKIN]) setNextButton(skinIcon) end -- Hat if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_HAT] > 1 and ArmoryStyleManager.savedVariables.builds[ARMORY_KEYBOARD.selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_HAT] ~= 5002 and not hasPoly then hatIcon = GetCollectibleIcon(ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_HAT]) setNextButton(hatIcon) end -- Costume if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_COSTUME] > 1 and not hasPoly then costumeIcon = GetCollectibleIcon(ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_COSTUME]) setNextButton(costumeIcon) end -- Mount if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_MOUNT] > 1 then mountIcon = GetCollectibleIcon(ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_MOUNT]) setNextButton(mountIcon) end -- Pet if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_VANITY_PET] > 1 then petIcon = GetCollectibleIcon(ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].collectibles[COLLECTIBLE_CATEGORY_TYPE_VANITY_PET]) setNextButton(petIcon) end -- Lock if isCurrentBuildLocked() then ArmoryStyleManager.lockButton:SetNormalTexture("ESOUI/art/miscellaneous/gamepad/gp_icon_locked32.dds") ArmoryStyleManager.lockButton:SetAnchor(RIGHT, ArmoryStyleManager.Collapse, RIGHT, -30, 0) else ArmoryStyleManager.lockButton:SetNormalTexture("ESOUI/art/miscellaneous/gamepad/gp_icon_unlocked32.dds") ArmoryStyleManager.lockButton:SetAnchor(RIGHT, ArmoryStyleManager.Collapse, RIGHT, -27, 0) end -- Role local roleIcon = nil local currentRole = ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].role if currentRole then if ArmoryStyleManager.savedVariables.builds[selectedBuildIndex].roleActive then roleIcon = ROLE_ICONS.active[currentRole] else roleIcon = ROLE_ICONS.notActive[currentRole] end ArmoryStyleManager.roleButton:SetNormalTexture(roleIcon) else ArmoryStyleManager.roleButton:SetNormalTexture("") end end local function SummonAssistant(assistantId) local _, _, icon, _, unlocked, _, summoned = GetCollectibleInfo(assistantId) local summondedMsg = "" local colour = "" local iconLink = zo_strformat("|t20:20:<<1>>|t", icon) local collectibleLink = zo_strformat("|H1:collectible:<<1>>|h|h", assistantId) if unlocked then colour = "bfbfbf" summondedMsg = "You summon" if summoned then summondedMsg = "You dismiss" end UseCollectible(assistantId) else colour = "bf0000" summondedMsg = "You did not unlock the collectible, cannot summon" end local message = zo_strformat("|c<<1>><<2>>|r<<3>><<4>>.", colour, summondedMsg, iconLink, collectibleLink) d(message) end function ArmoryStyleManager.SummonGrashorog() SummonAssistant(GRASHOROG_ID) end function ArmoryStyleManager.SummonZuqoth() SummonAssistant(ZUQOTH_ID) end ------------------------------------------------------------------------------------------------- -- Load in the saved variables -- ------------------------------------------------------------------------------------------------- local function InitSavedVariables() ArmoryStyleManager.savedVariables = ZO_SavedVars:NewCharacterIdSettings("ArmoryStyleManagerData", ArmoryStyleManager.variableVersion, nil, defaultData) end local function ArmoryBuildUpdated(_, buildIndex) local collectibles = {} for i, collectibleType in pairs(COLLECTIBLE_TYPES) do collectibles[collectibleType] = GetActiveCollectibleByType(collectibleType) end ArmoryStyleManager.savedVariables.builds[buildIndex].collectibles = collectibles ArmoryStyleManager.savedVariables.builds[buildIndex].title = GetTitle(GetCurrentTitleIndex()) ArmoryStyleManager.savedVariables.builds[buildIndex].role = GetSelectedLFGRole() ArmoryStyleManager.savedVariables.builds[buildIndex].tabard = Id64ToString(GetItemUniqueId(BAG_WORN, EQUIP_SLOT_COSTUME)) RefreshUI() end local function ArmoryBuildLoaded(_, result, buildIndex) if result ~= ARMORY_BUILD_RESTORE_RESULT_SUCCESS then return false end ArmoryStyleManager.savedVariables.currentBuildIndex = buildIndex for collectibleType, id in pairs(ArmoryStyleManager.savedVariables.builds[buildIndex].collectibles) do local eqippedCollectible = GetActiveCollectibleByType(collectibleType) if eqippedCollectible ~= id then if id ~= 0 then if IsCollectibleUnlocked(id) and IsCollectibleUsable(id) and IsCollectibleValidForPlayer(id) then UseCollectible(id) end else if eqippedCollectible ~= 0 then -- If a collectible is already equipped then we want to 'un- use' the current one UseCollectible(eqippedCollectible) end end end end local currentTitle = GetCurrentTitleIndex() local newTitleString = ArmoryStyleManager.savedVariables.builds[buildIndex].title local newTitle = nil local numTitles = GetNumTitles() for titleIdx = 0, numTitles do if GetTitle(titleIdx) == newTitleString then newTitle = titleIdx break end end if newTitle == nil then local errorMessage = "Invalid title saved, failed to load" local colour = "cb0000" local message = zo_strformat("<<1>>: |c<<2>><<3>>|r: <<4>>", name, colour, errorMessage, newTitleString) d(message) elseif currentTitle ~= newTitle then SelectTitle(newTitle) end local newRole = ArmoryStyleManager.savedVariables.builds[buildIndex].role local oldRole = GetSelectedLFGRole() if newRole then if newRole ~= oldRole and CanUpdateSelectedLFGRole() and ArmoryStyleManager.savedVariables.builds[buildIndex].roleActive then UpdateSelectedLFGRole(newRole) end end local tabard = ArmoryStyleManager.savedVariables.builds[buildIndex].tabard if tabard ~= '0' then local bagSize = GetBagSize(BAG_BACKPACK) for bagSlot = 0, bagSize do local id = Id64ToString(GetItemUniqueId(BAG_BACKPACK, bagSlot)) if id == tabard then EquipItem(BAG_BACKPACK, bagSlot, EQUIP_SLOT_COSTUME) end end else UnequipItem(EQUIP_SLOT_COSTUME) end RefreshUI() end local function RegisterEvents() EVENT_MANAGER:RegisterForEvent(name, EVENT_ARMORY_BUILD_UPDATED , ArmoryBuildUpdated) EVENT_MANAGER:RegisterForEvent(name, EVENT_ARMORY_BUILD_RESTORE_RESPONSE, ArmoryBuildLoaded) end local function CreateUI(control) local UIContainer = control:GetNamedChild("Container") local CurseOutfitRow = control:GetNamedChild("ContainerCurseOutfitRow") local Header = UIContainer:GetNamedChild("Header") local Collapse = Header:GetNamedChild("Collapse") local Mundus = UIContainer:GetNamedChild("Mundus") ArmoryStyleManager.CurseOutfitRow = CurseOutfitRow ArmoryStyleManager.Mundus = Mundus ArmoryStyleManager.UIContainer = UIContainer UIButtons = {} local lastSlotControl = nil for i=1,5 do local slotControl = CreateOverlay(CurseOutfitRow, LEFT, LEFT, 0, 0) slotControl:SetFont("ZoFontHeader") slotControl:SetDimensions(45, 45) if lastSlotControl then slotControl:SetAnchor(LEFT, lastSlotControl, RIGHT, BUTTON_PADDING_X, 0) else slotControl:SetAnchor(LEFT, UIContainer:GetNamedChild("Header"), LEFT, 295, 460) end table.insert(UIButtons, slotControl) lastSlotControl = slotControl end ArmoryStyleManager.UIButtons = UIButtons ArmoryStyleManager.lockButton = CreateButton("ArmoryStyleManager-lock", Header) ArmoryStyleManager.lockButton:SetDimensions(32, 32) ArmoryStyleManager.lockButton:SetAnchor(RIGHT, Collapse, RIGHT, -30, 0) ArmoryStyleManager.lockButton:SetHandler("OnMouseUp",function(self) local currentBuild = ArmoryStyleManager.savedVariables.builds[ARMORY_KEYBOARD.selectedBuildIndex] ArmoryStyleManager.savedVariables.builds[ARMORY_KEYBOARD.selectedBuildIndex].locked = not currentBuild.locked KEYBIND_STRIP:UpdateKeybindButtonGroup(ARMORY_KEYBOARD.keybindStripDescriptor) RefreshUI() end) ArmoryStyleManager.roleButton = CreateButton("ArmoryStyleManager-role", CurseOutfitRow) ArmoryStyleManager.roleButton:SetDimensions(45, 45) ArmoryStyleManager.roleButton:SetAnchor(LEFT, Collapse, LEFT, -75, 0) ArmoryStyleManager.roleButton:SetHandler("OnMouseUp",function(self) local currentBuild = ArmoryStyleManager.savedVariables.builds[ARMORY_KEYBOARD.selectedBuildIndex] ArmoryStyleManager.savedVariables.builds[ARMORY_KEYBOARD.selectedBuildIndex].roleActive = not currentBuild.roleActive RefreshUI() end) RefreshUI() return false end ------------------------------------------------------------------------------------------------- -- Initialize -- ------------------------------------------------------------------------------------------------- local function Initialize() InitSavedVariables() RegisterEvents() local AmoryAssistantName = GetCollectibleInfo(GRASHOROG_ID) ZO_CreateStringId("SI_BINDING_NAME_ARMORY_STYLE_MANAGER_SUMMON_GRASHOROG", zo_strformat("Summon <<1>>", AmoryAssistantName)) local AmoryAssistantName = GetCollectibleInfo(ZUQOTH_ID) ZO_CreateStringId("SI_BINDING_NAME_ARMORY_STYLE_MANAGER_SUMMON_ZUQOTH", zo_strformat("Summon <<1>>", AmoryAssistantName)) ZO_PreHook("ZO_Armory_ExpandedEntry_OnInitialized", CreateUI) ZO_PostHook("ZO_Armory_Keyboard_CollapsedEntry_OnMouseUp", RefreshUI) ZO_PostHook(ARMORY_KEYBOARD, "RefreshBuilds", RefreshUI) ARMORY_KEYBOARD.keybindStripDescriptor[2].enabled = function() if isCurrentBuildLocked() then return false end local function disabledAlertText() return zo_strformat(SI_ARMORY_BUILD_OPERATION_COOLDOWN_ALERT, ZO_FormatTimeMilliseconds(ARMORY_OPERATION_COOLDOWN_DURATION_MS, TIME_FORMAT_STYLE_SHOW_LARGEST_UNIT_DESCRIPTIVE, TIME_FORMAT_PRECISION_SECONDS)) end return not ZO_ARMORY_MANAGER:IsBuildOperationInProgress(), disabledAlertText end EVENT_MANAGER:UnregisterForEvent(name, EVENT_ADD_ON_LOADED) end local function AddonLoaded(e, addonName) if addonName ~= name then return end Initialize() end EVENT_MANAGER:RegisterForEvent(name, EVENT_ADD_ON_LOADED, AddonLoaded)