@@ -17,10 +17,6 @@ local FRAME_W, FRAME_H = 768, 512;
1717local NUM_ROWS = 19 ;
1818local ROW_HEIGHT = 16 ;
1919
20- -- Profession portrait icons, keyed by SkillLine.dbc id. Vanilla's DBC icon
21- -- field is a "Temp" placeholder for professions, so the real TradeSkillFrame
22- -- hardcodes these too (Blizzard_TradeSkillUI's TradeSkillIcons table) — we key
23- -- by id instead of name so it's locale-independent.
2420local PROFESSION_ICONS = {
2521 [171 ] = " Trade_Alchemy" ,
2622 [164 ] = " Trade_BlackSmithing" ,
@@ -47,11 +43,6 @@ local function ProfessionIcon(skillLineID)
4743 or " Interface\\ Icons\\ INV_Misc_QuestionMark" ;
4844end
4945
50- -- Exact port of the engine's trade-skill difficulty (the builder inside
51- -- Script_GetTradeSkillInfo, FUN_004fca20): `hi` = SkillLineAbility trivialHigh,
52- -- `lo` = trivialLow (defaults to hi-25 when zero), yellow = midpoint. Returns
53- -- the band 0..3 (orange/yellow/green/grey) for the linker's skill — identical
54- -- to what the default UI shows in the linker's own window.
5546local function DifficultyBand (skill , hi , lo )
5647 if not hi or hi <= 0 then
5748 return 3 ;
@@ -77,10 +68,6 @@ local BAND_COLOR = {
7768 [3 ] = TRIVIAL_DIFFICULTY_COLOR , -- grey
7869};
7970
80- -- Parse a `trade:` hyperlink body into its fields. Returns
81- -- `id, cur, max, linkerName, bits` (linkerName may be nil), or nil if
82- -- malformed. `bits` may legitimately be empty (a profession with zero
83- -- recipes).
8471local function ParseTradeLink (link )
8572 -- Current format, with the linker's name: trade:id:cur:max:Name:bits
8673 local _ , _ , id , cur , max , who , bits =
10289---- --------------------------------------------------------------------------
10390
10491local frame ;
105-
106- -- Resolve each recipe's crafted-item subclass. Returns the sorted distinct
107- -- subclass list, and whether any recipe crafts an item at all (false for
108- -- enchanting -> no filter shown). For items whose data isn't cached yet,
109- -- registers an Item-mixin load callback (`onLoaded`) so the list fills in as
110- -- the data arrives — no global GET_ITEM_INFO_RECEIVED polling.
11192local function ResolveSubclasses (list , onLoaded )
11293 local present , subs , anyItem = {}, {}, false ;
11394 for i = 1 , table .getn (list ) do
@@ -135,11 +116,6 @@ local function ResolveSubclasses(list, onLoaded)
135116 return subs , anyItem ;
136117end
137118
138- -- Subclass dropdown: "All Subclasses" + each distinct subclass. Buttons carry
139- -- their subclass in `value` so the shared click handler needs no per-iteration
140- -- closures (Lua 5.0 safe). The "All" button uses a sentinel because vanilla's
141- -- UIDropDownMenu_AddButton defaults an absent `value` to the button text —
142- -- which would otherwise filter by "All Subclasses" and match nothing.
143119local SUBCLASS_ALL = {};
144120
145121local function SubClassButton_OnClick ()
@@ -170,12 +146,6 @@ local function SubClassDropDown_Initialize()
170146 end
171147end
172148
173- -- (Re)build the subclass dropdown from the frame's recipe list and register
174- -- load callbacks (via ResolveSubclasses) for any crafted items not yet cached
175- -- — passing itself as the callback, so each arrival refreshes the dropdown.
176- -- Only rebuilds the visible list when a subclass filter is active (the "All"
177- -- view doesn't depend on subclasses, so we avoid resetting the scroll on every
178- -- item that loads).
179149local function RefreshSubclasses ()
180150 if not (frame and frame :IsShown () and frame .recipes ) then
181151 return ;
@@ -207,15 +177,11 @@ local function CreateFrame_TradeSkillLink()
207177 f :SetFrameStrata (" DIALOG" );
208178 f :Hide ();
209179
210- -- Portrait sits BEHIND the parchment so the corner ring frames it (the
211- -- TopLeft quadrant art has a transparent ring cut-out).
212180 local portrait = f :CreateTexture (nil , " BACKGROUND" );
213181 portrait :SetSize (60 , 60 );
214182 portrait :SetPoint (" TOPLEFT" , 7 , - 6 );
215183 f .portrait = portrait ;
216184
217- -- Authentic TradeSkillFrame parchment: four quadrant textures, on BORDER
218- -- so they overlay (and frame) the portrait behind them.
219185 local function Quad (file , w , h , point )
220186 local tx = f :CreateTexture (nil , " BORDER" );
221187 tx :SetTexture (" Interface\\ TradeSkillFrame\\ " .. file );
@@ -234,16 +200,12 @@ local function CreateFrame_TradeSkillLink()
234200 local close = CreateFrame (" Button" , nil , f , " UIPanelCloseButton" );
235201 close :SetPoint (" TOPRIGHT" , - 77 , - 8 );
236202
237- -- Skill-rank bar — matches TradeSkillRankFrame: 596x15 at (76,-44), blue
238- -- fill over the skills-bar texture with a dark-blue background.
239203 local bar = CreateFrame (" StatusBar" , nil , f );
240204 bar :SetSize (596 , 15 );
241205 bar :SetPoint (" TOPLEFT" , 76 , - 44 );
242206 bar :SetStatusBarTexture (" Interface\\ PaperDollInfoFrame\\ UI-Character-Skills-Bar" );
243207 bar :SetStatusBarColor (0.0 , 0.0 , 1.0 , 0.5 );
244208 bar :SetMinMaxValues (0 , 1 );
245- -- Background: white @ a=0.2 tinted dark blue @ 0.5 (alphas multiply, so it's
246- -- faint) — matches TradeSkillRankFrameBackground exactly.
247209 local barBg = bar :CreateTexture (nil , " BACKGROUND" );
248210 barBg :SetAllPoints (bar );
249211 barBg :SetTexture (1 , 1 , 1 , 0.2 );
@@ -256,9 +218,6 @@ local function CreateFrame_TradeSkillLink()
256218 edgeFile = " Interface\\ Tooltips\\ UI-Tooltip-Border" , edgeSize = 16 ,
257219 });
258220 border :SetBackdropBorderColor (0.4 , 0.4 , 0.4 );
259- -- Two FontStrings, exactly like TradeSkillRankFrame: the profession name in
260- -- GameFontNormalSmall (gold) at LEFT (6,1), then the rank in
261- -- GameFontHighlightSmall (white) 13px to its right.
262221 local barName = bar :CreateFontString (nil , " OVERLAY" , " GameFontNormalSmall" );
263222 barName :SetPoint (" LEFT" , 6 , 1 );
264223 local barRank = bar :CreateFontString (nil , " OVERLAY" , " GameFontHighlightSmall" );
@@ -273,8 +232,6 @@ local function CreateFrame_TradeSkillLink()
273232 summary :SetPoint (" TOPRIGHT" , - 110 , - 70 );
274233 f .summary = summary ;
275234
276- -- Subclass filter (item-producing professions only; hidden for enchanting,
277- -- which crafts no items). Mirrors TradeSkillSubClassDropDown at (56,-64).
278235 local dropdown = CreateFrame (" Frame" , " ClassicAPITradeSkillLinkSubClass" , f ,
279236 " UIDropDownMenuTemplate" );
280237 dropdown :SetPoint (" TOPLEFT" , 40 , - 60 );
@@ -292,11 +249,6 @@ local function CreateFrame_TradeSkillLink()
292249
293250 f .rows = {};
294251 for i = 1 , NUM_ROWS do
295- -- Inherit the real row button the CraftFrame/TradeSkillFrame use
296- -- (CraftButtonTemplate -> ClassTrainerSkillButtonTemplate). The name is
297- -- rendered through the template's ButtonText with Blizzard's exact font
298- -- metrics, so the row spacing is identical to those windows — no
299- -- hand-placed FontString to get wrong.
300252 local rowName = " ClassicAPITradeSkillLinkRow" .. i ;
301253 local row = CreateFrame (" Button" , rowName , f ,
302254 " ClassTrainerSkillButtonTemplate" );
@@ -307,28 +259,16 @@ local function CreateFrame_TradeSkillLink()
307259 row :SetPoint (" TOPLEFT" , f .rows [i - 1 ], " BOTTOMLEFT" , 0 , 0 );
308260 end
309261
310- -- Flat list (no collapsible headers): drop the +/- tree icon and its
311- -- icon-sized hover art.
312262 row :SetNormalTexture (" " );
313263 row :SetDisabledTexture (" " );
314264 row :SetHighlightTexture (" " );
315- -- Keep difficulty colour on hover (don't swap to the white HighlightFont).
316- -- if row.SetHighlightFontObject then
317- -- row:SetHighlightFontObject(GameFontNormal);
318- -- end
319265
320- -- The template anchors ButtonText past the (now hidden) tree icon;
321- -- re-anchor it to the row's left edge since we show no icon.
322266 local txt = getglobal (rowName .. " Text" );
323267 if txt then
324268 txt :ClearAllPoints ();
325269 txt :SetPoint (" LEFT" , row , " LEFT" , 4 , 0 );
326270 end
327271
328- -- Selection bar: Blizzard's exact selection texture (UI-Listbox-Highlight2,
329- -- full alpha, default BLEND — its translucency is baked into the texture,
330- -- so we don't guess an alpha), tinted per-row to the recipe's difficulty
331- -- colour via SetVertexColor in Refresh.
332272 local sel = row :CreateTexture (nil , " BACKGROUND" );
333273 sel :SetTexture (" Interface\\ Buttons\\ UI-Listbox-Highlight2" );
334274 sel :SetAllPoints (row );
@@ -358,45 +298,31 @@ local function CreateFrame_TradeSkillLink()
358298 local hdrRight = prodIcon :CreateTexture (nil , " BACKGROUND" );
359299 hdrRight :SetTexture (" Interface\\ ClassTrainerFrame\\ UI-ClassTrainer-DetailHeaderRight" );
360300 hdrRight :SetSize (64 , 64 );
361- -- Adjacent to the left piece (no overlap), like Blizzard's detail header.
362301 hdrRight :SetPoint (" TOPLEFT" , hdrLeft , " TOPRIGHT" , 0 , 0 );
363302 local prodCount = prodIcon :CreateFontString (nil , " ARTWORK" , " NumberFontNormal" );
364303 prodCount :SetPoint (" BOTTOMRIGHT" , - 5 , 2 );
365304 prodIcon .count = prodCount ;
366305 f .prodIcon = prodIcon ;
367306
368- -- Name is a child of the icon (ARTWORK, like the reagents) so it draws
369- -- above the plate; starts 5px right of the icon (matching the reagents'
370- -- icon.right + 5) so it clears the icon that now sits on the plate.
371307 local prodName = prodIcon :CreateFontString (nil , " ARTWORK" , " GameFontNormal" );
372308 prodName :SetPoint (" LEFT" , prodIcon , " RIGHT" , 5 , 0 );
373309 prodName :SetWidth (240 );
374310 prodName :SetJustifyH (" LEFT" );
375311 prodName :SetJustifyV (" MIDDLE" );
376312 f .prodName = prodName ;
377313
378- -- Spell description (enchants only — item recipes leave it empty so it
379- -- collapses to zero height and the reagent label sits right under the
380- -- icon). White, wrapping, like the real Craft window's CraftDescription.
381314 local prodDesc = f :CreateFontString (nil , " OVERLAY" , " GameFontHighlightSmall" );
382315 prodDesc :SetPoint (" TOPLEFT" , prodIcon , " BOTTOMLEFT" , 0 , - 6 );
383316 prodDesc :SetWidth (280 );
384317 prodDesc :SetJustifyH (" LEFT" );
385318 prodDesc :SetJustifyV (" TOP" );
386319 f .prodDesc = prodDesc ;
387320
388- -- Reagent label sits below the description (which is empty for items, so
389- -- it lands ~7px below the 37px icon — matching TradeSkillReagentLabel).
390321 local reagentLabel = f :CreateFontString (nil , " OVERLAY" , " GameFontNormalSmall" );
391322 reagentLabel :SetPoint (" TOPLEFT" , prodDesc , " BOTTOMLEFT" , 0 , - 8 );
392323 reagentLabel :SetText (SPELL_REAGENTS or " Reagents:" );
393324 f .reagentLabel = reagentLabel ;
394325
395- -- Reagent slots: two columns, four rows — Blizzard's exact geometry
396- -- (TradeSkillReagentN off QuestItemTemplate): 39px icons, reagent1 at the
397- -- label's BOTTOMLEFT (-5,-3), 147px horizontal pitch (button width), 43px
398- -- vertical (41px button + 2px gap). Count at the icon's bottom-right, name
399- -- (90px) to its right.
400326 f .reagents = {};
401327 for i = 1 , NUM_REAGENTS do
402328 local rowN = math.floor ((i - 1 ) / 2 );
@@ -406,19 +332,13 @@ local function CreateFrame_TradeSkillLink()
406332 btn :SetPoint (" TOPLEFT" , reagentLabel , " BOTTOMLEFT" ,
407333 col * 147 - 5 , - 3 - rowN * 43 );
408334 btn :SetNormalTexture (" Interface\\ Icons\\ INV_Misc_QuestionMark" );
409- -- Name plate behind each reagent — QuestItemTemplate's $parentNameFrame
410- -- (UI-QuestItemNameFrame, 128x64, LEFT of the icon's RIGHT at x=-10).
411335 local plate = btn :CreateTexture (nil , " BACKGROUND" );
412336 plate :SetTexture (" Interface\\ QuestFrame\\ UI-QuestItemNameFrame" );
413337 plate :SetSize (128 , 64 );
414338 plate :SetPoint (" LEFT" , btn , " RIGHT" , - 10 , 0 );
415339 local cnt = btn :CreateFontString (nil , " ARTWORK" , " NumberFontNormal" );
416340 cnt :SetPoint (" BOTTOMRIGHT" , - 4 , 1 );
417341 btn .count = cnt ;
418- -- Name anchored to the plate (LEFT + 15), exactly like the template.
419- -- The 90x36 box + MIDDLE vertical justify is what keeps the name
420- -- centered on the icon whether it's one line or wraps to two (the
421- -- template's $parentName carries the same explicit size).
422342 local nm = btn :CreateFontString (nil , " ARTWORK" , " GameFontHighlight" );
423343 nm :SetPoint (" LEFT" , plate , " LEFT" , 15 , 0 );
424344 nm :SetSize (90 , 36 );
@@ -437,14 +357,7 @@ local function CreateFrame_TradeSkillLink()
437357 f .reagents [i ] = btn ;
438358 end
439359
440- -- Populate the detail pane for `entry` (a recipe from the list). Item
441- -- name/icon/link come from the Item mixin; uncached items re-render this
442- -- pane via ContinueOnItemLoad (guarded against a newer selection). On-hand
443- -- counts from GetItemCount. Enchants (createdItem 0) show the spell instead.
444360 function f :RenderDetail (entry )
445- -- Fetch an item's name/icon/link via the Item mixin. If its data isn't
446- -- cached yet, re-render this pane when it loads — but only if this recipe
447- -- is still the selected one (a later selection must not be clobbered).
448361 local function itemInfo (id )
449362 local item = Item :CreateFromItemID (id );
450363 if not item :IsItemDataCached () then
@@ -457,9 +370,6 @@ local function CreateFrame_TradeSkillLink()
457370 return item :GetItemName (), item :GetItemIcon (), item :GetItemLink ();
458371 end
459372
460- -- Product: item icon/name for craft recipes, spell icon/name for
461- -- enchants. Name is coloured by difficulty band, like the list row and
462- -- the real window's skill-name.
463373 local prodTex , prodText , prodLink ;
464374 local created = entry .createdItem or 0 ;
465375 if created > 0 then
@@ -468,12 +378,9 @@ local function CreateFrame_TradeSkillLink()
468378 prodTex = tex ;
469379 prodLink = link ;
470380 else
471- -- Enchant / non-item recipe: use the spell's presentation.
472381 prodText = entry .name ;
473382 prodTex = C_Spell .GetSpellTexture (entry .spellID );
474383 end
475- -- Enchants carry a spell description (white); item recipes don't, so
476- -- the description collapses and the reagents move up under the icon.
477384 if created > 0 then
478385 self .prodDesc :SetText (" " );
479386 else
@@ -482,8 +389,6 @@ local function CreateFrame_TradeSkillLink()
482389 self .prodIcon :SetNormalTexture (prodTex or
483390 " Interface\\ Icons\\ INV_Misc_QuestionMark" );
484391 self .prodName :SetText (prodText or " " );
485- -- The skill name is always the default gold, like the real window
486- -- (Blizzard never difficulty-colours the detail's product name).
487392 self .prodName :SetTextColor (NORMAL_FONT_COLOR :GetRGB ());
488393 self .prodIcon .itemLink = prodLink ; -- item tooltip when created > 0
489394 self .prodIcon .spellID = entry .spellID ; -- else spell tooltip
@@ -559,14 +464,10 @@ local function CreateFrame_TradeSkillLink()
559464 row :SetText (entry .name or " " );
560465 local r , g , b = BAND_COLOR [entry .band or 3 ]:GetRGB ();
561466 if self .selectedSpellID and entry .spellID == self .selectedSpellID then
562- -- Selected: Blizzard's highlight texture tinted to the
563- -- difficulty colour (its own translucency sets the intensity),
564- -- text white.
565467 row .select :SetVertexColor (r , g , b );
566468 row .select :Show ();
567469 row :SetTextColor (1 , 1 , 1 );
568470 else
569- -- Unselected: no bar, text in the difficulty colour.
570471 row .select :Hide ();
571472 row :SetTextColor (r , g , b );
572473 end
@@ -649,8 +550,6 @@ local function ShowTradeSkillLink(link, text)
649550
650551 frame :ClearDetail ();
651552 frame :Show ();
652- -- Build the subclass dropdown (fills in async as uncached crafted items
653- -- load, via the Item mixin) then the visible list, then auto-select row 1.
654553 RefreshSubclasses ();
655554 frame :ApplyFilter ();
656555 local first = frame .displayed and frame .displayed [1 ];
@@ -660,11 +559,6 @@ local function ShowTradeSkillLink(link, text)
660559 return true ;
661560end
662561
663- -- Uncached crafted items no longer need a global GET_ITEM_INFO_RECEIVED
664- -- watcher: the subclass dropdown (RefreshSubclasses) and the detail pane
665- -- (RenderDetail) each register per-item Item-mixin ContinueOnItemLoad
666- -- callbacks that fill themselves in as the data arrives.
667-
668562---- --------------------------------------------------------------------------
669563-- Click interception: handle `trade:` before the engine's SetHyperlink (which
670564-- in 1.12 only knows item:/enchant: and would reject the link).
0 commit comments