-- AltSystem UI -- Creates the main dialog window with all interface elements. -- Uses the modern DropdownButton API (WoW 10.2.5+ / 12.0+). AltSystem = AltSystem or {} local WINDOW_WIDTH = 300 local WINDOW_HEIGHT = 478 local PADDING = 12 local ROW_HEIGHT = 30 local LABEL_WIDTH = 80 -- Helper: Build the skill option list from current AltSystem.Data.Skills local function BuildSkillOptions() local options = {} for _, skill in ipairs(AltSystem.Data.Skills) do local sign = skill.modifier >= 0 and "+" or "" local text if skill.level == "Base" or skill.level == "Inept" then text = skill.name .. " (" .. sign .. skill.modifier .. ")" else text = skill.name .. " (" .. skill.level .. " " .. sign .. skill.modifier .. ")" end table.insert(options, { text = text }) end return options end -- Helper: Create a modern dropdown (WowStyle1DropdownTemplate) local function CreateDropdown(parent, name, yOffset, labelText, options, defaultIndex, onSelect) local label = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal") label:SetPoint("TOPLEFT", parent, "TOPLEFT", PADDING, yOffset) label:SetText(labelText) label:SetWidth(LABEL_WIDTH) label:SetJustifyH("LEFT") local selectedIndex = defaultIndex or 1 local dropdown = CreateFrame("DropdownButton", name, parent, "WowStyle1DropdownTemplate") dropdown:SetPoint("LEFT", label, "RIGHT", 4, 0) dropdown:SetWidth(160) dropdown:SetupMenu(function(dropdown, rootDescription) for i, option in ipairs(options) do rootDescription:CreateRadio( option.text, function(data) return data == selectedIndex end, function(data) selectedIndex = data if onSelect then onSelect(data, options[data]) end end, i ) end end) return dropdown, function() return selectedIndex end, function(idx) selectedIndex = idx end end function AltSystem:CreateMainFrame() if AltSystem.MainFrame then return end -- Main frame local f = CreateFrame("Frame", "AltSystemMainFrame", UIParent, "BasicFrameTemplateWithInset") f:SetSize(WINDOW_WIDTH, WINDOW_HEIGHT) f:SetPoint("CENTER") f:SetMovable(true) f:EnableMouse(true) f:RegisterForDrag("LeftButton") f:SetScript("OnDragStart", f.StartMoving) f:SetScript("OnDragStop", f.StopMovingOrSizing) f:SetClampedToScreen(true) f.TitleBg:SetHeight(30) f.title = f:CreateFontString(nil, "OVERLAY", "GameFontHighlight") f.title:SetPoint("TOPLEFT", f.TitleBg, "TOPLEFT", 5, -3) f.title:SetText("AltSystem") -- Track current Y offset for layout local yPos = -40 ------------------------- -- Skill dropdown ------------------------- local skillOptions = BuildSkillOptions() local UpdateSkillWarning -- forward declaration local skillDropdown, getSkillIndex, setSkillIndex = CreateDropdown( f, "AltSystemSkillDropdown", yPos, "Skill:", skillOptions, AltSystem.State.selectedSkillIndex, function(index) AltSystem.State.selectedSkillIndex = index AltSystem.State.selectedSkillName = AltSystem.Data.Skills[index] and AltSystem.Data.Skills[index].name or nil UpdateSkillWarning(index) end) -- Warning icon for skill mismatch (shown next to dropdown when value doesn't match keyword) local skillWarning = CreateFrame("Frame", nil, f) skillWarning:SetSize(20, 20) skillWarning:SetPoint("LEFT", skillDropdown, "RIGHT", 4, 0) local skillWarningIcon = skillWarning:CreateTexture(nil, "ARTWORK") skillWarningIcon:SetAllPoints() skillWarningIcon:SetAtlas("services-icon-warning") skillWarning:SetScript("OnEnter", function(self) if self.tooltipText then GameTooltip:SetOwner(self, "ANCHOR_RIGHT") GameTooltip:SetText(self.tooltipText, 1, 0.82, 0) GameTooltip:Show() end end) skillWarning:SetScript("OnLeave", function() GameTooltip:Hide() end) skillWarning:Hide() -- Update the warning icon visibility based on the currently selected skill UpdateSkillWarning = function(index) local skill = AltSystem.Data.Skills[index] if skill and skill.warning then skillWarning.tooltipText = skill.warning skillWarning:Show() else skillWarning:Hide() end end -- Store references for refreshing AltSystem.SkillDropdown = skillDropdown AltSystem.GetSkillIndex = getSkillIndex AltSystem.SetSkillIndex = setSkillIndex AltSystem.UpdateSkillWarning = UpdateSkillWarning yPos = yPos - ROW_HEIGHT - 8 ------------------------- -- Item dropdown ------------------------- local itemOptions = {} for _, item in ipairs(AltSystem.Data.Items) do local sign = item.modifier >= 0 and "+" or "" local modText = item.modifier ~= 0 and (" (" .. sign .. item.modifier .. ")") or "" table.insert(itemOptions, { text = item.name .. modText, }) end CreateDropdown(f, "AltSystemItemDropdown", yPos, "Item:", itemOptions, AltSystem.State.selectedItemIndex, function(index) AltSystem.State.selectedItemIndex = index end) yPos = yPos - ROW_HEIGHT - 8 ------------------------- -- Defense dropdown ------------------------- local defenseOptions = {} for _, def in ipairs(AltSystem.Data.Defenses) do local sign = def.modifier >= 0 and "+" or "" local modText = " (" .. sign .. def.modifier .. ")" table.insert(defenseOptions, { text = def.name .. modText, }) end CreateDropdown(f, "AltSystemDefenseDropdown", yPos, "Defense:", defenseOptions, AltSystem.State.selectedDefenseIndex, function(index) AltSystem.State.selectedDefenseIndex = index end) yPos = yPos - ROW_HEIGHT - 8 ------------------------- -- Shield checkbox ------------------------- local shieldLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal") shieldLabel:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos) shieldLabel:SetText("Shield:") shieldLabel:SetWidth(LABEL_WIDTH) shieldLabel:SetJustifyH("LEFT") local shieldCheck = CreateFrame("CheckButton", "AltSystemShieldCheck", f, "UICheckButtonTemplate") shieldCheck:SetPoint("LEFT", shieldLabel, "RIGHT", -6, 0) shieldCheck:SetChecked(AltSystem.State.shieldEnabled) local shieldText = shieldCheck:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") shieldText:SetPoint("LEFT", shieldCheck, "RIGHT", 2, 0) shieldText:SetText("+1 modifier") shieldCheck:SetScript("OnClick", function(self) AltSystem.State.shieldEnabled = self:GetChecked() end) yPos = yPos - ROW_HEIGHT - 8 ------------------------- -- Pet/Summon checkbox ------------------------- local petLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal") petLabel:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos) petLabel:SetText("Pet:") petLabel:SetWidth(LABEL_WIDTH) petLabel:SetJustifyH("LEFT") local petCheck = CreateFrame("CheckButton", "AltSystemPetSummonCheck", f, "UICheckButtonTemplate") petCheck:SetPoint("LEFT", petLabel, "RIGHT", -6, 0) petCheck:SetChecked(AltSystem.State.petSummonEnabled) local petText = petCheck:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") petText:SetPoint("LEFT", petCheck, "RIGHT", 2, 0) petText:SetText("+d5 modifier") petCheck:SetScript("OnClick", function(self) AltSystem.State.petSummonEnabled = self:GetChecked() end) yPos = yPos - ROW_HEIGHT - 8 ------------------------- -- Announce checkbox + channel dropdown ------------------------- local announceLabel = f:CreateFontString(nil, "OVERLAY", "GameFontNormal") announceLabel:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos) announceLabel:SetText("Announce:") announceLabel:SetWidth(LABEL_WIDTH) announceLabel:SetJustifyH("LEFT") local announceCheck = CreateFrame("CheckButton", "AltSystemAnnounceCheck", f, "UICheckButtonTemplate") announceCheck:SetPoint("LEFT", announceLabel, "RIGHT", -6, 0) announceCheck:SetChecked(AltSystem.State.announceEnabled) -- Channel dropdown (shown only when announce is enabled) local channelOptions = {} for _, ch in ipairs(AltSystem.AnnounceChannels) do table.insert(channelOptions, { text = ch.name }) end local channelDropdown, getChannelIndex, setChannelIndex = CreateDropdown( f, "AltSystemChannelDropdown", yPos, "", channelOptions, AltSystem.State.announceChannelIndex, function(index) AltSystem.State.announceChannelIndex = index end) channelDropdown:SetPoint("LEFT", announceCheck, "RIGHT", 2, 0) channelDropdown:SetWidth(130) -- Show/hide channel dropdown based on checkbox state local function UpdateChannelDropdownVisibility() if AltSystem.State.announceEnabled then channelDropdown:Show() else channelDropdown:Hide() end end announceCheck:SetScript("OnClick", function(self) AltSystem.State.announceEnabled = self:GetChecked() UpdateChannelDropdownVisibility() end) UpdateChannelDropdownVisibility() yPos = yPos - ROW_HEIGHT - 12 ------------------------- -- Roll buttons ------------------------- local btnWidth = (WINDOW_WIDTH - PADDING * 3) / 2 local attackBtn = CreateFrame("Button", "AltSystemAttackRollBtn", f, "UIPanelButtonTemplate") attackBtn:SetSize(btnWidth, 28) attackBtn:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos) attackBtn:SetText("Attack/Skill Roll") local defenseBtn = CreateFrame("Button", "AltSystemDefenseRollBtn", f, "UIPanelButtonTemplate") defenseBtn:SetSize(btnWidth, 28) defenseBtn:SetPoint("TOPRIGHT", f, "TOPRIGHT", -PADDING, yPos) defenseBtn:SetText("Defense Roll") yPos = yPos - 40 ------------------------- -- Roll result area ------------------------- local resultBg = CreateFrame("Frame", nil, f, "InsetFrameTemplate") resultBg:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos) resultBg:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -PADDING, PADDING) local resultText = resultBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge") resultText:SetPoint("CENTER") resultText:SetText("Roll result will appear here") resultText:SetJustifyH("CENTER") resultText:SetWidth(resultBg:GetWidth() - 10) AltSystem.ResultText = resultText -- Button click handlers attackBtn:SetScript("OnClick", function() AltSystem:PerformRoll("attack") end) defenseBtn:SetScript("OnClick", function() AltSystem:PerformRoll("defense") end) -- Refresh skills from TRP3 profile each time the window is shown f:SetScript("OnShow", function() AltSystem:RefreshSkillDropdown() end) f:Hide() AltSystem.MainFrame = f end -- Refresh the skill dropdown with current TRP3 profile data function AltSystem:RefreshSkillDropdown() AltSystem.Data:RefreshSkills() -- Try to restore the previously selected skill by name; fall back to 1 (Base roll) local newIndex = 1 local savedName = AltSystem.State.selectedSkillName if savedName then for i, skill in ipairs(AltSystem.Data.Skills) do if skill.name == savedName then newIndex = i break end end end AltSystem.State.selectedSkillIndex = newIndex AltSystem.State.selectedSkillName = AltSystem.Data.Skills[newIndex] and AltSystem.Data.Skills[newIndex].name or nil if AltSystem.SetSkillIndex then AltSystem.SetSkillIndex(newIndex) end if AltSystem.UpdateSkillWarning then AltSystem.UpdateSkillWarning(newIndex) end -- Rebuild the dropdown menu with the new skill list if AltSystem.SkillDropdown then local skillOptions = BuildSkillOptions() AltSystem.SkillDropdown:SetupMenu(function(dropdown, rootDescription) for i, option in ipairs(skillOptions) do rootDescription:CreateRadio( option.text, function(data) return data == AltSystem.State.selectedSkillIndex end, function(data) AltSystem.State.selectedSkillIndex = data AltSystem.State.selectedSkillName = AltSystem.Data.Skills[data] and AltSystem.Data.Skills[data].name or nil if AltSystem.SetSkillIndex then AltSystem.SetSkillIndex(data) end if AltSystem.UpdateSkillWarning then AltSystem.UpdateSkillWarning(data) end end, i ) end end) end end -- Frame is created by AltSystem:Init() in Core.lua, after saved variables are loaded