🔥 FAZE SPRINT 1-3 COMPLETION: DayNight, Inventory, Core Farming System, Mrtvi Zombiji (ShamblerAI & Alfa Moć Taming), Sredili assets & daily UI

This commit is contained in:
2026-03-03 17:46:41 +01:00
parent 35153eeacf
commit 188bd769cf
49 changed files with 5054 additions and 286 deletions

View File

@@ -0,0 +1,326 @@
/**
* ============================================================
* 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
this.hotbar = [
'hoe',
'watering_can',
'wheat_seed',
'carrot_seed',
null,
null,
null,
];
this.activeSlot = 0; // Slot 1 = Motika
// 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',
},
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: '7 dni • 200g/harvest',
color: '#88cc44',
},
// 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,
},
};
// 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 + seme/resource
const def = this.ITEM_DEFS[key];
if (def && def.stackable && !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)`);
}
// ─────────────────────────────────────────────────────────────────────────
// 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,
};
}
}