🔥 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:
326
nova farma TRAE/src/systems/InventorySystem.js
Normal file
326
nova farma TRAE/src/systems/InventorySystem.js
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user