Files
novafarma/EMERGENCY_SYSTEMS_RECOVERY/CraftingSystem.js
2026-01-16 02:43:46 +01:00

353 lines
10 KiB
JavaScript

// Crafting System - Handles recipe management and item crafting
class CraftingSystem {
constructor(scene) {
this.scene = scene;
this.recipes = {};
this.categories = [];
this.unlockedRecipes = new Set();
// Crafting queue
this.craftingQueue = [];
this.isCrafting = false;
this.currentCraft = null;
this.craftProgress = 0;
console.log('🛠️ CraftingSystem initialized');
}
async loadRecipes() {
try {
// Load recipes from JSON file
const response = await fetch('data/recipes.json');
const data = await response.json();
this.recipes = data.recipes;
this.categories = data.categories;
// Initialize unlocked recipes
Object.keys(this.recipes).forEach(recipeId => {
const recipe = this.recipes[recipeId];
if (recipe.unlocked) {
this.unlockedRecipes.add(recipeId);
}
});
console.log(`✅ Loaded ${Object.keys(this.recipes).length} recipes`);
console.log(`🔓 ${this.unlockedRecipes.size} unlocked recipes`);
return true;
} catch (error) {
console.error('❌ Failed to load recipes:', error);
return false;
}
}
// Get all recipes (optionally filtered by category)
getRecipes(category = 'all') {
const recipeList = Object.values(this.recipes);
if (category === 'all') {
return recipeList;
}
return recipeList.filter(recipe => recipe.category === category);
}
// Get only unlocked recipes
getUnlockedRecipes(category = 'all') {
return this.getRecipes(category).filter(recipe =>
this.unlockedRecipes.has(recipe.id)
);
}
// Check if recipe is unlocked
isUnlocked(recipeId) {
return this.unlockedRecipes.has(recipeId);
}
// Unlock a recipe
unlockRecipe(recipeId) {
if (this.recipes[recipeId]) {
this.unlockedRecipes.add(recipeId);
console.log(`🔓 Unlocked recipe: ${this.recipes[recipeId].name}`);
// Notify UI
this.scene.events.emit('recipe-unlocked', recipeId);
return true;
}
return false;
}
// Check if player has required ingredients
canCraft(recipeId) {
const recipe = this.recipes[recipeId];
if (!recipe) return false;
// Check if unlocked
if (!this.isUnlocked(recipeId)) {
return { canCraft: false, reason: 'locked' };
}
// Check ingredients
const inventory = this.scene.inventorySystem;
if (!inventory) {
return { canCraft: false, reason: 'no_inventory' };
}
const missing = [];
for (const [itemId, requiredAmount] of Object.entries(recipe.ingredients)) {
const hasAmount = inventory.getItemCount(itemId);
if (hasAmount < requiredAmount) {
missing.push({
item: itemId,
required: requiredAmount,
has: hasAmount,
need: requiredAmount - hasAmount
});
}
}
if (missing.length > 0) {
return { canCraft: false, reason: 'missing_ingredients', missing };
}
return { canCraft: true };
}
// Start crafting an item
craftItem(recipeId) {
const recipe = this.recipes[recipeId];
if (!recipe) {
console.warn(`⚠️ Recipe not found: ${recipeId}`);
return false;
}
// Check if can craft
const check = this.canCraft(recipeId);
if (!check.canCraft) {
console.warn(`⚠️ Cannot craft ${recipe.name}: ${check.reason}`);
return false;
}
// Consume ingredients
const inventory = this.scene.inventorySystem;
for (const [itemId, amount] of Object.entries(recipe.ingredients)) {
inventory.removeItem(itemId, amount);
}
// Add to crafting queue
this.craftingQueue.push({
recipeId: recipeId,
recipe: recipe,
startTime: Date.now(),
duration: recipe.craftTime || 1000
});
console.log(`🔨 Started crafting: ${recipe.name}`);
// Start crafting if not already crafting
if (!this.isCrafting) {
this.startNextCraft();
}
// Emit event
this.scene.events.emit('craft-started', recipeId);
// Play sound
if (this.scene.soundManager && this.scene.soundManager.playCraftSound) {
this.scene.soundManager.playCraftSound();
}
return true;
}
// Start next item in queue
startNextCraft() {
if (this.craftingQueue.length === 0) {
this.isCrafting = false;
this.currentCraft = null;
this.craftProgress = 0;
return;
}
this.isCrafting = true;
this.currentCraft = this.craftingQueue[0];
this.craftProgress = 0;
console.log(`⏳ Processing: ${this.currentCraft.recipe.name}`);
}
// Update crafting progress
update(delta) {
if (!this.isCrafting || !this.currentCraft) return;
const elapsed = Date.now() - this.currentCraft.startTime;
this.craftProgress = Math.min(1.0, elapsed / this.currentCraft.duration);
// Check if finished
if (this.craftProgress >= 1.0) {
this.completeCraft();
}
// Emit progress event for UI
this.scene.events.emit('craft-progress', {
recipe: this.currentCraft.recipe,
progress: this.craftProgress
});
}
// Complete current craft
completeCraft() {
if (!this.currentCraft) return;
const recipe = this.currentCraft.recipe;
// Add result to inventory
const inventory = this.scene.inventorySystem;
inventory.addItem(recipe.result.item, recipe.result.quantity);
console.log(`✅ Crafted: ${recipe.result.quantity}x ${recipe.name}`);
// Emit event
this.scene.events.emit('craft-complete', {
recipeId: recipe.id,
item: recipe.result.item,
quantity: recipe.result.quantity
});
// Play sound
if (this.scene.soundManager && this.scene.soundManager.playSuccessSound) {
this.scene.soundManager.playSuccessSound();
}
// Show floating text
if (this.scene.player && this.scene.player.sprite) {
const text = `+${recipe.result.quantity} ${recipe.name}`;
this.scene.events.emit('floating-text', {
x: this.scene.player.sprite.x,
y: this.scene.player.sprite.y - 50,
text: text,
color: '#00ff00'
});
// ✨ PARTICLE EFFECT - Craft sparkles
if (this.scene.particleEnhancements) {
this.scene.particleEnhancements.craftSparkles(
this.scene.player.sprite.x,
this.scene.player.sprite.y
);
}
}
// Remove from queue
this.craftingQueue.shift();
// Start next craft
this.startNextCraft();
}
// Cancel current craft
cancelCraft() {
if (!this.currentCraft) return false;
const recipe = this.currentCraft.recipe;
// Refund ingredients (partial refund based on progress)
const refundPercent = 1.0 - this.craftProgress;
const inventory = this.scene.inventorySystem;
for (const [itemId, amount] of Object.entries(recipe.ingredients)) {
const refundAmount = Math.floor(amount * refundPercent);
if (refundAmount > 0) {
inventory.addItem(itemId, refundAmount);
}
}
console.log(`❌ Cancelled crafting: ${recipe.name} (${Math.floor(refundPercent * 100)}% refund)`);
// Remove from queue
this.craftingQueue.shift();
// Emit event
this.scene.events.emit('craft-cancelled', recipe.id);
// Start next
this.startNextCraft();
return true;
}
// Get current crafting info
getCurrentCraft() {
if (!this.currentCraft) return null;
return {
recipe: this.currentCraft.recipe,
progress: this.craftProgress,
timeRemaining: this.currentCraft.duration * (1 - this.craftProgress)
};
}
// Get queue length
getQueueLength() {
return this.craftingQueue.length;
}
// Clear entire queue
clearQueue() {
// Refund all queued items
this.craftingQueue.forEach(craft => {
const inventory = this.scene.inventorySystem;
for (const [itemId, amount] of Object.entries(craft.recipe.ingredients)) {
inventory.addItem(itemId, amount);
}
});
this.craftingQueue = [];
this.isCrafting = false;
this.currentCraft = null;
this.craftProgress = 0;
console.log('🗑️ Cleared crafting queue');
}
// Save crafting state
getSaveData() {
return {
unlockedRecipes: Array.from(this.unlockedRecipes),
craftingQueue: this.craftingQueue.map(craft => ({
recipeId: craft.recipeId,
startTime: craft.startTime,
duration: craft.duration
})),
currentProgress: this.craftProgress
};
}
// Load crafting state
loadSaveData(data) {
if (!data) return;
// Restore unlocked recipes
if (data.unlockedRecipes) {
this.unlockedRecipes = new Set(data.unlockedRecipes);
}
// Restore crafting queue
if (data.craftingQueue && data.craftingQueue.length > 0) {
this.craftingQueue = data.craftingQueue.map(saved => ({
recipeId: saved.recipeId,
recipe: this.recipes[saved.recipeId],
startTime: saved.startTime,
duration: saved.duration
}));
this.startNextCraft();
}
console.log('💾 Loaded crafting state');
}
}