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

537 lines
16 KiB
JavaScript

/**
* RecipeSystem.js
* ===============
* Manages crafting recipes, blueprints, and progression unlocks
*
* Features:
* - Recipe database with material requirements
* - Blueprint unlock mechanics (find, level, quest, buy)
* - Crafting validation and execution
* - Material consumption
* - Crafting time delays
* - UI integration
*
* @author NovaFarma Team
* @date 2025-12-22
*/
export default class RecipeSystem {
constructor(scene) {
this.scene = scene;
// Recipe storage
this.recipes = new Map();
this.unlockedRecipes = new Set();
this.blueprintLocations = new Map(); // World spawn locations
// Crafting state
this.currentlyCrafting = null;
this.craftQueue = [];
// Categories
this.categories = {
BUILDING: 'building',
EQUIPMENT: 'equipment',
FURNITURE: 'furniture',
MAGIC: 'magic',
TRANSPORT: 'transport',
UPGRADE: 'upgrade'
};
// Initialize recipe database
this.initializeRecipes();
// Load saved unlocks
this.loadUnlockedRecipes();
console.log('🔨 RecipeSystem initialized with', this.recipes.size, 'recipes');
}
initializeRecipes() {
// ===== BUILDING RECIPES =====
this.addRecipe('wooden_fence', {
name: 'Wooden Fence',
category: this.categories.BUILDING,
description: 'Basic fence to keep animals in',
materials: [
{ item: 'wood', quantity: 5, displayName: 'Wood' },
{ item: 'nails', quantity: 2, displayName: 'Nails' }
],
craftTime: 2000, // 2 seconds
unlockLevel: 1,
blueprint: null, // Available from start
output: { item: 'fence_wooden', quantity: 1 },
sprite: 'fence_horizontal'
});
this.addRecipe('stone_fence', {
name: 'Stone Fence',
category: this.categories.BUILDING,
description: 'Durable stone fence',
materials: [
{ item: 'stone', quantity: 10, displayName: 'Stone' },
{ item: 'mortar', quantity: 3, displayName: 'Mortar' }
],
craftTime: 4000,
unlockLevel: 5,
blueprint: 'blueprint_stone_fence',
output: { item: 'fence_stone', quantity: 1 },
sprite: 'fence_full'
});
this.addRecipe('house_upgrade_2', {
name: 'House Upgrade Level 2',
category: this.categories.UPGRADE,
description: 'Expand your house - adds bedroom',
materials: [
{ item: 'wood', quantity: 100, displayName: 'Wood' },
{ item: 'stone', quantity: 50, displayName: 'Stone' },
{ item: 'gold', quantity: 500, displayName: 'Gold' }
],
craftTime: 10000, // 10 seconds
unlockLevel: 3,
blueprint: 'blueprint_house_2',
output: { item: 'house_level_2', quantity: 1 },
sprite: 'house_sprite',
prerequisites: ['house_level_1']
});
this.addRecipe('barn_upgrade_2', {
name: 'Barn Upgrade Level 2',
category: this.categories.UPGRADE,
description: 'Expand barn capacity to 8 animals',
materials: [
{ item: 'wood', quantity: 75, displayName: 'Wood' },
{ item: 'stone', quantity: 30, displayName: 'Stone' },
{ item: 'gold', quantity: 400, displayName: 'Gold' }
],
craftTime: 8000,
unlockLevel: 4,
blueprint: 'blueprint_barn_2',
output: { item: 'barn_level_2', quantity: 1 },
sprite: 'barn_isometric'
});
// ===== EQUIPMENT RECIPES =====
this.addRecipe('iron_axe', {
name: 'Iron Axe',
category: this.categories.EQUIPMENT,
description: 'Chops trees faster than basic axe',
materials: [
{ item: 'iron_ingot', quantity: 3, displayName: 'Iron Ingot' },
{ item: 'wood', quantity: 2, displayName: 'Wood' }
],
craftTime: 3000,
unlockLevel: 2,
blueprint: null,
output: { item: 'axe_iron', quantity: 1 },
sprite: 'tools'
});
this.addRecipe('steel_pickaxe', {
name: 'Steel Pickaxe',
category: this.categories.EQUIPMENT,
description: 'Mine rare ores',
materials: [
{ item: 'steel_ingot', quantity: 5, displayName: 'Steel Ingot' },
{ item: 'wood', quantity: 3, displayName: 'Wood' }
],
craftTime: 5000,
unlockLevel: 6,
blueprint: 'blueprint_steel_pickaxe',
output: { item: 'pickaxe_steel', quantity: 1 },
sprite: 'tools'
});
// ===== FURNITURE RECIPES =====
this.addRecipe('wooden_bed', {
name: 'Wooden Bed',
category: this.categories.FURNITURE,
description: 'Comfortable place to sleep',
materials: [
{ item: 'wood', quantity: 30, displayName: 'Wood' },
{ item: 'fabric', quantity: 10, displayName: 'Fabric' }
],
craftTime: 4000,
unlockLevel: 2,
blueprint: null,
output: { item: 'bed_wooden', quantity: 1 },
sprite: 'house_sprite'
});
// ===== MAGIC RECIPES =====
this.addRecipe('fire_staff', {
name: 'Fire Staff',
category: this.categories.MAGIC,
description: 'Cast fire spells',
materials: [
{ item: 'magic_crystal', quantity: 5, displayName: 'Magic Crystal' },
{ item: 'wood', quantity: 10, displayName: 'Enchanted Wood' },
{ item: 'ruby', quantity: 1, displayName: 'Ruby' }
],
craftTime: 8000,
unlockLevel: 10,
blueprint: 'blueprint_fire_staff',
output: { item: 'staff_fire', quantity: 1 },
sprite: 'magic_staffs_6_types'
});
// ===== TRANSPORT RECIPES =====
this.addRecipe('wooden_cart', {
name: 'Wooden Cart',
category: this.categories.TRANSPORT,
description: 'Haul resources faster',
materials: [
{ item: 'wood', quantity: 50, displayName: 'Wood' },
{ item: 'iron_ingot', quantity: 10, displayName: 'Iron' },
{ item: 'rope', quantity: 5, displayName: 'Rope' }
],
craftTime: 6000,
unlockLevel: 5,
blueprint: 'blueprint_cart',
output: { item: 'cart_wooden', quantity: 1 },
sprite: 'cart_wagon_system'
});
console.log('📜 Loaded', this.recipes.size, 'recipes');
}
addRecipe(id, data) {
this.recipes.set(id, {
id,
...data,
timescrafted: 0
});
}
canCraft(recipeId) {
const recipe = this.recipes.get(recipeId);
if (!recipe) {
console.warn('Recipe not found:', recipeId);
return { canCraft: false, reason: 'Recipe not found' };
}
// Check if unlocked
if (recipe.blueprint && !this.unlockedRecipes.has(recipeId)) {
return { canCraft: false, reason: 'Blueprint not unlocked' };
}
// Check level requirement
const playerLevel = this.scene.player?.stats?.level || 1;
if (playerLevel < recipe.unlockLevel) {
return {
canCraft: false,
reason: `Requires level ${recipe.unlockLevel}`
};
}
// Check prerequisites
if (recipe.prerequisites) {
for (const prereq of recipe.prerequisites) {
if (!this.hasItem(prereq)) {
return {
canCraft: false,
reason: `Requires ${prereq}`
};
}
}
}
// Check materials
const missingMaterials = [];
for (const material of recipe.materials) {
const hasQuantity = this.getItemQuantity(material.item);
if (hasQuantity < material.quantity) {
missingMaterials.push({
item: material.displayName,
need: material.quantity,
have: hasQuantity
});
}
}
if (missingMaterials.length > 0) {
return {
canCraft: false,
reason: 'Missing materials',
missing: missingMaterials
};
}
return { canCraft: true };
}
craft(recipeId) {
const check = this.canCraft(recipeId);
if (!check.canCraft) {
this.scene.uiSystem?.showError(check.reason);
return false;
}
const recipe = this.recipes.get(recipeId);
// Consume materials
this.consumeMaterials(recipe);
// Show crafting UI
this.scene.uiSystem?.showCraftingProgress(recipe);
// Set crafting state
this.currentlyCrafting = {
recipeId,
startTime: Date.now(),
endTime: Date.now() + recipe.craftTime
};
// Wait for craft time
this.scene.time.delayedCall(recipe.craftTime, () => {
this.completeCraft(recipe);
});
// Emit event
this.scene.events.emit('craftingStarted', { recipeId, recipe });
return true;
}
consumeMaterials(recipe) {
for (const material of recipe.materials) {
this.removeItem(material.item, material.quantity);
}
console.log('💰 Consumed materials for:', recipe.name);
}
completeCraft(recipe) {
// Add item to inventory
this.addItem(recipe.output.item, recipe.output.quantity);
// Update stats
recipe.timescrafted++;
// Clear crafting state
this.currentlyCrafting = null;
// Show notification
this.scene.uiSystem?.showNotification({
title: 'Crafting Complete!',
message: `Created ${recipe.name}`,
icon: recipe.sprite,
duration: 3000
});
// Emit event
this.scene.events.emit('craftingComplete', {
recipeId: recipe.id,
recipe,
output: recipe.output
});
// Process queue if any
if (this.craftQueue.length > 0) {
const nextRecipe = this.craftQueue.shift();
this.craft(nextRecipe);
}
console.log('✅ Crafted:', recipe.name);
}
// ===== BLUEPRINT UNLOCK SYSTEM =====
unlockBlueprint(recipeId, method = 'find') {
if (this.unlockedRecipes.has(recipeId)) {
console.warn('Blueprint already unlocked:', recipeId);
return false;
}
const recipe = this.recipes.get(recipeId);
if (!recipe) {
console.warn('Recipe not found:', recipeId);
return false;
}
// Add to unlocked
this.unlockedRecipes.add(recipeId);
// Show notification
this.scene.uiSystem?.showNotification({
title: '📜 Blueprint Unlocked!',
message: `You can now craft: ${recipe.name}`,
icon: 'blueprint',
duration: 5000,
color: '#FFD700'
});
// Save unlocks
this.saveUnlockedRecipes();
// Emit event
this.scene.events.emit('blueprintUnlocked', {
recipeId,
recipe,
method
});
console.log('📜 Blueprint unlocked:', recipe.name, `(${method})`);
return true;
}
findBlueprintInWorld(x, y) {
// Check if player is near a blueprint object
const nearbyBlueprints = this.scene.blueprintObjects?.filter(bp => {
const distance = Phaser.Math.Distance.Between(x, y, bp.x, bp.y);
return distance < 50; // Within 50 pixels
});
if (nearbyBlueprints && nearbyBlueprints.length > 0) {
const blueprint = nearbyBlueprints[0];
this.unlockBlueprint(blueprint.recipeId, 'find');
blueprint.destroy(); // Remove from world
return true;
}
return false;
}
unlockBlueprintByLevel(level) {
// Auto-unlock recipes at certain levels
const levelUnlocks = {
2: ['iron_axe', 'wooden_bed'],
5: ['stone_fence', 'wooden_cart'],
10: ['fire_staff']
};
if (levelUnlocks[level]) {
for (const recipeId of levelUnlocks[level]) {
this.unlockBlueprint(recipeId, 'level');
}
}
}
// ===== INVENTORY INTEGRATION =====
hasItem(itemId) {
// Integrate with InventorySystem
if (this.scene.inventorySystem) {
return this.scene.inventorySystem.hasItem(itemId);
}
// Fallback: check player stats
return this.scene.player?.inventory?.[itemId] > 0;
}
getItemQuantity(itemId) {
// Integrate with InventorySystem
if (this.scene.inventorySystem) {
return this.scene.inventorySystem.getQuantity(itemId);
}
// Fallback
return this.scene.player?.inventory?.[itemId] || 0;
}
addItem(itemId, quantity) {
// Integrate with InventorySystem
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(itemId, quantity);
} else {
// Fallback
if (!this.scene.player.inventory) {
this.scene.player.inventory = {};
}
this.scene.player.inventory[itemId] =
(this.scene.player.inventory[itemId] || 0) + quantity;
}
}
removeItem(itemId, quantity) {
// Integrate with InventorySystem
if (this.scene.inventorySystem) {
this.scene.inventorySystem.removeItem(itemId, quantity);
} else {
// Fallback
this.scene.player.inventory[itemId] -= quantity;
}
}
// ===== DATA PERSISTENCE =====
saveUnlockedRecipes() {
const unlocked = Array.from(this.unlockedRecipes);
localStorage.setItem('unlockedRecipes', JSON.stringify(unlocked));
}
loadUnlockedRecipes() {
const saved = localStorage.getItem('unlockedRecipes');
if (saved) {
const unlocked = JSON.parse(saved);
this.unlockedRecipes = new Set(unlocked);
console.log('📜 Loaded', this.unlockedRecipes.size, 'unlocked recipes');
}
}
// ===== GETTERS =====
getRecipe(recipeId) {
return this.recipes.get(recipeId);
}
getAllRecipes() {
return Array.from(this.recipes.values());
}
getRecipesByCategory(category) {
return this.getAllRecipes().filter(r => r.category === category);
}
getUnlockedRecipes() {
return this.getAllRecipes().filter(r =>
!r.blueprint || this.unlockedRecipes.has(r.id)
);
}
getLockedRecipes() {
return this.getAllRecipes().filter(r =>
r.blueprint && !this.unlockedRecipes.has(r.id)
);
}
getCraftableRecipes() {
return this.getUnlockedRecipes().filter(r =>
this.canCraft(r.id).canCraft
);
}
getCraftingProgress() {
if (!this.currentlyCrafting) return null;
const elapsed = Date.now() - this.currentlyCrafting.startTime;
const total = this.currentlyCrafting.endTime - this.currentlyCrafting.startTime;
const progress = Math.min(1, elapsed / total);
return {
recipeId: this.currentlyCrafting.recipeId,
progress,
timeRemaining: Math.max(0, this.currentlyCrafting.endTime - Date.now())
};
}
// ===== UPDATE =====
update(time, delta) {
// Update crafting progress UI
if (this.currentlyCrafting) {
const progress = this.getCraftingProgress();
this.scene.events.emit('craftingProgress', progress);
}
}
// ===== CLEANUP =====
destroy() {
this.saveUnlockedRecipes();
this.recipes.clear();
this.unlockedRecipes.clear();
this.blueprintLocations.clear();
this.craftQueue = [];
this.currentlyCrafting = null;
}
}