Files
2026-07-17 20:30:02 -04:00

226 lines
7.3 KiB
Lua

-- Items panel: money, the 20-slot bag (Bag.add/remove, ordered by
-- Bag.order), gym badges (boolean flags on inventory), and PC Item
-- storage (a plain S.save.pcItems dict, created on first use).
local Bag = require("src.inventory.Bag")
local M = {}
local ROW_H = 20
local LIST_H = 200
local VISIBLE_ROWS = math.floor(LIST_H / ROW_H)
local function mark(S)
S.dirty = true
end
-- Prev/Next pagination (mirrors Events/Dex panels) so bag/PC lists longer
-- than VISIBLE_ROWS stay fully reachable instead of truncating silently.
local function clampScroll(scroll, total)
local maxScroll = math.max(0, total - VISIBLE_ROWS)
scroll = scroll or 0
if scroll > maxScroll then scroll = maxScroll end
if scroll < 0 then scroll = 0 end
return scroll
end
local function pageSlice(items, scroll)
local page = {}
for i = 1, math.min(VISIBLE_ROWS, #items - scroll) do
page[i] = items[scroll + i]
end
return page
end
local function drawPager(Kit, x, y, total, scroll, onPrev, onNext)
if Kit.button(x, y, 90, 26, "Prev") then onPrev() end
if Kit.button(x + 100, y, 90, 26, "Next") then onNext() end
local shown = math.min(VISIBLE_ROWS, math.max(0, total - scroll))
Kit.label(x + 210, y + 5, string.format("%d-%d of %d",
total > 0 and scroll + 1 or 0, scroll + shown, total))
end
local function clamp(n, lo, hi)
if n < lo then return lo end
if n > hi then return hi end
return n
end
local function isBadgeId(id)
return id:find("BADGE", 1, true) ~= nil
end
local function badgeIds(cat)
local ids = {}
for _, id in ipairs(cat.items) do
if isBadgeId(id) then table.insert(ids, id) end
end
return ids
end
local function bagLines(save)
local order = Bag.order(save)
local lines = {}
for i, id in ipairs(order) do
lines[i] = string.format("%-16s x%d", id, save.inventory[id] or 0)
end
return lines, order
end
local function pcItemOrder(pcItems)
local ids = {}
for id in pairs(pcItems) do table.insert(ids, id) end
table.sort(ids)
return ids
end
local function pcLines(pcItems, order)
local lines = {}
for i, id in ipairs(order) do
lines[i] = string.format("%-16s x%d", id, pcItems[id] or 0)
end
return lines
end
local function pcAdd(save, id, qty)
save.pcItems = save.pcItems or {}
local pc = save.pcItems
pc[id] = math.min(99, (pc[id] or 0) + (qty or 1))
end
local function pcRemove(save, id, qty)
local pc = save.pcItems
if not pc or not pc[id] then return end
pc[id] = pc[id] - (qty or 1)
if pc[id] <= 0 then pc[id] = nil end
end
function M.draw(S, Kit, x, y)
S.save.pcItems = S.save.pcItems or {}
-- Money
Kit.label(x, y, "Money: $" .. tostring(S.save.money))
local moneyBtnY = y + 22
if Kit.button(x, moneyBtnY, 60, 26, "-100") then
S.save.money = clamp(S.save.money - 100, 0, 999999); mark(S)
end
if Kit.button(x + 66, moneyBtnY, 60, 26, "-10") then
S.save.money = clamp(S.save.money - 10, 0, 999999); mark(S)
end
if Kit.button(x + 132, moneyBtnY, 60, 26, "+10") then
S.save.money = clamp(S.save.money + 10, 0, 999999); mark(S)
end
if Kit.button(x + 198, moneyBtnY, 60, 26, "+100") then
S.save.money = clamp(S.save.money + 100, 0, 999999); mark(S)
end
-- Item picker (species-like picker over S.cat.items) shared by bag/PC add
local pickerY = moneyBtnY + 40
S.itemPickerIdx = clamp(S.itemPickerIdx or 1, 1, #S.cat.items)
local pickId = S.cat.items[S.itemPickerIdx]
Kit.label(x, pickerY + 5, "Item:")
if Kit.button(x + 46, pickerY, 26, 26, "<") then
S.itemPickerIdx = ((S.itemPickerIdx - 2) % #S.cat.items) + 1
end
Kit.label(x + 82, pickerY + 5, pickId)
if Kit.button(x + 280, pickerY, 26, 26, ">") then
S.itemPickerIdx = (S.itemPickerIdx % #S.cat.items) + 1
end
if Kit.button(x + 320, pickerY, 110, 26, "Add to Bag") then
if Bag.add(S.save, pickId, 1) then mark(S) end
end
if Kit.button(x + 440, pickerY, 110, 26, "Add to PC") then
pcAdd(S.save, pickId, 1); mark(S)
end
-- Bag list
local bagLabelY = pickerY + 40
Kit.label(x, bagLabelY, string.format("Bag (%d/%d slots)", Bag.slots(S.save), Bag.CAPACITY))
local bagListY = bagLabelY + 20
local lines, order = bagLines(S.save)
S.selectedBagIdx = clamp(S.selectedBagIdx or 1, 1, math.max(#order, 1))
S.bagScroll = clampScroll(S.bagScroll, #order)
local bagClick = Kit.list(x, bagListY, 300, LIST_H, pageSlice(lines, S.bagScroll),
S.selectedBagIdx - S.bagScroll, ROW_H)
if bagClick then S.selectedBagIdx = S.bagScroll + bagClick end
local bagPagerY = bagListY + LIST_H + 8
drawPager(Kit, x, bagPagerY, #order, S.bagScroll,
function() S.bagScroll = clampScroll(S.bagScroll - VISIBLE_ROWS, #order) end,
function() S.bagScroll = clampScroll(S.bagScroll + VISIBLE_ROWS, #order) end)
local bagActionsY = bagPagerY + 34
if Kit.button(x, bagActionsY, 100, 28, "Remove 1") then
local id = order[S.selectedBagIdx]
if id then
Bag.remove(S.save, id, 1)
S.selectedBagIdx = clamp(S.selectedBagIdx, 1, math.max(#Bag.order(S.save), 1))
mark(S)
end
end
if Kit.button(x + 110, bagActionsY, 100, 28, "Remove all") then
local id = order[S.selectedBagIdx]
if id then
Bag.remove(S.save, id, S.save.inventory[id])
S.selectedBagIdx = clamp(S.selectedBagIdx, 1, math.max(#Bag.order(S.save), 1))
mark(S)
end
end
-- PC items list (mirrors bag UX; plain dict, no slot cap)
local pcLabelY = bagActionsY + 40
local pcOrder = pcItemOrder(S.save.pcItems)
Kit.label(x, pcLabelY, string.format("PC Items (%d kinds)", #pcOrder))
local pcListY = pcLabelY + 20
S.selectedPcIdx = clamp(S.selectedPcIdx or 1, 1, math.max(#pcOrder, 1))
S.pcScroll = clampScroll(S.pcScroll, #pcOrder)
local pcClick = Kit.list(x, pcListY, 300, LIST_H,
pageSlice(pcLines(S.save.pcItems, pcOrder), S.pcScroll),
S.selectedPcIdx - S.pcScroll, ROW_H)
if pcClick then S.selectedPcIdx = S.pcScroll + pcClick end
local pcPagerY = pcListY + LIST_H + 8
drawPager(Kit, x, pcPagerY, #pcOrder, S.pcScroll,
function() S.pcScroll = clampScroll(S.pcScroll - VISIBLE_ROWS, #pcOrder) end,
function() S.pcScroll = clampScroll(S.pcScroll + VISIBLE_ROWS, #pcOrder) end)
local pcActionsY = pcPagerY + 34
if Kit.button(x, pcActionsY, 100, 28, "Remove 1") then
local id = pcOrder[S.selectedPcIdx]
if id then
pcRemove(S.save, id, 1)
pcOrder = pcItemOrder(S.save.pcItems)
S.selectedPcIdx = clamp(S.selectedPcIdx, 1, math.max(#pcOrder, 1))
mark(S)
end
end
if Kit.button(x + 110, pcActionsY, 100, 28, "Remove all") then
local id = pcOrder[S.selectedPcIdx]
if id then
pcRemove(S.save, id, S.save.pcItems[id])
pcOrder = pcItemOrder(S.save.pcItems)
S.selectedPcIdx = clamp(S.selectedPcIdx, 1, math.max(#pcOrder, 1))
mark(S)
end
end
-- Badges: boolean flags directly on inventory, toggled by click
local badgeLabelY = pcActionsY + 40
Kit.label(x, badgeLabelY, "Badges (click to toggle)")
local badgeY = badgeLabelY + 20
local ids = badgeIds(S.cat)
for i, id in ipairs(ids) do
local col = (i - 1) % 4
local row = math.floor((i - 1) / 4)
local bx = x + col * 150
local by = badgeY + row * 30
local on = S.save.inventory[id] == true
if Kit.button(bx, by, 144, 26, id .. (on and " [X]" or "")) then
if on then S.save.inventory[id] = nil else S.save.inventory[id] = true end
mark(S)
end
end
end
return M