Skip to content

Enchanting table fixes, merchant panel gamepad buttons, bounty map pin icons and rewards - #37

Open
ksavila wants to merge 12 commits into
MidnightsFX:mfx/0_15_setsfrom
ksavila:ksavila/enchant_table_set_marker
Open

ksavila wants to merge 12 commits into
MidnightsFX:mfx/0_15_setsfrom
ksavila:ksavila/enchant_table_set_marker

Conversation

@ksavila

@ksavila ksavila commented Oct 2, 2026 •

Copy link
Copy Markdown

Changes to the enchanting table, the merchant panel's gamepad controls, the bounty map pins, inventory tooltips on a gamepad and two loot config rules.

Set item marker

Set items carry a rune marker in the inventory grid, but the enchanting table showed them with nothing to tell them apart. This puts the same marker on item icons in the table.

  • Every tab's item rows go through MultiSelectItemListElement, so one call there covers the whole table (list rows and grid cells).
  • Same sprite and Set Item Color as the inventory, including the Auga sprite, and the same items: magic set pieces and vanilla sets.
  • The marker is a child of the icon sized by anchors, so it scales with whatever size the row gives the icon. Rows are pooled, so it is updated on every SetItem, empty rows included.
  • It sits 15% of the icon's height lower than in the inventory. The inventory sprite leaves room under the rune for the durability bar, which the table does not draw.

The inventory marker itself is unchanged.

Messages when an action cannot go through

With an inventory provider registered (a craft-from-containers mod), an item or the materials a tab is showing can stop being reachable while the tab is open: another player opens the chest, or takes the item out of it. The table already refused to pay out for something it could not take, but it did so silently, so the button just did nothing.

  • Item gone. Sacrifice, identify, enchant, disenchant, augment and the rune tab (target item, rune or set rune) now show "No longer available: ". Sacrifice and identify name every selected item that could not be removed, in one message.
  • Materials gone. Enchant, augment, disenchant, convert and upgrade now show the vanilla missing requirements message when the cost can no longer be paid at the moment the button is pressed. Identify and the rune tab already did.
  • Upgrades are charged up front. The table used to be upgraded first and the cost charged when the response came back, so an upgrade whose materials became unreachable in between went through unpaid. The cost is now taken before the request and refunded to the player's inventory if the table refuses it.
  • A refused upgrade no longer says "upgraded". It showed "upgraded to level N" whether or not the request succeeded. It now shows " could not be upgraded".
  • InventoryManagement.RemoveItem returns how many it removed instead of void, as RemoveExactItem already does.

Two new strings in English.json: mod_epicloot_item_unavailable and mod_epicloot_upgradefailedmessage.

Known gap: if the response to an upgrade request never arrives (the table's owner disconnects mid-request), the materials stay spent.

Upgrade tab refresh on a client that does not own the table

After an upgrade, the upgrade tab kept showing the cost of the level that had just been bought until the table was closed and reopened. Only the table's owner writes the new level and raises the level changed events. Any other client refreshed on the success response, which arrives before the ZDO sync that carries the new level, and nothing refreshed again when the sync landed.

  • EnchantingTable now keeps the last feature levels it saw and re-reads them whenever the ZDO's data revision moves, raising OnFeatureLevelChanged and OnAnyFeatureLevelChanged for any that changed.
  • That covers the upgrade tab's cost list and level text, the tab stars and the decorations on the table itself, including when another player upgrades a table you have open or are standing next to.
  • The owner updates the same cache when it writes the level, so its events fire as before.
  • Together with the up front charge above: a second press against the stale cost list was already refused and refunded, and the list no longer goes stale in the first place.

Disenchant tab no longer lists unidentified items

An unidentified item is magic, so it passed the disenchant check and showed up in the disenchant tab. Unidentified items are now excluded there.

Equipped sort on the augment tab

The augment tab's sort dropdown has a fourth option, Equipped, that lists equipped and hotbar items first. Within each group the items are ordered by rarity, then by name.

  • MultiSelectItemList.SortMode gains Equipped, sorted by EnchantingUIController.SortByEquipped.
  • The option is added to the dropdown at runtime by AddEquippedSortMode, which AugmentUI calls in Awake, so the prefab is untouched and the other tabs keep their three options.
  • The dropdown value is cast straight to SortMode, so the option is only added when the prefab's dropdown has exactly the three existing options before it.

One new string in English.json: mod_epicloot_enchanting_equipped.

Gamepad focus when every list is empty

When every list on a tab was empty, the focus controller took focus away from each list in turn and nothing got it back once a list refilled, so the gamepad had no row selected until the tab was reopened.

  • With every list empty, the focused list now keeps focus.
  • When a list refills, the first row is focused again and the hints refresh.

Right stick scrolls the products list

On the sacrifice and identify tab the products list had no gamepad scrolling, so a long list of products could not be read with a controller.

  • GamepadScroll.ApplyRightStickY has a ScrollRect overload next to the Scrollbar one. It scrolls by pixels per second, so the speed does not depend on the list's length or the frame rate.
  • MultiSelectItemList.ScrollWithRightStick exposes it, and SacrificeUI calls it on the products list.

Right stick scrolls inventory item tooltips

A long item tooltip could only be scrolled with the mouse wheel, so on a controller the bottom of it could not be read.

  • ScrollWheelHandler now also applies the right stick to the tooltip's scroll rect while a gamepad is active, through the same GamepadScroll.ApplyRightStickY overload as the products list.
  • It only does so when the tooltip's owner sits in an InventoryGrid, so tooltips anywhere else are unaffected. The check is cached per tooltip owner.

Merchant panel gamepad buttons

  • A confirms, X abandons. The focused list's action button was on X and abandoning a bounty on Y. They are now on A and X.
  • Abandon dialog glyphs. The Yes and No buttons show the A and B glyphs while a gamepad is active.
  • No row tooltip over the abandon dialog. The row's gamepad tooltip follows the EventSystem selection and covered the dialog, which already shows that bounty. The selection is cleared while the dialog is open and restored when it closes.
  • Y no longer closes the gamble result. Y also opens the vanilla inventory. The result dialog now closes on A, B, Escape or the inventory button only.
  • A on the gamble result does not buy again. The A press that closes the result is consumed, so the merchant panel underneath does not read it as a second gamble purchase.
  • The store closes with a dialog open. Vanilla opens the inventory on Y whatever the panel is showing, and StoreGui.Update is what closes the store under it. That update was skipped while a dialog was open, so the store stayed up behind the inventory. It now runs whenever the inventory is visible.

Bounty map pins

  • Trophy icon. A bounty's pin shows the trophy of its target instead of the generic bounty icon.
  • Gold rim. A bounty that rewards gold tokens gets a gold-rimmed area circle. The sprite is generated once at runtime with the vanilla area fill colour.
  • Rewards under the name. Once the large map is zoomed in to the default level or closer, each bounty pin lists its reward icons and counts (iron tokens, gold tokens, coins) under the name. The row is created the first time the pin's name label is visible at that zoom and hidden again when zoomed out.
  • Both places that create a bounty pin now go through MinimapController.CreateBountyPinInfo.

Loot config

  • Dvergr tankard and lantern are not enchantable. Both are added to RestrictedItems in loottables.json, by item name and by prefab name, next to the other tankards.
  • Lumberjacking Drop only rolls on axes. Its only requirement was chop damage, which crossbows also have. It now also requires the Axes skill type, in the balanced, legendary and minimal overhauls.

No prefab or bundle changes.

Testing

The set marker was checked in game on the enchanting table.

The upgrade tab refresh on a client that does not own the table builds, but has not been checked in game yet.

The messages were tested with two clients on one server, both on this build with a craft-from-containers mod registered as an inventory provider. Player A is at the table with linked chests in range; player B is at the chest. A does not switch tabs or reselect after B acts.

Item gone (A selects the chest item, B takes it or leaves the chest open, A presses the button)

  1. Sacrifice an enchanted sword: "No longer available", no products, no socket stones, B keeps the sword, the list refreshes.
  2. Sacrifice two items, one from A's inventory and one from the chest: only the inventory item pays out and the message names only the chest item.
  3. Identify an unidentified item: message, nothing consumed, no cost charged.
  4. Enchant, disenchant and augment a chest item: message, no materials spent, item unchanged.
  5. Rune tab with the target item in the chest: the message names the item.
  6. Rune tab, etching with a rune and a set rune from the chest: the message names the rune and nothing is spent.

Materials gone (A carries the item, the materials are only in the chest; A selects, B opens the chest, A presses)

  1. Enchant, augment, disenchant: missing requirements message, nothing changes, selection kept.
  2. Convert: message, nothing converted, selection cleared.
  3. Upgrade: message, no upgrade, the button greys out.

Upgrade tab

  1. Materials in the inventory: charged once, "upgraded to level N", level rises.
  2. Materials in a chest, then split between inventory and chest: inventory spent first, the chest covers the rest, charged once.
  3. Unlocking a locked feature: "unlocked!", charged once.
  4. With the no-cost cheat on: the upgrade works and nothing is charged.
  5. Two players pressing Upgrade on the same feature at the same moment: the loser sees "could not be upgraded" and gets the materials back; the winner is charged once.

Regression, single player

  1. Without an inventory provider: one normal action per tab works, charges the exact cost and shows no new messages.
  2. A merchant purchase and a treasure map purchase still charge correctly.
  3. In a non-English language the new messages show text, not a bracketed key.

@ksavila ksavila changed the title Show the set item marker on enchanting table item icons Enchanting table: set item marker on icons, messages when an action cannot go through Oct 3, 2026
…an upgrade syncs in on a client that does not own the table
@ksavila

ksavila commented Oct 4, 2026

Copy link
Copy Markdown
Author
image image

@ksavila ksavila changed the title Enchanting table: set item marker on icons, messages when an action cannot go through Enchanting table fixes, merchant panel gamepad buttons, bounty map pin icons and rewards Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant