- 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
362 lines
12 KiB
JavaScript
362 lines
12 KiB
JavaScript
/**
|
||
* ============================================================
|
||
* 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,
|
||
};
|
||
}
|
||
}
|