// ═══ inventory.js ═══ // ============================================================ // INVENTORY — weapon picker state and equip helpers // ============================================================ const MAX_WEAPON_SLOTS = 8; let _pickerSlot = -1; let _pickerScrollY = 0; let _pickerScrollMax = 0; function weaponUpgradeCount(w) { return (G.weaponUpgradesBought[w.instanceId] || []).length; } function weaponElementLabel(w) { return getWeaponElements(w) .map(el => ELEMENTS[el]?.icon || '') .join(''); } function weaponStatRows(w) { return [ ['DMG', w.damage], ['RATE', w.fireRate + 'f'], w.aoeRadius ? ['AOE', w.aoeRadius] : null, w.targets && w.targets > 1 ? ['TARGETS', w.targets] : null, w.pierce ? ['PIERCE', w.pierce] : null, w.chains ? ['CHAINS', w.chains] : null, ['TARGET', (w.targeting || 'nearest').toUpperCase()], ].filter(Boolean); } function weaponUpgradeLabels(w) { const bought = G.weaponUpgradesBought[w.instanceId] || []; const tree = WEAPON_UPGRADE_TREES[w.defId] || []; return bought.map(id => tree.find(u => u.id === id)?.label || id); } function openWeaponPicker(slotIndex) { if (slotIndex >= G.tower.weaponSlots) return; _pickerSlot = slotIndex; _pickerScrollY = 0; setPaused(true, false); document.body.classList.add('inventory-open'); G.weaponInventory = G.weaponInventory || []; } function closeWeaponPicker() { document.body.classList.remove('inventory-open'); _pickerSlot = -1; _pickerScrollY = 0; if (!G.shopOpen) setPaused(false); } function equipWeaponInstanceToSlot(slotIndex, instanceId) { if (slotIndex >= G.tower.weaponSlots) return; G.weaponInventory = G.weaponInventory || []; const sourceSlot = G.weapons.slice(0, G.tower.weaponSlots).findIndex(w => w && w.instanceId === instanceId); if (sourceSlot === slotIndex) return; const displaced = G.weapons[slotIndex]; if (sourceSlot >= 0) { G.weapons[slotIndex] = G.weapons[sourceSlot]; G.weapons[sourceSlot] = displaced || null; } else { const invIdx = G.weaponInventory.findIndex(w => w.instanceId === instanceId); if (invIdx === -1) return; const invWeapon = G.weaponInventory.splice(invIdx, 1)[0]; G.weapons[slotIndex] = invWeapon; if (displaced) G.weaponInventory.push(displaced); } addLog(getWeaponDef(G.weapons[slotIndex]).name + ' equipped.', 'info'); updateHUD(); } function removeWeaponFromSlot(slotIndex) { if (slotIndex >= G.tower.weaponSlots) return; const activeCount = G.weapons.slice(0, G.tower.weaponSlots).filter(w => w != null).length; if (activeCount <= 1) { addLog('Cannot remove last weapon!', 'lose'); return; } const w = G.weapons[slotIndex]; if (!w) return; G.weaponInventory = G.weaponInventory || []; G.weaponInventory.push(w); G.weapons[slotIndex] = null; addLog(getWeaponDef(w).name + ' moved to inventory.', 'info'); updateHUD(); } function buyAndEquipWeapon(slotIndex, defId) { const def = WEAPON_DEFS.find(w => w.id === defId); if (!def || slotIndex >= G.tower.weaponSlots || spendableCredits() < def.cost) return; if (!canBuyWeaponType(defId)) { addLog(`${def.name} limit reached (${MAX_WEAPONS_PER_TYPE}/${MAX_WEAPONS_PER_TYPE}).`, 'lose'); return; } G.credits -= def.cost; const instance = makeWeaponInstance(defId); G.weaponUpgradesBought[instance.instanceId] = []; const displaced = G.weapons[slotIndex]; G.weapons[slotIndex] = instance; if (displaced) { G.weaponInventory = G.weaponInventory || []; G.weaponInventory.push(displaced); addLog(`Purchased ${def.name}! Swapped previous weapon to inventory.`, 'win'); } else { addLog(`Purchased ${def.name}!`, 'win'); } updateHUD(); }