mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 04:31:09 +02:00
Honor modded bag capacity
This commit is contained in:
@@ -12,7 +12,7 @@ this port.
|
|||||||
|
|
||||||
| # | Mechanic | Value | Why the Game Boy had this limit | Where it lives here |
|
| # | Mechanic | Value | Why the Game Boy had this limit | Where it lives here |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| 1 | Bag capacity | 20 item slots | `wNumBagItems` save block was a fixed 20-entry id/quantity array in SRAM | `src/inventory/Bag.lua:8` (`Bag.CAPACITY = 20`) |
|
| 1 | Bag capacity | 20 item slots by default | `wNumBagItems` save block was a fixed 20-entry id/quantity array in SRAM | `Data.constants.bagSize`, read by `src/inventory/Bag.lua` (`Bag.capacity`) |
|
||||||
| 2 | Party size | 6 Pokémon | `wPartyMon1..6` were 6 fixed save-RAM slots | `src/pokemon/Party.lua:5` (`Party.MAX = 6`) |
|
| 2 | Party size | 6 Pokémon | `wPartyMon1..6` were 6 fixed save-RAM slots | `src/pokemon/Party.lua:5` (`Party.MAX = 6`) |
|
||||||
| 3 | PC storage | 12 boxes × 20 Pokémon | `wBoxDataStart` / Bill's PC allocated a fixed 12×20 SRAM block | `src/pokemon/Boxes.lua:7-8` |
|
| 3 | PC storage | 12 boxes × 20 Pokémon | `wBoxDataStart` / Bill's PC allocated a fixed 12×20 SRAM block | `src/pokemon/Boxes.lua:7-8` |
|
||||||
| 4 | Moves per Pokémon | 4 | Fixed 4-move-slot field in the party/box Pokémon struct | `src/pokemon/Pokemon.lua:20`, enforced again in `src/battle/BattleState.lua:1941` |
|
| 4 | Moves per Pokémon | 4 | Fixed 4-move-slot field in the party/box Pokémon struct | `src/pokemon/Pokemon.lua:20`, enforced again in `src/battle/BattleState.lua:1941` |
|
||||||
@@ -38,6 +38,10 @@ this port.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
- Mods may patch `constants.bagSize` through the public content registry. The
|
||||||
|
native `save.lua` format keeps every existing item when the configured
|
||||||
|
limit changes; exporting to a cartridge `.sav` still writes only the first
|
||||||
|
20 bag slots because the original SRAM layout has no room for more.
|
||||||
- PC Box **overflow handling** was deliberately changed even though the
|
- PC Box **overflow handling** was deliberately changed even though the
|
||||||
20×12 box *shape* was kept faithful: instead of Gen 1's "full box discards
|
20×12 box *shape* was kept faithful: instead of Gen 1's "full box discards
|
||||||
or blocks the deposit," this port spills into the next box with room.
|
or blocks the deposit," this port spills into the next box with room.
|
||||||
|
|||||||
@@ -380,7 +380,8 @@ semantics - so the two windows read as one app. Six tabs:
|
|||||||
party dock, so deposit and withdraw live in one place. Empty slots are
|
party dock, so deposit and withdraw live in one place. Empty slots are
|
||||||
clickable and create a mon there.
|
clickable and create a mon there.
|
||||||
- **Items**: money, a searchable item picker (replacing the arrows that
|
- **Items**: money, a searchable item picker (replacing the arrows that
|
||||||
cycled one id at a time through ~250 items), the 20-slot bag, PC storage
|
cycled one id at a time through ~250 items), the configurable bag (20 slots
|
||||||
|
by default), PC storage
|
||||||
with no slot cap, and the eight badges as toggle chips.
|
with no slot cap, and the eight badges as toggle chips.
|
||||||
- **Events**: flags, defeated trainers, taken items and per-map object
|
- **Events**: flags, defeated trainers, taken items and per-map object
|
||||||
toggles, with a real filter field and a two-column paged grid.
|
toggles, with a real filter field and a two-column paged grid.
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ return function(mod)
|
|||||||
caughtAreas()[areaKey(self.game, self)] = "DUPES_LOST"
|
caughtAreas()[areaKey(self.game, self)] = "DUPES_LOST"
|
||||||
mod.save:set("caught_areas", caughtAreas())
|
mod.save:set("caught_areas", caughtAreas())
|
||||||
end
|
end
|
||||||
Bag.add(self.game.save, ball, 1)
|
Bag.add(self.game.save, ball, 1, self.game.data)
|
||||||
self:say(reason == "area" and "This area already\nhas a captured POKéMON!"
|
self:say(reason == "area" and "This area already\nhas a captured POKéMON!"
|
||||||
or "You already have\nthis POKéMON family!")
|
or "You already have\nthis POKéMON family!")
|
||||||
return
|
return
|
||||||
|
|||||||
+5
-5
@@ -14,12 +14,12 @@ local MODULES = {
|
|||||||
-- Optional for compatibility with developer and stale caches.
|
-- Optional for compatibility with developer and stale caches.
|
||||||
local OPTIONAL = { "audio", "palettes", "icons" }
|
local OPTIONAL = { "audio", "palettes", "icons" }
|
||||||
|
|
||||||
-- The rules the engine still carries as literals. The constants registry
|
-- Vanilla defaults for rules exposed through the constants registry. A
|
||||||
-- deep-merges over these, so a value has to exist before a mod can patch
|
-- value has to exist before a mod can patch it; each one matches the
|
||||||
-- it; each one is the number the engine hard-codes today, so seeding them
|
-- engine's no-mod behavior, so seeding them changes nothing on a vanilla
|
||||||
-- changes nothing on a mod-free boot.
|
-- boot.
|
||||||
local CONSTANT_DEFAULTS = {
|
local CONSTANT_DEFAULTS = {
|
||||||
bagSize = 20, -- BAG_ITEM_CAPACITY (src/inventory/Bag.lua)
|
bagSize = 20, -- BAG_ITEM_CAPACITY (Bag.capacity fallback)
|
||||||
partyMax = 6, -- PARTY_LENGTH (src/pokemon/Party.lua)
|
partyMax = 6, -- PARTY_LENGTH (src/pokemon/Party.lua)
|
||||||
boxCount = 12, boxSize = 20, -- Bill's PC (src/pokemon/Boxes.lua)
|
boxCount = 12, boxSize = 20, -- Bill's PC (src/pokemon/Boxes.lua)
|
||||||
moveMax = 4,
|
moveMax = 4,
|
||||||
|
|||||||
@@ -1058,7 +1058,7 @@ local function reclaim(save, data, report)
|
|||||||
if type(entry) == "table" and known(data.items, entry.id) then
|
if type(entry) == "table" and known(data.items, entry.id) then
|
||||||
table.remove(orphaned.items, i)
|
table.remove(orphaned.items, i)
|
||||||
if entry.from == "pcItems" or type(save.inventory) ~= "table"
|
if entry.from == "pcItems" or type(save.inventory) ~= "table"
|
||||||
or not Bag.add(save, entry.id, entry.count or 1) then
|
or not Bag.add(save, entry.id, entry.count or 1, data) then
|
||||||
save.pcItems = save.pcItems or {}
|
save.pcItems = save.pcItems or {}
|
||||||
save.pcItems[entry.id] = (save.pcItems[entry.id] or 0) + (entry.count or 1)
|
save.pcItems[entry.id] = (save.pcItems[entry.id] or 0) + (entry.count or 1)
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -214,7 +214,7 @@ function VERBS.give(self, rest)
|
|||||||
end
|
end
|
||||||
elseif game.data.items and game.data.items[id] then
|
elseif game.data.items and game.data.items[id] then
|
||||||
local n = tonumber(count) or 1
|
local n = tonumber(count) or 1
|
||||||
if require("src.inventory.Bag").add(save, id, n) then
|
if require("src.inventory.Bag").add(save, id, n, game.data) then
|
||||||
self:print(("%s x%d added"):format(id, n))
|
self:print(("%s x%d added"):format(id, n))
|
||||||
else
|
else
|
||||||
self:print("bag full")
|
self:print("bag full")
|
||||||
|
|||||||
+23
-7
@@ -1,11 +1,26 @@
|
|||||||
-- The 20-slot bag (BAG_ITEM_CAPACITY, constants/menu_constants.asm):
|
-- The bag defaults to 20 slots (BAG_ITEM_CAPACITY,
|
||||||
-- a distinct item id occupies one slot regardless of quantity; badges
|
-- constants/menu_constants.asm), but mods may replace that limit through
|
||||||
-- live in the inventory table but are not bag items. save.bagOrder
|
-- Data.constants.bagSize. A distinct item id occupies one slot regardless
|
||||||
-- keeps acquisition order like wBagItems (SELECT can reorder it).
|
-- of quantity; badges live in the inventory table but are not bag items.
|
||||||
|
-- save.bagOrder keeps acquisition order like wBagItems (SELECT can reorder
|
||||||
|
-- it).
|
||||||
|
|
||||||
local Bag = {}
|
local Bag = {}
|
||||||
|
|
||||||
Bag.CAPACITY = 20
|
local DEFAULT_CAPACITY = 20
|
||||||
|
|
||||||
|
-- `data` is injectable for the save editor and headless mod tests. Normal
|
||||||
|
-- gameplay may omit it because the loader merges mods into the Data
|
||||||
|
-- singleton before any item can be added. The fallback keeps old/stale
|
||||||
|
-- generated caches and isolated callers at the vanilla limit.
|
||||||
|
function Bag.capacity(data)
|
||||||
|
data = data or require("src.core.Data")
|
||||||
|
local configured = data and data.constants and data.constants.bagSize
|
||||||
|
if type(configured) == "number" and configured >= 1 then
|
||||||
|
return math.floor(configured)
|
||||||
|
end
|
||||||
|
return DEFAULT_CAPACITY
|
||||||
|
end
|
||||||
|
|
||||||
local function isBadge(id)
|
local function isBadge(id)
|
||||||
return id:find("BADGE", 1, true) ~= nil
|
return id:find("BADGE", 1, true) ~= nil
|
||||||
@@ -55,9 +70,10 @@ end
|
|||||||
-- Add qty of an item; returns false (and adds nothing) when a new slot
|
-- Add qty of an item; returns false (and adds nothing) when a new slot
|
||||||
-- is needed and the bag is full, or when the stack would pass 99
|
-- is needed and the bag is full, or when the stack would pass 99
|
||||||
-- (AddItemToInventory's per-slot quantity cap).
|
-- (AddItemToInventory's per-slot quantity cap).
|
||||||
function Bag.add(save, id, qty)
|
function Bag.add(save, id, qty, data)
|
||||||
local inv = save.inventory
|
local inv = save.inventory
|
||||||
if not inv[id] and not isBadge(id) and Bag.slots(save) >= Bag.CAPACITY then
|
if not inv[id] and not isBadge(id)
|
||||||
|
and Bag.slots(save) >= Bag.capacity(data) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if not isBadge(id) and (inv[id] or 0) + (qty or 1) > 99 then
|
if not isBadge(id) and (inv[id] or 0) + (qty or 1) > 99 then
|
||||||
|
|||||||
@@ -210,11 +210,12 @@ end
|
|||||||
-- text (label or literal; {RAM:wStringBuffer} becomes the item name);
|
-- text (label or literal; {RAM:wStringBuffer} becomes the item name);
|
||||||
-- pass false when the script shows its own received-text row.
|
-- pass false when the script shows its own received-text row.
|
||||||
function Commands.give_item(ctx, itemId, count, gotText)
|
function Commands.give_item(ctx, itemId, count, gotText)
|
||||||
-- the 20-slot bag can refuse (BAG_ITEM_CAPACITY): say so and halt
|
-- the bag can refuse at its configured capacity (20 in vanilla): halt
|
||||||
-- the script, so later set_flag rows don't burn the gift -- make
|
-- the script, so later set_flag rows don't burn the gift -- make
|
||||||
-- room and talk again, like the original (pokered's `jr nc, .bag_full`
|
-- room and talk again, like the original (pokered's `jr nc, .bag_full`
|
||||||
-- skips the received text entirely when AddItemToInventory refuses)
|
-- skips the received text entirely when AddItemToInventory refuses)
|
||||||
if not require("src.inventory.Bag").add(ctx.save, itemId, count or 1) then
|
if not require("src.inventory.Bag").add(
|
||||||
|
ctx.save, itemId, count or 1, ctx.game.data) then
|
||||||
Commands.show_text(ctx, ctx.game.data.text
|
Commands.show_text(ctx, ctx.game.data.text
|
||||||
and ctx.game.data.text._BagFullText or Strings("You can't carry\nany more items!"))
|
and ctx.game.data.text._BagFullText or Strings("You can't carry\nany more items!"))
|
||||||
return math.huge
|
return math.huge
|
||||||
|
|||||||
+1
-1
@@ -76,7 +76,7 @@ local function withdraw(game)
|
|||||||
onChoose = function(item, list)
|
onChoose = function(item, list)
|
||||||
askQuantity(game, list, pc[item.value] or 1, item.value, function(qty)
|
askQuantity(game, list, pc[item.value] or 1, item.value, function(qty)
|
||||||
local Bag = require("src.inventory.Bag")
|
local Bag = require("src.inventory.Bag")
|
||||||
if not Bag.add(game.save, item.value, qty) then
|
if not Bag.add(game.save, item.value, qty, game.data) then
|
||||||
list.footer = Strings("You can't carry\nany more items.")
|
list.footer = Strings("You can't carry\nany more items.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ local function buy(game, stock)
|
|||||||
list.footer = notEnough
|
list.footer = notEnough
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if not Bag.add(game.save, item.value, qty) then
|
if not Bag.add(game.save, item.value, qty, game.data) then
|
||||||
list.footer = txt(game, "_PokemartItemBagFullText",
|
list.footer = txt(game, "_PokemartItemBagFullText",
|
||||||
Strings("You can't carry\nany more items."))
|
Strings("You can't carry\nany more items."))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1803,7 +1803,7 @@ function OverworldState:tryHiddenObject(fx, fy)
|
|||||||
if h.x == fx and h.y == fy then
|
if h.x == fx and h.y == fy then
|
||||||
save.hiddenTaken = save.hiddenTaken or {}
|
save.hiddenTaken = save.hiddenTaken or {}
|
||||||
if save.hiddenTaken[key] then return false end
|
if save.hiddenTaken[key] then return false end
|
||||||
if not require("src.inventory.Bag").add(save, h.item, 1) then
|
if not require("src.inventory.Bag").add(save, h.item, 1, Game.data) then
|
||||||
Game.stack:push(TextBox.new(Game, Strings("You can't carry\nany more items!")))
|
Game.stack:push(TextBox.new(Game, Strings("You can't carry\nany more items!")))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -2423,7 +2423,7 @@ function OverworldState:talkTo(npc)
|
|||||||
-- (e.g. Blue's House wall Town Map / walking Daisy, #11). Lua treats
|
-- (e.g. Blue's House wall Town Map / walking Daisy, #11). Lua treats
|
||||||
-- the string "0" as truthy, so screen it out and fall through to text.
|
-- the string "0" as truthy, so screen it out and fall through to text.
|
||||||
if d.item and d.item ~= "0" and d.item ~= 0 then
|
if d.item and d.item ~= "0" and d.item ~= 0 then
|
||||||
if not require("src.inventory.Bag").add(Game.save, d.item, 1) then
|
if not require("src.inventory.Bag").add(Game.save, d.item, 1, Game.data) then
|
||||||
Game.stack:push(TextBox.new(Game, Strings("You can't carry\nany more items!")))
|
Game.stack:push(TextBox.new(Game, Strings("You can't carry\nany more items!")))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2414,14 +2414,15 @@ local function sellItem(id)
|
|||||||
return sold
|
return sold
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Free up bag slots so `needed` NEW item kinds fit (Bag.CAPACITY is 20
|
-- Free up bag slots so `needed` NEW item kinds fit (20 slots without a
|
||||||
-- slots; a stack of an item already held costs nothing). This is why
|
-- capacity mod; a stack of an item already held costs nothing). This is why
|
||||||
-- every restock had been reporting "HYPER_POTION x0": the buy list
|
-- every restock had been reporting "HYPER_POTION x0": the buy list
|
||||||
-- opened, the quantity was set, the engine said "no room" -- and the run
|
-- opened, the quantity was set, the engine said "no room" -- and the run
|
||||||
-- walked into the Mansion with FULL_HEALs but not one HP restore.
|
-- walked into the Mansion with FULL_HEALs but not one HP restore.
|
||||||
local function freeBagSlots(needed, where)
|
local function freeBagSlots(needed, where)
|
||||||
local used = #(G.save.bagOrder or {})
|
local used = #(G.save.bagOrder or {})
|
||||||
local free = 20 - used
|
local capacity = require("src.inventory.Bag").capacity(G.data)
|
||||||
|
local free = capacity - used
|
||||||
for _, id in ipairs(SELLABLE_JUNK) do
|
for _, id in ipairs(SELLABLE_JUNK) do
|
||||||
if free >= needed then break end
|
if free >= needed then break end
|
||||||
if ((G.save.inventory or {})[id] or 0) > 0 then
|
if ((G.save.inventory or {})[id] or 0) > 0 then
|
||||||
@@ -2632,7 +2633,8 @@ function ops.shop(s, where)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local used = #(G.save.bagOrder or {})
|
local used = #(G.save.bagOrder or {})
|
||||||
if newKinds > 0 and 20 - used < newKinds then
|
local capacity = require("src.inventory.Bag").capacity(G.data)
|
||||||
|
if newKinds > 0 and capacity - used < newKinds then
|
||||||
freeBagSlots(newKinds, where)
|
freeBagSlots(newKinds, where)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
-- T4: constants.bagSize controls the bag through the public mod API while
|
||||||
|
-- vanilla and existing-save behavior remain unchanged.
|
||||||
|
|
||||||
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||||
|
|
||||||
|
local T = require("tests.modkit")
|
||||||
|
local Bag = require("src.inventory.Bag")
|
||||||
|
|
||||||
|
local CAPACITY_MOD = {
|
||||||
|
["mods/fix_small_bag/manifest.json"] = [[{
|
||||||
|
"id": "fix_small_bag",
|
||||||
|
"name": "Fixture Small Bag",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"entry": "main.lua",
|
||||||
|
"api": 2
|
||||||
|
}]],
|
||||||
|
["mods/fix_small_bag/main.lua"] = [[
|
||||||
|
local mod = ...
|
||||||
|
mod.content.constants:patch("bagSize", 2)
|
||||||
|
]],
|
||||||
|
}
|
||||||
|
|
||||||
|
-- No-mod parity: the new lookup keeps the cartridge's 20-slot limit.
|
||||||
|
do
|
||||||
|
local data = T.fixtures.fresh()
|
||||||
|
local run = T.sdk.loadNone({ data = data })
|
||||||
|
T.eq(#run.errors, 0, "the no-mod baseline loads cleanly")
|
||||||
|
T.eq(Bag.capacity(data), 20, "the vanilla bag still has 20 slots")
|
||||||
|
T.eq(Bag.capacity({}), 20, "a stale dataset without bagSize falls back to 20")
|
||||||
|
run.release()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The public constants registry changes both the reported and enforced cap.
|
||||||
|
do
|
||||||
|
local data = T.fixtures.fresh()
|
||||||
|
local run = T.sdk.loadMods({ "mods/fix_small_bag" },
|
||||||
|
{ data = data, fs = T.sdk.memfs(CAPACITY_MOD) })
|
||||||
|
T.eq(#run.errors, 0, "the capacity mod loads cleanly")
|
||||||
|
T.eq(Bag.capacity(data), 2, "Bag.capacity reads merged constants.bagSize")
|
||||||
|
|
||||||
|
local save = { inventory = {} }
|
||||||
|
T.check(Bag.add(save, "FIX_POTION", 1, data), "the first item fits")
|
||||||
|
T.check(Bag.add(save, "FIX_BALL", 1, data), "the second item fits")
|
||||||
|
T.check(not Bag.add(save, "FIX_TM", 1, data),
|
||||||
|
"a new item is refused at the modded limit")
|
||||||
|
T.eq(Bag.slots(save), 2, "a refused add does not change the bag")
|
||||||
|
run.release()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Saves are dictionaries, not fixed arrays: lowering the active cap never
|
||||||
|
-- truncates an older or modded save. Existing stacks remain usable while a
|
||||||
|
-- new item waits until the player makes enough room.
|
||||||
|
do
|
||||||
|
local data = T.fixtures.fresh()
|
||||||
|
data.constants.bagSize = 1
|
||||||
|
local save = {
|
||||||
|
inventory = { FIX_POTION = 1, FIX_BALL = 1 },
|
||||||
|
bagOrder = { "FIX_POTION", "FIX_BALL" },
|
||||||
|
}
|
||||||
|
T.eq(Bag.slots(save), 2, "an over-cap save keeps all existing slots")
|
||||||
|
T.check(Bag.add(save, "FIX_POTION", 1, data),
|
||||||
|
"an over-cap save can still add to an existing stack")
|
||||||
|
T.eq(save.inventory.FIX_POTION, 2, "the existing stack is updated")
|
||||||
|
T.check(not Bag.add(save, "FIX_TM", 1, data),
|
||||||
|
"an over-cap save cannot add another item kind")
|
||||||
|
T.eq(Bag.slots(save), 2, "the compatibility path never drops items")
|
||||||
|
end
|
||||||
|
|
||||||
|
T.finish("bag_capacity")
|
||||||
@@ -181,12 +181,13 @@ end
|
|||||||
do
|
do
|
||||||
-- the bag has a hard slot cap; the picker must refuse past it
|
-- the bag has a hard slot cap; the picker must refuse past it
|
||||||
local S = newState()
|
local S = newState()
|
||||||
|
local capacity = Bag.capacity(S.data)
|
||||||
local added = 0
|
local added = 0
|
||||||
for _, id in ipairs(S.cat.items) do
|
for _, id in ipairs(S.cat.items) do
|
||||||
if not Ops.isBadgeId(id) and Ops.addToBag(S, id) then added = added + 1 end
|
if not Ops.isBadgeId(id) and Ops.addToBag(S, id) then added = added + 1 end
|
||||||
if added >= Bag.CAPACITY then break end
|
if added >= capacity then break end
|
||||||
end
|
end
|
||||||
eq(Bag.slots(S.save), Bag.CAPACITY, "the bag filled to its cap")
|
eq(Bag.slots(S.save), capacity, "the bag filled to its cap")
|
||||||
S.dirty = false
|
S.dirty = false
|
||||||
local spare
|
local spare
|
||||||
for _, id in ipairs(S.cat.items) do
|
for _, id in ipairs(S.cat.items) do
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ local function tabCount(id)
|
|||||||
return tostring(n)
|
return tostring(n)
|
||||||
elseif id == "items" then
|
elseif id == "items" then
|
||||||
local Bag = require("src.inventory.Bag")
|
local Bag = require("src.inventory.Bag")
|
||||||
return ("%d/%d"):format(Bag.slots(S.save), Bag.CAPACITY)
|
return ("%d/%d"):format(Bag.slots(S.save), Bag.capacity(S.data))
|
||||||
elseif id == "events" then
|
elseif id == "events" then
|
||||||
local n = 0
|
local n = 0
|
||||||
for _ in pairs(S.save.flags or {}) do n = n + 1 end
|
for _ in pairs(S.save.flags or {}) do n = n + 1 end
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
--
|
--
|
||||||
-- Clamps mirror the running game, not the UI: level 1-100, DV 0-15, party 6
|
-- Clamps mirror the running game, not the UI: level 1-100, DV 0-15, party 6
|
||||||
-- (src/pokemon/Party), box 20 x 12 (src/pokemon/Boxes), money 0-999999,
|
-- (src/pokemon/Party), box 20 x 12 (src/pokemon/Boxes), money 0-999999,
|
||||||
-- item stack 99 and 20 bag slots (src/inventory/Bag).
|
-- item stack 99 and the configured bag capacity (20 by default;
|
||||||
|
-- src/inventory/Bag).
|
||||||
|
|
||||||
local Pokemon = require("src.pokemon.Pokemon")
|
local Pokemon = require("src.pokemon.Pokemon")
|
||||||
local PartyMod = require("src.pokemon.Party")
|
local PartyMod = require("src.pokemon.Party")
|
||||||
@@ -338,11 +339,13 @@ end
|
|||||||
|
|
||||||
function Ops.addToBag(S, id)
|
function Ops.addToBag(S, id)
|
||||||
if not id then return Ops.say(S, "Pick an item first") end
|
if not id then return Ops.say(S, "Pick an item first") end
|
||||||
if Bag.add(S.save, id, 1) then
|
local capacity = Bag.capacity(S.data)
|
||||||
|
if Bag.add(S.save, id, 1, S.data) then
|
||||||
return Ops.mark(S, ("Added %s to the bag (%d/%d slots)")
|
return Ops.mark(S, ("Added %s to the bag (%d/%d slots)")
|
||||||
:format(id, Bag.slots(S.save), Bag.CAPACITY))
|
:format(id, Bag.slots(S.save), capacity))
|
||||||
end
|
end
|
||||||
return Ops.say(S, ("Bag is full (%d/%d slots)"):format(Bag.slots(S.save), Bag.CAPACITY))
|
return Ops.say(S, ("Bag is full (%d/%d slots)")
|
||||||
|
:format(Bag.slots(S.save), capacity))
|
||||||
end
|
end
|
||||||
|
|
||||||
function Ops.bagAdjust(S, id, delta)
|
function Ops.bagAdjust(S, id, delta)
|
||||||
@@ -352,7 +355,7 @@ function Ops.bagAdjust(S, id, delta)
|
|||||||
if have >= Ops.STACK_MAX then
|
if have >= Ops.STACK_MAX then
|
||||||
return Ops.say(S, ("%s is already at x%d"):format(id, Ops.STACK_MAX))
|
return Ops.say(S, ("%s is already at x%d"):format(id, Ops.STACK_MAX))
|
||||||
end
|
end
|
||||||
Bag.add(S.save, id, delta)
|
Bag.add(S.save, id, delta, S.data)
|
||||||
else
|
else
|
||||||
Bag.remove(S.save, id, -delta)
|
Bag.remove(S.save, id, -delta)
|
||||||
if not S.save.inventory[id] then
|
if not S.save.inventory[id] then
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
-- Items panel: money, the shared item picker, badges, the 20-slot bag
|
-- Items panel: money, the shared item picker, badges, the configurable bag
|
||||||
-- (Bag.add/remove, ordered by Bag.order) and PC item storage (a plain
|
-- (Bag.add/remove, ordered by Bag.order) and PC item storage (a plain
|
||||||
-- S.save.pcItems dict with no slot cap).
|
-- S.save.pcItems dict with no slot cap).
|
||||||
--
|
--
|
||||||
@@ -178,12 +178,13 @@ function M.draw(S, Kit, x, y, w, h)
|
|||||||
|
|
||||||
-- --------------------------------------------------------------- bag
|
-- --------------------------------------------------------------- bag
|
||||||
local order = Bag.order(S.save)
|
local order = Bag.order(S.save)
|
||||||
|
local capacity = Bag.capacity(S.data)
|
||||||
Kit.card(bagX, y, listW, h)
|
Kit.card(bagX, y, listW, h)
|
||||||
Kit.caption(bagX + pad, y + pad, "BAG")
|
Kit.caption(bagX + pad, y + pad, "BAG")
|
||||||
Kit.textRight("mono", ("%d/%d slots"):format(Bag.slots(S.save), Bag.CAPACITY),
|
Kit.textRight("mono", ("%d/%d slots"):format(Bag.slots(S.save), capacity),
|
||||||
bagX + listW - pad, y + pad, PAL.caption)
|
bagX + listW - pad, y + pad, PAL.caption)
|
||||||
local barY = y + pad + Kit.textHeight("caption") + 8 * s
|
local barY = y + pad + Kit.textHeight("caption") + 8 * s
|
||||||
local slotFrac = Bag.slots(S.save) / Bag.CAPACITY
|
local slotFrac = Bag.slots(S.save) / capacity
|
||||||
Kit.meter(bagX + pad, barY, listW - 2 * pad, 5 * s, slotFrac * 100,
|
Kit.meter(bagX + pad, barY, listW - 2 * pad, 5 * s, slotFrac * 100,
|
||||||
slotFrac >= 1 and PAL.yellow or PAL.blue)
|
slotFrac >= 1 and PAL.yellow or PAL.blue)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user