622a9fd170
Inverted tower-defense browser game — deploy enemies yourself, tower auto-kills them, pocket credits, upgrade weapons. HTML + Canvas + vanilla JS, no build step. Co-Authored-By: claude-flow <ruv@ruv.net>
114 lines
3.7 KiB
JavaScript
114 lines
3.7 KiB
JavaScript
// ═══ 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();
|
|
}
|