step 10.15: done
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
// src/game/inventory.js — Shared inventory helpers.
|
||||
// Pure data operations; no DB, no Express.
|
||||
|
||||
/**
|
||||
* Grant an item to a character's inventory.
|
||||
* Stackable items merge into one row (increment quantity).
|
||||
* Non-stackable items get one row per unit (quantity 1 each).
|
||||
*
|
||||
* @param {object} s — prepared statements cache (from service's getStmts)
|
||||
* @param {number} characterId
|
||||
* @param {object} item — item row with `stackable` and `id`
|
||||
* @param {number} quantity
|
||||
* @param {number} now — timestamp in ms
|
||||
*/
|
||||
function grantItem(s, characterId, item, quantity, now) {
|
||||
if (item.stackable) {
|
||||
const row = s.stackRow.get(characterId, item.id);
|
||||
if (row) s.addToStack.run(quantity, row.id);
|
||||
else s.insertInv.run(characterId, item.id, quantity, now);
|
||||
} else {
|
||||
for (let i = 0; i < quantity; i++) s.insertInv.run(characterId, item.id, 1, now);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { grantItem };
|
||||
@@ -12,6 +12,7 @@ const { calculateRewards, rollLoot } = require('../game/rewards');
|
||||
const { checkLevelUp, applyXpGain } = require('../game/leveling');
|
||||
const { computeHp } = require('../game/hp');
|
||||
const { getEquipmentBonuses } = require('../game/equipment');
|
||||
const { grantItem } = require('../game/inventory');
|
||||
|
||||
const MIN_HP_PCT_TO_HUNT = 0.2;
|
||||
const DEFEAT_GOLD_LOSS_PCT = 0.10;
|
||||
@@ -59,17 +60,6 @@ function pickWeightedMonster(monsters, rng) {
|
||||
return monsters[monsters.length - 1];
|
||||
}
|
||||
|
||||
// Stackable items merge into one row per (character, item); others get one row per unit.
|
||||
function grantItem(s, characterId, item, quantity, now) {
|
||||
if (item.stackable) {
|
||||
const row = s.stackRow.get(characterId, item.id);
|
||||
if (row) s.addToStack.run(quantity, row.id);
|
||||
else s.insertInv.run(characterId, item.id, quantity, now);
|
||||
} else {
|
||||
for (let i = 0; i < quantity; i++) s.insertInv.run(characterId, item.id, 1, now);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} characterId
|
||||
* @param {number} zoneId
|
||||
|
||||
+20
-10
@@ -5,6 +5,7 @@ const { AppError } = require('../utils/errors');
|
||||
const { getEquipmentBonuses } = require('../game/equipment');
|
||||
const { calcDerived } = require('../game/stats');
|
||||
const { materialSellPrice } = require('../game/rewards');
|
||||
const { grantItem } = require('../game/inventory');
|
||||
|
||||
// Prepared statements cached per DB handle (WeakMap).
|
||||
const stmtCache = new WeakMap();
|
||||
@@ -41,6 +42,21 @@ function getStmts(db) {
|
||||
'SELECT * FROM characters WHERE id = ?'
|
||||
),
|
||||
|
||||
// Get inventory row for stack check (used by shared grantItem).
|
||||
stackRow: db.prepare(
|
||||
'SELECT id FROM inventory WHERE character_id = ? AND item_id = ? AND equipped_slot IS NULL'
|
||||
),
|
||||
|
||||
// Add to existing stack (used by shared grantItem).
|
||||
addToStack: db.prepare(
|
||||
'UPDATE inventory SET quantity = quantity + ? WHERE id = ?'
|
||||
),
|
||||
|
||||
// Insert new inventory row (used by shared grantItem).
|
||||
insertInv: db.prepare(
|
||||
'INSERT INTO inventory (character_id, item_id, quantity, acquired_at) VALUES (?, ?, ?, ?)'
|
||||
),
|
||||
|
||||
// Get inventory rows for a character + item (for selling).
|
||||
inventoryRows: db.prepare(
|
||||
'SELECT * FROM inventory WHERE character_id = ? AND item_id = ? AND quantity >= ?'
|
||||
@@ -253,21 +269,15 @@ function buyItem(characterId, itemId, quantity) {
|
||||
const now = require('../utils/time').now();
|
||||
|
||||
// Execute the purchase inside a transaction.
|
||||
const doBuy = db.transaction((cost, ng, cid, iid, qty, acquiredAt) => {
|
||||
const doBuy = db.transaction((ng, cid, itemObj, qty, acquiredAt) => {
|
||||
// Deduct gold.
|
||||
s.updateGold.run(ng, cid);
|
||||
|
||||
// If stackable and already owned, increment quantity.
|
||||
const existing = s.inventoryRows.get(cid, iid, 1);
|
||||
if (existing && item.stackable) {
|
||||
s.incrementQty.run(qty, cid, iid);
|
||||
} else {
|
||||
// New inventory entry.
|
||||
s.addToInventory.run(cid, iid, qty, acquiredAt);
|
||||
}
|
||||
// Grant item (stackable merges, non-stackable gets one row per unit).
|
||||
grantItem(s, cid, itemObj, qty, acquiredAt);
|
||||
});
|
||||
|
||||
doBuy(totalCost, newGold, characterId, itemId, quantity, now);
|
||||
doBuy(newGold, characterId, item, quantity, now);
|
||||
|
||||
// Return updated inventory listing.
|
||||
return listInventory(characterId);
|
||||
|
||||
Reference in New Issue
Block a user