✓ Selection States
Gamepad users select slots and perform actions through a state machine. Each state represents a step in the selection flow, from idle to completing actions like swap, drop, or quick move.
State Overview
The selection state machine
Step 0: Idle
Ready to select a slot
🎒 SELECTING
D-Pad selects slot
↓
Step 1: Source Selected
First slot chosen, waiting for target
🎒 SWAP - SELECT TARGET
From Source State
State Details
What happens in each state
| State | Step | Description | Enabled Actions |
|---|---|---|---|
Idle |
0 | Waiting for user to select a slot with D-Pad | D-Pad navigation, B to cancel |
Source |
1 | Source slot selected, waiting for target or action | Y: Swap, X: Drop, A: QuickMove, B: Cancel |
Dropping |
2 | Adjusting drop amount with D-Pad Up/Down | DPadUp/Down: Amount, A: Drop, B: Cancel |
Actions
What each action does
Y
Swap
Swap the source item with the currently selected slot.
Select source → Y → Select target → Items swapped
X
Drop
Drop the selected item with configurable amount.
Select item → X → Adjust amount → A to confirm
A + R1
Quick Move
Move item to first empty slot in the other container.
Hotbar item → A+R1 → Moves to Storage
Storage item → A+R1 → Moves to Hotbar
B
Cancel
Cancel current selection and return to Idle state.
Any state → B → Clear selection
Code Structure
SelectionManager implementation
Selection State
Luau
local SelectionState = {
enabled = false,
step = 0, -- 0: idle, 1: source, 2: dropping
sourceType = nil, -- "Hotbar" | "Storage"
sourceSlot = nil, -- Slot index
sourceFrame = nil, -- Frame reference
}
Get Slot Info
Luau
function SelectionManager.GetSelectedSlotInfo()
local selected = GuiService.SelectedObject
if not selected then return nil end
local slotFrame = selected.Parent
local slotType
if slotFrame.Parent.Name == "Hotbar" then
slotType = "Hotbar"
elseif slotFrame.Parent.Name == "ScrollingFrame" then
slotType = "Storage"
end
local slotName = slotFrame.Name:gsub("_", "")
local slotIndex = tonumber(slotName)
return {
Type = slotType,
Index = slotIndex,
Frame = slotFrame
}
end
Swap Handler
Step-by-step swap logic
HandleSwap Logic
Luau
function SelectionManager.HandleSwap()
local selected = SelectionManager.GetSelectedSlotInfo()
if not selected then return end
-- Step 0: Select source
if SelectionState.step == 0 then
SelectionState.step = 1
SelectionState.sourceType = selected.Type
SelectionState.sourceSlot = selected.Index
SelectionState.sourceFrame = selected.Frame
SelectionManager.ApplySelectionHighlight(selected.Frame)
SelectionManager.NotifyStateChanged()
-- Step 1: Select target and swap
elseif SelectionState.step == 1 then
-- Same slot = cancel
if SelectionState.sourceType == selected.Type
and SelectionState.sourceSlot == selected.Index then
SelectionManager.CancelSelection()
return
end
-- Perform swap
InventoryController.Swap(
SelectionState.sourceType,
SelectionState.sourceSlot,
selected.Type,
selected.Index,
true
)
SelectionManager.CancelSelection()
end
end
Drop Handler
Drop with amount selection
HandleDrop Logic
Luau
function SelectionManager.HandleDrop()
local selected = SelectionManager.GetSelectedSlotInfo()
if not selected then return end
-- Get item data
local store = require(script.Parent.Parent.CoreState.InventoryStore)
local item = store:GetItemFromSlot(selected.Type, selected.Index)
if not item then return end
-- Enter dropping state
SelectionState.step = 2
SelectionManager.NotifyStateChanged()
-- Disable inventory, enable drop context
InputManager.SetInventoryEnabled(false)
InputManager.SetDropEnabled(true)
SelectionManager.LoadDropBinds()
-- Show drop UI
ConsoleDropUI.Show(item, 1)
-- Set up callbacks
ConsoleDropUI.OnDrop = function(amount)
InventoryController.Drop(selected.Type, selected.Index, amount, true)
SelectionManager.CloseDropUI()
end
ConsoleDropUI.OnDropAll = function()
InventoryController.Drop(selected.Type, selected.Index, item.Amount, true)
SelectionManager.CloseDropUI()
end
ConsoleDropUI.OnCancel = function()
SelectionManager.CloseDropUI()
end
end
Hooks Integration
Firing hooks on selection changes
SelectionManager fires hooks when slots are selected/deselected:
Selection Hooks
Luau
-- Apply highlight when slot is selected
function SelectionManager.ApplySelectionHighlight(frame)
if HookManager then
HookManager:Fire("OnSelect", frame)
end
end
-- Clear highlight when slot is deselected
function SelectionManager.ClearSelectionHighlight(frame)
if HookManager then
HookManager:Fire("OnDeselect", frame)
end
end
| Hook | Arguments | Fired When |
|---|---|---|
OnSelect |
frame |
Slot is selected (step 0 → 1) |
OnDeselect |
frame |
Selection is cleared |
Related Documentation
See also