Files
novafarma/nova farma TRAE/src/systems/InventorySystem.js
David Kotnik b660429e3c feat: Faza 1 Gameplay Loop - Kista, Sekanje, Gradnja, Kmetovanje, Dnevnik, Zombiji
- Starter Chest (Kista): Nov sprite asset (chest_closed.png), zamenjal rectangles z dejansko sliko, dodal axe reward ob odprtju
- Sekanje dreves: Zahteva Sekiro v rokah, padec drevesa odvrze 3 kose lesa (pickup sistem), unlock dnevniska vnosa
- Gradnja Barikad [B]: Nov wooden_fence.png asset, BuildingSystem posodobljen z leseno barikado (cena: 2 les), ghost preview z grid snappingom, deductItem() API
- Farming zanka: Popravljen seed property v InventorySystem, unlock ob prvem sajenju in zetvi
- Kaijev Dnevnik [J]: Novi JournalSystem.js s 6 vnosi, gotski UI z zlatimi okviri, animirano odpiranje, odklepanje ob napredku
- Zombie nochni napadi: Stopnjevano po nochih (max 8, hitrost do 65px/s, krajsi spawn delay), unlock dnevnika ob prvi nochi
- InventorySystem: Popravljen bug kjer tools niso bili dodani v hotbar, dodan axe in wood v ITEM_DEFS, nova deductItem() funkcija
- Pomoznna remove_bg.py skripta za odstranjevanje belega ozadja assetov
2026-03-13 20:11:46 +01:00

362 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* ============================================================
* InventorySystem.js — Nova Farma
* ============================================================
* Hotbar (7 slotov) + Items logika
*
* DEMO starter items:
* Slot 1: 🪓 Motika (Hoe) → ore tla
* Slot 2: 💧 Zalivalka → zalij crop
* Slot 3: 🌾 Pšenica semena ×5
* Slot 4: 🥕 Korenje semena ×5
* Slot 5: — prazen —
* Slot 6: — prazen —
* Slot 7: — prazen —
*
* Keys: [1]-[7] za slot, scroll za rotate
* Emit 'hotbarChanged' { slot, item } → GrassScene → FarmingSystem
* ============================================================
*/
export default class InventorySystem {
/**
* @param {Phaser.Scene} scene — GrassSceneClean
*/
constructor(scene) {
this.scene = scene;
// Vsi predmeti (full inventory)
this.items = {};
// Format: { 'wheat_seed': { name, icon, count, type, tool/seed } }
// Hotbar = 7 slotov, vsak kaže na item key ali null (začenjamo prazni!)
this.hotbar = [
null,
null,
null,
null,
null,
null,
null,
];
this.activeSlot = 0; // Slot 1
// Item definicije
this.ITEM_DEFS = {
hoe: {
name: 'Motika',
icon: '🪓',
type: 'tool',
tool: 'hoe',
stackable: false,
count: 1,
desc: '[E] Oraj tla',
},
watering_can: {
name: 'Zalivalka',
icon: '💧',
type: 'tool',
tool: 'watering_can',
stackable: false,
count: 1,
desc: '[E] Zalij rastlino',
},
axe: {
name: 'Sekira',
icon: '🪓',
type: 'tool',
tool: 'axe',
stackable: false,
count: 1,
desc: '[M1] Podri drevo',
},
wheat_seed: {
name: 'Pšenica',
icon: '🌾',
type: 'seed',
seed: 'wheat',
stackable: true,
count: 5,
desc: '3 dni • 30g/harvest',
color: '#ffdd88',
},
carrot_seed: {
name: 'Korenje',
icon: '🥕',
type: 'seed',
seed: 'carrot',
stackable: true,
count: 5,
desc: '4 dni • 40g/harvest',
color: '#ff8844',
},
cannabis_seed: {
name: 'Konoplja',
icon: '🌿',
type: 'seed',
seed: 'cannabis',
stackable: true,
count: 0,
desc: '[E] Posadi na preorano',
color: '#88cc44',
value: 50,
},
// Harvested items
wheat: {
name: 'Pšenica',
icon: '🌾',
type: 'resource',
stackable: true,
count: 0,
value: 30,
},
carrot: {
name: 'Korenje',
icon: '🥕',
type: 'resource',
stackable: true,
count: 0,
value: 40,
},
cannabis_bud: {
name: 'Konoplja',
icon: '🌿',
type: 'resource',
stackable: true,
count: 0,
value: 200,
},
wood: {
name: 'Les',
icon: '🪵',
type: 'resource',
stackable: true,
count: 0,
value: 10,
},
};
// Inicializiraj items iz ITEM_DEFS (samo tiste s count > 0)
for (const [key, def] of Object.entries(this.ITEM_DEFS)) {
this.items[key] = { ...def };
}
// Denar (Gold)
this.gold = 0;
// Number keys [1]-[7]
for (let i = 1; i <= 7; i++) {
scene.input.keyboard.on(`keydown-${i}`, () => this.selectSlot(i - 1));
}
// Scroll wheel za rotation
scene.input.on('wheel', (pointer, gObj, dx, dy) => {
if (dy > 0) this.selectSlot((this.activeSlot + 1) % 7);
else if (dy < 0) this.selectSlot((this.activeSlot + 6) % 7);
});
// Poslušaj harvest evente → dodaj v inventar
scene.events.on('harvest', (data) => {
this.addItem(data.item, data.count);
this.addGold(data.value);
});
// Prvič sinhronizira z FarmingSystem
this._syncWithFarming();
console.log('🎒 InventorySystem initialized');
}
// ─────────────────────────────────────────────────────────────────────────
// IZBERI SLOT
// ─────────────────────────────────────────────────────────────────────────
selectSlot(index) {
if (index < 0 || index >= 7) return;
this.activeSlot = index;
this._syncWithFarming();
this._notifyUI();
console.log(`🎒 Slot ${index + 1}: ${this.hotbar[index] || 'prazen'}`);
}
// ─────────────────────────────────────────────────────────────────────────
// DODAJ ITEM
// ─────────────────────────────────────────────────────────────────────────
addItem(key, count = 1) {
if (!this.items[key]) {
this.items[key] = { ...(this.ITEM_DEFS[key] || { name: key, icon: '📦', count: 0 }) };
}
this.items[key].count += count;
// Dodaj v hotbar če je prazen slot in item še ni v hotbaru
const def = this.ITEM_DEFS[key];
if (def && !this.hotbar.includes(key)) {
const emptySlot = this.hotbar.findIndex(s => s === null);
if (emptySlot !== -1) this.hotbar[emptySlot] = key;
}
this._notifyUI();
console.log(`🎒 +${count}× ${key} (skupaj: ${this.items[key].count})`);
}
addGold(amount) {
this.gold += amount;
this._notifyUI();
console.log(`💰 +${amount}g (skupaj: ${this.gold}g)`);
}
deductItem(key, amount) {
if (!this.items[key] || this.items[key].count < amount) return false;
this.items[key].count -= amount;
// Če je stackable in gre na 0, odstrani tudi iz hotbara
if (this.items[key].count <= 0 && this.items[key].stackable) {
const index = this.hotbar.indexOf(key);
if (index !== -1) {
this.hotbar[index] = null;
}
}
this._notifyUI();
return true;
}
// ─────────────────────────────────────────────────────────────────────────
// PORABI ITEM (semena pri sajenju)
// ─────────────────────────────────────────────────────────────────────────
useActiveItem() {
const key = this.hotbar[this.activeSlot];
if (!key) return false;
const item = this.items[key];
if (!item) return false;
if (item.type === 'seed') {
if (item.count <= 0) {
this._showMsg(`❌ Ni ${item.name} semen!`, '#ff6666');
return false;
}
item.count--;
if (item.count <= 0 && item.stackable) {
// Odstrani iz hotbara
this.hotbar[this.activeSlot] = null;
}
this._notifyUI();
return true;
}
if (item.type === 'tool') return true; // Orodja se ne porabijo
return false;
}
// ─────────────────────────────────────────────────────────────────────────
// SYNC z FarmingSystem
// ─────────────────────────────────────────────────────────────────────────
_syncWithFarming() {
const farming = this.scene.farmingSystem;
if (!farming) return;
const key = this.hotbar[this.activeSlot];
if (!key) {
farming.setTool(null);
return;
}
const item = this.items[key];
if (!item) return;
if (item.type === 'tool') {
farming.setTool(item.tool);
farming.setSeed(null);
} else if (item.type === 'seed') {
farming.setTool('hoe'); // Semena → avtomatsko orodje = motika za saditev
farming.setSeed(item.seed);
} else {
farming.setTool(null);
farming.setSeed(null);
}
}
// ─────────────────────────────────────────────────────────────────────────
// NOTIFY UIScene
// ─────────────────────────────────────────────────────────────────────────
_notifyUI() {
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
// Pošlji hotbar stanje
const hotbarData = this.hotbar.map((key, i) => {
if (!key) return null;
const item = this.items[key];
const def = this.ITEM_DEFS[key];
return {
key,
icon: def?.icon || '📦',
name: def?.name || key,
count: item?.count ?? 1,
active: i === this.activeSlot,
type: def?.type || 'unknown',
stackable: def?.stackable || false,
};
});
uiScene.events.emit('hotbarUpdate', {
slots: hotbarData,
activeSlot: this.activeSlot,
gold: this.gold,
});
}
_showMsg(msg, color = '#ffffff') {
const cam = this.scene.cameras.main;
const txt = this.scene.add.text(
cam.worldView.centerX,
cam.worldView.top + 80,
msg, {
fontFamily: 'Arial Black',
fontSize: '20px',
color,
stroke: '#000000',
strokeThickness: 4,
}
).setOrigin(0.5).setDepth(9999);
this.scene.tweens.add({
targets: txt,
y: txt.y - 40,
alpha: { from: 1, to: 0 },
duration: 1500,
onComplete: () => txt.destroy(),
});
}
// ─────────────────────────────────────────────────────────────────────────
// PUBLIC API
// ─────────────────────────────────────────────────────────────────────────
getActiveItem() {
const key = this.hotbar[this.activeSlot];
return key ? this.items[key] : null;
}
getActiveItemKey() {
return this.hotbar[this.activeSlot];
}
getCount(key) {
return this.items[key]?.count || 0;
}
getGold() {
return this.gold;
}
getState() {
return {
items: this.items,
hotbar: this.hotbar,
activeSlot: this.activeSlot,
gold: this.gold,
};
}
}