File Details
v1.4.2
- R
- Apr 15, 2026
- 291.19 KB
- 46
- 12.0.1
- Retail
File Name
Carrot-v1.4.2.zip
Supported Versions
- 12.0.1
Changelog
v1.4.2
New Feature: Auction House Search Button on Quests
- Item-collection quests (profession dailies, "Collect 10 Felsteel Bar"-type) and world quests now get a magnifying-glass button on the row when the auction house is open. Click to shop for the items Blizzard's map pin can't help you with
- Uses Auctionator when installed (
Auctionator.API.v1.MultiSearch("Carrot", names)— queues every needed item in the shopping list at once), falls back to Blizzard's nativeAuctionHouseFrame:SendBrowseQuery(firstName, 0, 0, {})when it isn't. Profession quests almost always ask for one item type, so a single native browse query is usually what the player wants - Objective parsing handles all three common locale formats:
"0/10 Felsteel Bar"(enUS leading progress),"Felsteel Bar: 0/10"(trailing-colon variant), and"Felsteel Bar 0/10"(no-colon variant). Fails open to the raw objective text so an unanticipated locale still searches something sensible - Position: anchored to the left of
row.timeTextwith a 4 px gap, so it never collides with the WQ expiration label and regular quest rows (with emptytimeText) get it flush at the top-right corner - Tooltip: title flips between
L["Search on Auctionator"]andL["Search on Auction House"]based on which backend will handle the click, followed by the list of items to be searched. Both strings localized in all 10 locales
v1.4.1
Critical Taint Fix
[ADDON_ACTION_BLOCKED] AddOn 'Carrot' tried to call SetPassThroughButtons():DefaultTrackerHider'shooksecurefunchook onObjectiveTrackerFrame.Showwas synchronously callingHider:DoHide()→SafeSetAlpha(ObjectiveTrackerFrame, 0)from inside the hook body. The hook fires during Blizzard's internalShow()calls, which happen insidesecureexecuterange(dataProviders, ...)on quest / map canvas events. Mutating a Blizzard-owned frame from within that secure range leaked Carrot's taint into every subsequent Blizzard function in the same range, surfacing asSetPassThroughButtonsblocked whenQuestDataProvider.RefreshAllData→AcquirePin→CheckMouseButtonPassthroughtried to configure a map pin- Fix: wrap the
Hider:DoHide()call inC_Timer.After(0, ...)so theSetAlphamutation runs on the next frame in a plain (non-secure) context. Re-checksisHidden/hideDefaultTracker/inCombatinside the deferred closure since state can change between the hook and the timer fire.SetAlphaon its own wasn't the taint vector (v1.3.2 replacedSetScalefor that reason) — the new factor is context: v1.4.0 added enough Blizzard hooks firing insidesecureexecuterange(scenario widget tracking, block discovery, etc.) that this latent "mutation inside secure range" path finally triggered
v1.4.0
New Feature: Prey Section (Midnight Prey Hunt system)
- Dedicated tracker section for the 12.x Prey Hunt world feature (Hunt Tables, not a Hunter class ability). Replaces Blizzard's tiny red on-screen crystal with a proper row: quest title + zone + stage-colored horizontal fill bar (Cold → Warm → Hot → Final, stage-mapped to 0 / 33 / 66 / 100% via Preydator's "Thirds" convention)
- Zone-gated: only visible when the player is in (or a sub-zone of) the prey's zone, with a canonical map-ID equivalence table + parent-map walk so sub-instances inside the right parent zone still count. Stays visible after zone exit when the quest is ready to turn in, so the turn-in prompt survives a hearthstone
- Click-to-complete: prey quests are auto-popup style. Click handler honors
prey.isComplete(same signal the renderer uses) and firesShowQuestComplete(questID)+RemoveAutoQuestPopUp(questID)when the quest is ready — no running to an NPC. Blizzard's nativeSOUNDKIT.UI_AUTO_QUEST_COMPLETEstill plays since we never touch the popup list - Completion visuals: vertical yellow → dark amber gradient fill on the gold bar, WCAG AAA-contrast dark brown
COMPLETElabel with no shadow, completion glow,L["Click to complete"]objective line - Duplicate suppression: filter removes the prey quest from
CT.state.questsand skips its auto-popup inPopulateQuestSectionso "Click to complete" only appears once, in the Prey section - Live stage updates from the
PreyHuntProgresswidget viaUPDATE_UI_WIDGET(matched by type, not set ID — the widget lives in whichever ambient set Blizzard picks)
New Feature: Events Section + Full UIWidget Renderer Coverage
- Events section: reads
C_UIWidgetManager.GetAllWidgetsBySetID(GetObjectiveTrackerWidgetSetID())read-only (never callsRegisterForWidgetSet— the taint rule from v1.3.1 still stands). Replaces the Abundance / zone event UI that was lost when we removed the tainted widget container - Scenario step widget set (
C_ScenarioInfo.GetScenarioStepInfo().widgetSetID): renders Blizzard'sScenarioHeaderTimer(02:52 countdown) andScenarioHeaderCurrenciesAndBackground(e.g. Abundance Bag 0/1500) inside the scenario section — the API channel the default tracker uses for Abundance-style events - 30 widget type renderers covering every entry in
Enum.UIWidgetVisualizationType:- Text/label: IconAndText, IconTextAndBackground, TextureAndText, TextureAndTextRow, TextWithState, TextWithSubtext, TextColumnRow, BulletTextList, ButtonHeader, DoubleIconAndText
- Bars/progress: StatusBar, DoubleStatusBar, CaptureBar, CaptureZone, ZoneControl, TugOfWar, DiscreteProgressSteps, FillUpFrames
- Resources/currencies: HorizontalCurrencies, StackedResourceTracker, IconTextAndCurrencies
- Spell/item: SpellDisplay (with tooltip, colored border from
spellInfo.borderColor), ItemDisplay (withGameTooltip:SetItemByIDhover and asyncItem:CreateFromItemIDloading) - State/indicator: DoubleStateIconRow, PreyHuntProgress, TextureWithAnimation
- Scenario-specific: ScenarioHeaderTimer, ScenarioHeaderCurrenciesAndBackground, ScenarioHeaderDelves
- Layout: Spacer
- Generic fallback renderer catches any future widget type Blizzard ships — inspects the info table for text/icon/bar fields and renders what it finds. No widget type silently vanishes
- Self-registering registry:
WIDGET_RENDERERS[EnumName] = RenderFn, keys matchEnum.UIWidgetVisualizationTypeverbatim. Dispatcher auto-resolves the accessor viaGet<Name>WidgetVisualizationInfo/Get<Name>VisualizationInfo(Blizzard's naming is inconsistent across types). Adding a new renderer is 2 lines - Skipped:
MapPinAnimation,UnitPowerBar(nameplate/map only, not tracker)
Quest Row Timer Bar
- Big purple fill bar for timed quests (
C_QuestLog.GetTimeAllowed > 0) — Abundance / bonus objective timers now render as a full-width countdown bar between title and objective withMM:SScentered inside. Replaces the tiny cornertimeText. Color shifts purple → orange → red as time drains - Applied to both regular quest rows and world quest rows.
ZoneEngine.BuildTaskQuestEntryalso now collectsquestTimerSeconds/questTimerMax
Layout
- World quest group-finder eye moved to the left of the title (just inside the tier bar). Long WQ titles no longer get truncated by the eye on the right, wrap mode looks cleaner, click target stays at a fixed X regardless of title length / item button presence
- Quest item button slots between the eye and the title when present, so the eye always sits at the same absolute X
Correctness Fixes
- Taint hazards:
C_QuestLog.GetTimeAllowed,GetNumAutoQuestPopUps,GetAutoQuestPopUp,C_ScenarioInfo/C_UIWidgetManager/C_Spell.GetSpellInfo/GetQuestProgressBarPercentall nowpcall-wrapped per the 12.x AllowedWhenUntainted rules. Never registers aUIWidgetContaineragainst any widget set - "Ready to turn in" 0.1% sliver bug: when a progressbar-type quest was complete,
GetQuestProgressBarPercentcould return a tiny residual value that bypassed theisComplete → fraction=1fallback, leaving a 1-px fill on pool reuse. Rewrote to force fraction=1 onisCompleteand to always compute fill widths via a parent-walkGetKnownWidthhelper instead of the anchor-derivedprogressBg:GetWidth()(which returns 0 on first render / stale on pool reuse) - "EVENTS (0)" ghost header:
UpdateWindowLayoutwas re-computing counts viaCOUNT_FNSwhich could disagree withPopulateSection's actual rendered count. Now readsinstance._lastCountsstashed by the populate pass - Pool reuse leaks: quest row pool shared with the Prey section — tall 16-px bar, dark-brown label colors, suppressed shadow were leaking back into the next quest populate (visible as "Midnight: Prey" rendering with a giant gold bar). Introduced
ResetQuestRowSharedStatecalled at the top of everyPopulateQuestRow/PopulateWorldQuestRow - First-render widget bars:
RenderEventWidgetran beforeSetPointanchors resolved, causing every event widget bar to compute against a 0-width frame. Anchor now applied before render, and internal renderers useComputeBarWidth/ApplyFractionalFillhelpers that walk up to the first ancestor with an explicitSetWidth - Achievement tracking from in-game UI: listen for
CONTENT_TRACKING_UPDATE(modern 12.xC_ContentTrackingpath) in addition to the legacyTRACKED_ACHIEVEMENT_UPDATEevent. Tracking an achievement via the achievement pane no longer silently waits for/reload
DRY Refactor
- Extracted shared helpers:
GetKnownWidth,ComputeBarWidth,ApplyFractionalFill,ResetQuestRowSharedState,FindAutoQuestPopUp,RegisterExtra(forward-declared),LazyFontString,LazyTexture. Collapsed ~6 duplicated parent-walk width blocks and 3 hand-rolled auto-popup iterations into single call sites
Abundance Bag Bar + Scenario Block Widget Set Discovery
- Abundance bag progress bar (the
1201/1500"Bag" counter that appears below the timer) now renders inline under the scenario header. Lives in widget set514in a siblingScenarioObjectiveTracker.ContentsFrameblock — distinct from the scenario step's widget set (1480, the timer).GetAllWidgetsBySetID(stepSetID)only returns the timer; we discover the extra set IDs by walking the liveContentsFramechildren and reading each block'sWidgetContainer.widgetSetID(read-only, noRegisterForWidgetSet, no taint) UPDATE_UI_WIDGETfilter picks up pushes for any discovered scenario-block set so deliveries / counter changes driveCT:Refresh()immediately. Cache invalidates onSCENARIO_UPDATE/SCENARIO_COMPLETED/ZONE_CHANGED_NEW_AREAand lazy-rebuilds on cache miss so a newly mounted block can't be permanently rejected- Block walk extended to
BonusObjectiveTracker.ContentsFrameso any future event that parks its progress bar in the bonus tracker is auto-discovered RenderStatusBarWidgetfully mirrors Blizzard'sUIWidgetBaseStatusBarTemplate:SetBarText:math.ceildisplayed value,GENERIC_FRACTION_STRINGforValueOverMax(rawbarMax, notbarMax-barMin), respectoverrideBarTextShownType.Always, empty label forHidden/Time/ unknown — same data Blizzard's tracker shows- Smooth value tweening (300 ms linear) on every StatusBar widget value change. Dedicated per-frame ticker that auto-stops when no bars are animating, resumes from the current interpolated position on mid-tween pushes, and stays out of
hasTimerbars (those are driven byactiveEventTimersalready) - Compact widget rows when
info.textis empty:RenderStatusBarWidgetandRenderScenarioHeaderTimerWidgetnow collapse toEVENT_BAR_HEIGHT + 6(16 px) instead ofEVENT_ROW_BAR_H(32 px), so the Abundance timer sits flush under "0/1 Complete Event" instead of leaving 16 px of blank title area - Scenario timer purple gradient: Abundance / scenario timer fill is a horizontal
(0.28, 0.16, 0.55) → (0.60, 0.50, 1.00)SetGradientinstead of a flat purple, matching Blizzard's stage-bar visual. White base set once outside the per-tickapplyFillbecause per-tickSetColorTextureclobbersSetGradientin 12.x
Scenario Bonus Objectives
EvaluateScenarioBonusmirrorsBonusObjectiveTrackerMixin:ProcessScenarioBonusObjectives— walksC_Scenario.GetBonusSteps(), reads each step viaC_Scenario.GetStepInfo+C_ScenarioInfo.GetCriteriaInfoByStep, filters byshouldShowBonusObjective, and feedsCT.state.scenarioBonusSteps- Supersession pruning via
C_Scenario.GetSupersededObjectives(): when step B replaces step A, we drop A while B is incomplete and drop B once A's criteria are all satisfied — same logic Blizzard uses PopulateBonusSectionextended to render scenario bonus steps after its quest-based entries: a header row (step name + description in scenario-orange) followed by compact criteria rows viaPopulateScenarioRow, reusing the existing scenario row pool- New events registered:
SCENARIO_BONUS_VISIBILITY_UPDATE,CRITERIA_COMPLETE,QUEST_WATCH_LIST_CHANGED— matchingBonusObjectiveTrackerMixin's subscription list
Recipe Section Overhaul
248/1reagent count fix:C_Item.GetItemCountnow passed all 5 arguments includingincludeAccountBank=true(warband bank, new in 12.x). Previous 4-arg form silently excluded the warband bank, so reagents stored there read as0. We preferProfessionsUtil.AccumulateReagentsInPossession(slot.reagents)(Blizzard's canonical helper that wraps the count), withItemUtil.GetCraftingReagentCountand a manualC_Item.GetItemCount(itemID, true, false, true, true)as defensive fallbacks- Multi-tier reagent slots: now use
slot.required(Blizzard's canonicalIsReagentSlotRequiredflag) instead of a hand-rolleddataSlotType == Reagentcheck. Catches legacy single-item slots, multi-tierModifiedReagentslots ("Any quality of X"), and modifying-required slots — recipes with 4 ingredients no longer drop to 2 when half are multi-tier. Currency slots are still skipped (not shoppable) - Slot category names: prefer
slot.slotInfo.slotText("Fine Chorus Petal") over a specific tier's item name, matching Blizzard's tracker wording - Completed reagent visuals: rendering switched from the legacy
row.objective:SetText("line1\nline2")path toRenderObjectiveLines(row, reagentLines, row.title, -2)— completed reagents now get the same green checkmark + dimmed-text treatment as completed quest / achievement / scenario criteria, via the shared columnar helper - Click-to-open for unknown professions: tracked recipes from personal crafting orders (player doesn't own the profession) used to be silent no-ops. Click handler now mirrors
Blizzard_ProfessionsRecipeTracker.lua— checksC_TradeSkillUI.IsRecipeProfessionLearned(recipeID). Profession learned →OpenRecipe(recipeID, isRecraft)(recraft flag honored so tracked recrafts open the recraft pane). Not learned →Professions.InspectRecipe(recipeID)for the read-only inspect view. Foreign-profession recrafts skip the inspect path (not meaningful) - Auctionator integration: magnifying-glass button (
common-search-magnifyingglassatlas) appears on the top-left of recipe rows when (a)Auctionator.API.v1is loaded, (b)AuctionHouseFrame:IsShown(), and (c) the recipe has unmet reagents. Click queues every missing reagent's item name intoAuctionator.API.v1.MultiSearch("Carrot", names). Item names are resolved fromrecipe.reagents[i].itemIDsat click time viaC_Item.GetItemInfo— not cached display names — so multi-tier slots search every accepted item, not the slot's category label. Title shifts right by 20 px when the button is visible, restores its default anchor when hidden. Refreshes onAUCTION_HOUSE_SHOW/AUCTION_HOUSE_CLOSED
Delve Enhancements
- Delve detection rewrite:
Enum.ScenarioType.Delvesno longer exists in 12.x. Now usesC_DelvesUI.HasActiveDelve(mapID)— the same call Blizzard's ownInstanceDifficultyMixin:IsInDelve()uses. Was silently returning false on every player, breaking every code path gated onscenario.isDelve - Compact
ScenarioHeaderDelveslayout: header inlines the tier ("Shadowguard Point (Tier 11)") via the newL["TIER_LABEL_FORMAT"]localized format string. Currencies and spell icons share a single row instead of two; currency rows are sized to their measured content width instead of a fixed 90 px so spell icons sit immediately to the right with no wasted gap - Tooltips on every delve icon:
- Spell icons —
OnEntercallsGameTooltip:SetSpellByID(spellID), surfacing the full spell tooltip on hover (these icons were otherwise unidentifiable since they only showed an icon + stack overlay) - Currency icons — hover shows the currency name, widget tooltip text, and (via
C_CurrencyInfo.GetCurrencyInfo) the description + current/max amounts - Tier text — overlay button on the title FontString uses
info.tierTooltipSpellIDfor the tier perk's spell tooltip, falling back to the widget's general tooltip
- Spell icons —
- Spell side label always shown:
sp.text(e.g."Nemesis Strongbox 2/4") now always renders next to the icon when present, ignoring Blizzard'stextShownState == Hiddenflag. Their default UI surfaces this only via tooltip; players want it inline. Stack overlay still respectsstackDisplay > 0per Blizzard's check (previous coalescesp.stackDisplay or ""was buggy because0is truthy in Lua, painting "0" on every stackless spell) hideTrackerCompletelyfor delves: matches the existing M+ option. Hides every Carrot tracker window while inside a delve, for users with a dedicated delve addon. Default off- Scenario peek toggle ("Show All" / "Focus"): when M+ or Delve
hideOtherSectionsis active, a button appears on the scenario section header that togglesCT.state.exclusivePeek. Flipping peek on temporarily overrideshideOtherSectionsso every section becomes visible until the user clicks "Focus" again. Resets onSCENARIO_COMPLETED,PLAYER_ENTERING_WORLD, andCHALLENGE_MODE_RESETso the next exclusive scenario starts focused
World Quest Row Improvements
timeTextanchor fix: the"3d"expiration label was anchoringRIGHT → RIGHT(mid-edge to mid-edge), so on tall WQ rows it floated down to the row's vertical midpoint and overlapped the objective's(54%)progress text. Switched toTOPRIGHT → TOPRIGHTso it stays pinned to the title line regardless of row height. 2 px top margin for breathing roomApplyBarFillFromBGnew helper: reads the bar background's own resolved width viaGetKnownWidth(bg)instead ofComputeBarWidth(row). WQ rows insetprogressBgby the eye-icon gutter (20 px), so the row-based calc was ~20 px too wide and saturated the fill at ~84 % actual progress. WQ rows now use the new helper; quest / scenario rows continue with the legacy path because theirprogressBgstarts at the standard padding inset- Both title and objective right edges respect
timeText.LEFT:RenderObjectiveLinesaccepts arightInsetparameter, set topadding + 60for WQ rows so wrapped objective text never slides under the "3d" column FormatTimeLeftPrecise: WQ tooltip "Time remaining" line now reads"2d 14h 35m"(full breakdown, drops zero segments) instead of the compact"3d"shown on the row itself- Group-finder eye gated on real eligibility:
C_LFGList.CanCreateQuestGroup(questID)(the canonical check Blizzard'sQuestUtil.CanCreateQuestGroupwraps) replaces our blanketsuggestedGroup = truefor every world quest. Solo-runnable WQs no longer show the eye — only elites and explicitly group-suggested content do, matching Blizzard's default
Other Fixes
- Achievement progress bar gap:
progressBgnow anchorsTOP → row.objective:BOTTOMinstead ofBOTTOMLEFT → row.BOTTOMLEFTso the bar sits directly under the criteria block. The previous bottom anchor combined withCalcRowHeight's padding overestimate left a visible gap between the last criteria line and the bar. Falls back to the row-bottom anchor for collapsed / no-criteria rows - Criteria icon vertical alignment: removed the spurious
+2Y offset onpair.text:SetPoint("TOPLEFT", pair.icon, "TOPRIGHT", gap, 2). Was pushing text up 2 px relative to the icon, leaving the icon visually below the text baseline on every row that usesRenderObjectiveLines(quests, achievements, scenario criteria, recipes) - Prey zone detection: now uses
GetQuestUiMapID(questID, true)(the same call Blizzard's ownUIWidgetTemplatePreyHuntProgress:OnMouseUpuses) as the primary source. Prey quests aren't task quests soC_TaskQuest.GetQuestZoneIDwas returning nil and the section never showed. Also fails open: ifFindPreyHuntProgressInfo()returned awidgetInfo, we markinZone = trueregardless of the map-ID match — Blizzard's widget only broadcasts when the player is in range, so its presence is the ground truth GetExtraScenarioBlockWidgetSetIDsscopes a temporarysupersededPairsinstead ofpairs— earlier draft accidentally shadowed thepairsbuiltin which would have broken any futurepairs(...)call inside the block
Localization
L["TIER_LABEL_FORMAT"] = "Tier %s"— locale-controlled format string for the delve tier suffix. CJK locales invert to"%s 등급"/"%s 级"/"%s 級"so the number comes before the unit. English default added explicitly in theenUSblock since the metatable fallback would otherwise return the literal identifierL["Show All"]/L["Focus"]— peek button label, in all 10 locales (English + 9)L["Search on Auctionator"]— recipe row tooltip header, in all 10 locales.luacheckrcglobals added:C_DelvesUI,C_LFGList,Auctionator,AuctionHouseFrame,ItemUtil,Professions,ProfessionsUtil
Diagnostics
/carrot widgets— dumps tracker widget set + every field on each widget's visualization info (for debugging event/scenario rendering)/carrot widgetapi— lists everyC_UIWidgetManageraccessor available on the current client/carrot barinfo— dumps everyGetStatusBarWidgetVisualizationInfotable for StatusBars parented underScenarioObjectiveTracker.ContentsFrameblocks. The canonical tool for "why doesn't Carrot render this scenario / event bar?" investigations — covers the per-block sibling widget sets the primaryGetAllWidgetsBySetIDquery doesn't reach- Removed exploratory diagnostics (
eventquest,tracehook,statusbars,stagedump) once the Abundance investigation wrapped —Config.luashrank from 938 lines to 346
v1.3.2
Critical Taint Fix
- Quest log / QuickJoin / GameTooltip "tainted by 'Carrot'" errors:
DefaultTrackerHiderwas callingSetScale(0.001)onObjectiveTrackerFrameplus walkingObjectiveTrackerManager.moduleToContainerMapand mutating every module. Module frames contain protected children (quest-special-itemSecureActionButtons, LFG queue bits) and in 12.xSetScaleon such frames taints downstream Blizzard code, surfacing as"attempt to compare a secret number value","attempt to perform numeric conversion on a secret number value", and"Secret values are only allowed during untainted execution"insideQuestMapFrame,LayoutFrame, andQuickJoinToast - Fix: rewrote the hider to
SetAlpha(0)only (noSetScale, noSetPoint), dropped the module-container walk, added anIsProtected()guard so secure frames are skipped, and wrapped every mutation inpcall. Children inherit the parent's alpha so a single call cascades through the tracker tree
v1.3.1
Critical Taint Fix
- GameTooltip taint ("tainted by 'Carrot'"): removed Carrot's
UIWidgetContainerthat was registering againstC_UIWidgetManager.GetObjectiveTrackerWidgetSetID()— a widget set shared with Blizzard's own tracker and tooltip code. Registering our own container against the shared set ID was poisoningDefaultWidgetLayout/GameTooltip_ClearWidgetSet, producing errors like"attempt to compare a secret number value (tainted by 'Carrot')"insideLayoutFrame. Trade-off: Carrot's tracker no longer renders Abundance event bars / zone event widget progress inline
Mythic+ / Scenario Fixes
- Enemy forces percent: now parsed from
criteriaInfo.quantityStringvia%d+(matching AngryKeystones and Blizzard's own ScenarioObjectiveTracker). The previousquantity/totalQuantityformula gave nonsense like 112% at the start of a key becausequantityis an internal encoded value for weighted progress, not the displayable current count - Death tooltip crash:
"table index is secret"—C_DamageMetercombat sourcenameanddeathTimeSecondsfields are secret values in 12.x that can't be read, compared, or used as table keys. Death log now stores onlyclassFilename+deathRecapID, and the tooltip groups deaths by class withLOCALIZED_CLASS_NAMES_MALE+RAID_CLASS_COLORS - Binary scenario criteria bar: hidden for
totalQuantity <= 1(boss kills etc.), since the checkmark/dash prefix already conveys state — no more redundant "0/1" bars overlapping adjacent rows in Skyreach-style scenarios
Quest Item Buttons
- Shown on world quests and bonus objectives: the existing
PopulateQuestSectionalready wired item buttons for regular quests, butPopulateWorldQuestSection/PopulateBonusSectionnever did. ExtractedAttachItemButtonToWQRowthat runs the sameC_QuestLog.GetLogIndexForQuestID→GetQuestLogSpecialItemInfolookup (verified against AngryKeystones, OPie, Plumber). World quests like "Mobilize! Enlist! Recruit!" now get their clickable Flyer button in Carrot's tracker - Padding no longer oscillates across refreshes: anchor shifting was previously driven by whether we successfully placed a
SecureActionButtonthis render, which fails in combat lockdown. Combat/non-combat refreshes were flipping the title left/right every tick during active world quests. Split the decision: combat-safeQuestHasSpecialItemprobe drives the layout, button placement itself is a best-effort combat-gated step. Applied to both regular quests and WQ/bonus rows
Layout & Row Fixes
- World quest row overlap: two WQs sometimes overlapped briefly and corrected themselves after a refresh. Root cause:
timeTextauto-sized from countdown content ("5h 32m" → "5h" → "30m" → "NOW!"), cascading throughgroupFinderBtn.RIGHT → title.RIGHTand flipping title wrap every second. Row-below yOffsets were computed with the old wrapped height. Fixed by lockingtimeText:SetWidth(56)on bothCreateQuestRowandCreateWorldQuestRow
Default Tracker Hider
- Hide all objective tracker modules, not just the main frame: 12.x split the tracker across independent module frames (quest, world quest, scenario, bonus, achievement, campaign) held in
ObjectiveTrackerManager.moduleToContainerMap. Hiding onlyObjectiveTrackerFrameleft module containers peeking from the right. Now walks the map and suppresses every frame - Hide WorldQuestTracker (Tercio) frames when installed: auto-detects
_G.WorldQuestTrackerScreenPaneland applies the same treatment, gated on the existinghideDefaultTrackertoggle. WQT anchored its panels relative toObjectiveTrackerFrame.topleft/toprightand computed offsets viaObjectiveTrackerManager.moduleToContainerMap, so with Blizzard's tracker suppressed its own frames ended up at unexpected positions
v1.3.0
Achievements
- Criteria list: Each achievement now shows its individual criteria below the progress count, using the same bullet/checkmark/faded styling as quest objectives
- Per-achievement expand/collapse: Small
+/-arrow in the top right of every achievement row toggles the criteria list; state saved per-achievement inCT.db.achievementCollapsed - Row layout fix: Name and progress text no longer overlap at larger font sizes — anchored top-to-bottom relative to each other instead of centered on the icon with hardcoded offsets
- Dynamic row height:
CalcRowHeightnow accounts forprogressTextand criteria list so achievement rows grow correctly with font size changes - Default Achievements tab for existing installs: One-time migration adds an "Achievements" tab (and enables tabs) on the first load so upgraders get the new default layout. After the migration runs, users can freely delete the tab without it being recreated
Mythic+ / Delves
- Auto-focus scenario tab on M+ start: New
TF:FocusSectionhelper automatically switches the containing window to whichever tab owns the scenario section whenCHALLENGE_MODE_STARTfires (and on/carrot mplusdemo), so users with the Achievements tab active don't miss the timer/boss/EF bar - Checkmark + faded styling for bosses and delve criteria: Completed M+ boss rows and delve criteria now use Blizzard's green
ReadyCheck-Readyicon plus the configuredCompleted Objectivecolor/alpha, matching quest objectives. M+ split times fade with the title; delta and "Best:" hints stay full color - Enemy forces bar race fix: Explicit progressBg/progressFill re-anchoring and a
scrollChild → row → 200fallback chain that handles the Lua truthiness bug whereX or 200returns0whenXis0. No more "shows 0.1% then corrects itself after a reload" - Boss row font leak fix:
timerTextRow:SetFont(..., +4)used to stick on rows the pool handed back toMPlusTextRow, causing one apparently-random boss row to render with a larger font.GetScenarioRowandMPlusTextRownow reapply the base font defensively - Timer bar marker draw order:
+2/+3threshold markers are now created atOVERLAYsublevel 7 viaSetDrawLayer, soprogressFillcan never cover them regardless of pool-reuse creation order. Also guardedmarkerWidthagainst a saved0value (Luaor 1fails for0)
Migrations & Data Model
- One-time migration flags: New
CT.db.migrationstable tracks which "ensure section exists" migrations have run. Thescenario,recipes, andachievementsensures now run exactly once per profile, after which users can delete those sections or tabs without them being re-added on every reload (previously they were silently re-added on every load)
v1.2.0
Window Tabs
- Tabs inside windows: Each tracker window can now host multiple tabs, each with its own filtered sections, order, collapsed state, and quest subcategory order
- Per-tab section filtering: Sections are assigned to exactly one tab, so you can split quests/M+ into one tab and achievements into another
- Tab bar: Button-style tabs at the top of the window with active/inactive states using the tracker's yellow accent color; hidden when tabs are disabled
- Renameable tabs: Tab names are user-editable from the Windows options panel
- Configurable tab opacity: New
Active Tab AlphaandInactive Tab Alphasliders in Appearance → Tab Bar - New default layout: Fresh installs ship with tabs enabled and a "Main" / "Achievements" split to surface both features
- Saved data migration: Existing profiles are migrated into the tabs model on load without touching visible behavior
Objective Styling
- Blizzard-style completed objectives: Finished objective lines are greyed out and semi-transparent so players can focus on what's left
- Green checkmark icon: Completed objectives are prefixed with Blizzard's
ReadyCheck-Readygreen check; in-progress ones get a dash bullet - Yellow quest titles: Auto-tracked quest titles now default to Blizzard's classic gold (
1.0, 0.82, 0) - Configurable: New Appearance → Objectives section with
Show Bullets,Show Checkmark, andCompleted Objective Alphasettings; newCompleted Objectivecolor in the Colors panel
M+ Bug Fixes
- Enemy forces bar: Now parses the percent from
criteriaInfo.quantityString(matching Blizzard's ScenarioObjectiveTracker) instead ofquantity/totalQuantity, which isn't normalized to 100 for weighted progress. Fill now reliably climbs 0 → 100% - Boss row layout drift: Boss name rows no longer oscillate between one and two lines. Root cause was
GetStringHeight()returning inconsistent values across refreshes on wrapping font strings (unresolved layout on first pass). M+ rows now disable wrap and use a fixed single-line height; scenario row pool restores wrap on checkout so delve criteria still wrap correctly
v1.1.0
Mythic+ Tracker
- Text-based M+ display: MythicPlusTimer-style layout — remaining time, elapsed/total, +2/+3 threshold countdowns
- Segmented timer bar: Visual countdown bar with +3/+2 threshold markers (configurable color and width)
- Blizzard timer hook: Synced via ScenarioObjectiveTracker.ChallengeModeBlock:UpdateTime (zero drift)
- Boss split timing: Records boss kill times, compares against personal best per dungeon
- Affix display: Text (dash-separated) or icons mode (configurable in Settings → Dungeons)
- Enemy forces: Blue progress bar with percentage text inside
- Death counter: Shows count + time penalty; tooltip with per-player breakdown via C_DamageMeter
- Auto-hide sections: Option to hide all non-scenario sections during M+ or Delves
- Hide tracker option: For players using external M+ addons
- Demo mode:
/carrot mplusdemoto preview,/carrot stopdemoto clear - M+ colors: Customizable +3/+2/+1/Depleted/Enemy Forces/Marker colors in Colors panel
- Marker width slider: 1-4px (Settings → Dungeons)
Recipe Tracking
- New "Recipes" section showing tracked profession recipes with reagent have/need counts
- Progress bar showing fraction of reagent types fulfilled
- Left-click opens recipe in profession UI, right-click untracks
- "Show Recipes" filter toggle, auto-enabled when a recipe is tracked
- Reagent names resolved via C_Item.GetItemInfo with fallbacks
New Features
- Quest type colors: Daily (blue), Weekly (teal), Campaign (orange) — distinct colors for titles and tier bars
- Group finder button: Eye icon on all world quest rows to open LFG
- Quest reward preview: Tooltip shows XP, gold, item, and currency rewards
- Quest countdown timers: Timed quests (e.g., Abundance events) show live MM:SS countdown
- UIWidget support: Zone event progress bars (Abundance) via C_UIWidgetManager
- Progress bar percentage: "progressbar" type objectives show % text inside the bar
- Auto quest popups: OFFER (new quest) and COMPLETE (turn-in) via GetNumAutoQuestPopUps API
- Campaign chapter progress: Tooltip shows "Campaign Quest (Chapter 3/7)"
- Minimap button: Click opens settings, shift-drag to reposition
- Delve improvements: Step title, compact 12px scenario bars with text inside, stage indicator
- Dungeons & Instances settings panel: M+ and Delve toggles
Context Menu
- Share Quest: Share quest with party members
- Abandon Quest: Abandon with Blizzard confirmation dialog (shown in red)
Bug Fixes
- Interface version: Updated to 120001 (WoW 12.0.1)
- M+ timer always 0: Uses GetActiveChallengeMapID (not GetActiveKeystoneInfo) for map ID
- M+ GetActiveKeystoneInfo: Fixed return value unpacking (2 values, not 3)
- Delve objectives not showing: Added "scenario" to default window sections with migration
- Font dropdown clipping: Custom
Carrot-Compact-Dropdownwidget with 300px max height (library-safe, no Libs/ modifications) - Text overlap on progress bar: Progress bar anchored below objective text; height accounts for content
- Wrap/ellipsis flickering: Permanent anchors at row creation, never cleared during populate
- Combat lockdown errors: Guarded C_SuperTrack/QuestMapFrame; deferred event registration
- ADDON_ACTION_FORBIDDEN: Removed COMBAT_LOG_EVENT_UNFILTERED (restricted in 12.x)
- Tracker blank after /reload in combat: Removed blanket combat bail-out from TF:Update()
- World quest type detection: Uses Enum.QuestWQType instead of Enum.QuestTagType
- World quest progress bar: Uses progressBarPct from C_TaskQuest when available
- Quest item icon overflow: Inset icon texture by 2px inside border frame
- Quest item indentation: Pooled rows reset anchors when no item button present
- Progress bar on non-numeric quests: Hidden for 0/1 objectives
- Stale objective/bar heights: Reset when text empty or bar hidden
- Boss names overlapping bars: M+ boss rows rendered directly, bar hidden
- Timer dividers on wrong row: Hidden in GetScenarioRow for pooled reuse
- Layout jump on first frame: All Get*Row functions set explicit width from parent
- Minimap button error: Uses CT.Options:Open() instead of Settings.OpenToCategory
- MakeColorOption crash: Fallback to COLOR_DEFAULTS for new color keys
UI Polish
- Filter icon changed to visible notepad icon
- Scenario criteria: compact 12px bar with count text inside
- Tier bar colors: Scenario and World Quest/default now customizable
- Timer text +4pt larger for main countdown
- Timer bar aligned with content indentation
- Enemy forces default color changed from purple to blue
- Localization: All new strings translated for 9 languages (ptBR, deDE, frFR, esES/esMX, itIT, ruRU, koKR, zhCN, zhTW)
v1.0.0
- Initial release
- Context-aware quest tracking: auto-shows quests in your current zone
- Three-tier quest visibility: Pinned, Recommended, Zone (auto-tracked)
- Quest subcategories: Pinned, Ready to Turn In, Campaign, Daily, Weekly, Zone
- World quest tracking with time remaining display
- Bonus objective tracking
- Scenario/dungeon objective tracking
- Achievement tracking with zone story auto-detection
- Quest item buttons (SecureActionButton, combat-safe)
- Proximity sorting (closest quests first)
- Subzone highlighting
- Configurable appearance: fonts, colors, sizes, outlines, shadows
- Collapsible sections and subcategories with drag-to-resize handles
- Customizable section and subcategory display order
- Filter dropdown for toggling quest types
- Profile management via AceDB (switch, copy, import/export)
- Hover highlight effect
- Blizzard default tracker suppression (combat-safe)

