Files
novafarma/src/systems/CookingSystem.js
2025-12-13 00:02:38 +01:00

476 lines
13 KiB
JavaScript

/**
* COOKING & RECIPE SYSTEM
* Complete cooking system with recipes, food buffs, spoilage, and skill progression
*/
class CookingSystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// Recipes
this.recipes = new Map();
this.knownRecipes = new Set();
// Cooking stations
this.cookingStations = new Map();
// Active cooking
this.activeCooking = [];
// Food items
this.foodItems = new Map();
// Cooking skill
this.cookingLevel = 1;
this.cookingXP = 0;
// Settings
this.settings = {
spoilageRate: 0.01, // 1% per minute
xpPerRecipe: 10,
xpScaling: 1.5
};
this.loadProgress();
this.init();
console.log('✅ Cooking System initialized');
}
init() {
this.defineRecipes();
this.defineCookingStations();
console.log('🍳 Cooking system ready');
}
// ========== RECIPES ==========
defineRecipes() {
// Basic recipes
this.defineRecipe('wheat_bread', {
name: 'Wheat Bread',
ingredients: { wheat: 3, water: 1 },
cookTime: 30, // seconds
cookingStation: 'oven',
buffs: { hunger: 50, health: 10 },
buffDuration: 0, // permanent (hunger/health)
spoilTime: 300, // 5 minutes
xp: 10,
requiredLevel: 1
});
this.defineRecipe('vegetable_soup', {
name: 'Vegetable Soup',
ingredients: { carrot: 2, potato: 2, water: 1 },
cookTime: 45,
cookingStation: 'stove',
buffs: { hunger: 60, health: 15, stamina: 20 },
buffDuration: 180, // 3 minutes
spoilTime: 240,
xp: 15,
requiredLevel: 2
});
this.defineRecipe('grilled_meat', {
name: 'Grilled Meat',
ingredients: { raw_meat: 1 },
cookTime: 20,
cookingStation: 'grill',
buffs: { hunger: 70, health: 20, strength: 15 },
buffDuration: 300, // 5 minutes
spoilTime: 180,
xp: 20,
requiredLevel: 3
});
this.defineRecipe('mutant_stew', {
name: 'Mutant Stew',
ingredients: { mutant_meat: 2, carrot: 3, potato: 2, water: 1 },
cookTime: 60,
cookingStation: 'cauldron',
buffs: { hunger: 80, health: 30, strength: 25, speed: 15 },
buffDuration: 600, // 10 minutes
spoilTime: 360,
xp: 50,
requiredLevel: 5
});
this.defineRecipe('golden_apple_pie', {
name: 'Golden Apple Pie',
ingredients: { golden_apple: 1, wheat: 5, sugar: 3 },
cookTime: 90,
cookingStation: 'oven',
buffs: { hunger: 100, health: 50, all_stats: 20 },
buffDuration: 900, // 15 minutes
spoilTime: 600,
xp: 100,
requiredLevel: 10
});
}
defineRecipe(id, data) {
this.recipes.set(id, {
id,
...data,
discovered: false
});
}
// ========== COOKING STATIONS ==========
defineCookingStations() {
this.cookingStations.set('stove', {
name: 'Stove',
cost: { iron: 10, wood: 5 },
cookingSpeed: 1.0
});
this.cookingStations.set('oven', {
name: 'Oven',
cost: { iron: 15, stone: 20 },
cookingSpeed: 1.2
});
this.cookingStations.set('grill', {
name: 'Grill',
cost: { iron: 8, wood: 10 },
cookingSpeed: 0.8
});
this.cookingStations.set('cauldron', {
name: 'Cauldron',
cost: { iron: 20, magic_crystal: 1 },
cookingSpeed: 1.5
});
}
// ========== COOKING ==========
canCook(recipeId) {
const recipe = this.recipes.get(recipeId);
if (!recipe) return false;
// Check level
if (this.cookingLevel < recipe.requiredLevel) {
console.log(`❌ Requires cooking level ${recipe.requiredLevel}`);
return false;
}
// Check ingredients
if (!this.scene.inventorySystem) return false;
for (const [ingredient, amount] of Object.entries(recipe.ingredients)) {
const has = this.scene.inventorySystem.getItemCount(ingredient);
if (has < amount) {
console.log(`❌ Missing ${ingredient}: ${has}/${amount}`);
return false;
}
}
return true;
}
startCooking(recipeId, stationType) {
if (!this.canCook(recipeId)) return false;
const recipe = this.recipes.get(recipeId);
const station = this.cookingStations.get(stationType);
if (!station) {
console.log('❌ Invalid cooking station');
return false;
}
if (recipe.cookingStation !== stationType) {
console.log(`❌ Requires ${recipe.cookingStation}`);
return false;
}
// Consume ingredients
for (const [ingredient, amount] of Object.entries(recipe.ingredients)) {
this.scene.inventorySystem.removeItem(ingredient, amount);
}
// Start cooking
const cookTime = recipe.cookTime / station.cookingSpeed;
const cooking = {
recipeId,
startTime: Date.now(),
cookTime: cookTime * 1000, // convert to ms
station: stationType
};
this.activeCooking.push(cooking);
// Discover recipe
if (!recipe.discovered) {
this.discoverRecipe(recipeId);
}
console.log(`🍳 Started cooking ${recipe.name} (${cookTime}s)`);
return true;
}
updateCooking(delta) {
const now = Date.now();
for (let i = this.activeCooking.length - 1; i >= 0; i--) {
const cooking = this.activeCooking[i];
const elapsed = now - cooking.startTime;
if (elapsed >= cooking.cookTime) {
// Cooking complete!
this.completeCooking(cooking);
this.activeCooking.splice(i, 1);
}
}
}
completeCooking(cooking) {
const recipe = this.recipes.get(cooking.recipeId);
// Create food item
const food = this.createFoodItem(recipe);
// Add to inventory
if (this.scene.inventorySystem) {
this.scene.inventorySystem.addItem(cooking.recipeId, 1);
}
// Grant XP
this.addCookingXP(recipe.xp);
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
console.log(`✅ Cooked ${recipe.name}!`);
}
createFoodItem(recipe) {
const food = {
id: `food_${Date.now()}`,
recipeId: recipe.id,
name: recipe.name,
buffs: recipe.buffs,
buffDuration: recipe.buffDuration,
createdTime: Date.now(),
spoilTime: recipe.spoilTime * 1000,
spoiled: false
};
this.foodItems.set(food.id, food);
return food;
}
// ========== EATING ==========
eatFood(foodId) {
const food = this.foodItems.get(foodId);
if (!food) return false;
// Check if spoiled
if (this.isSpoiled(food)) {
console.log('🤢 Food is spoiled!');
// Negative effects
if (this.scene.statsSystem) {
this.scene.statsSystem.health -= 10;
}
this.foodItems.delete(foodId);
return false;
}
// Apply buffs
this.applyFoodBuffs(food);
// Remove food
this.foodItems.delete(foodId);
console.log(`😋 Ate ${food.name}!`);
return true;
}
applyFoodBuffs(food) {
const buffs = food.buffs;
// Permanent buffs (hunger, health)
if (this.scene.statsSystem) {
if (buffs.hunger) {
this.scene.statsSystem.hunger = Math.min(100, this.scene.statsSystem.hunger + buffs.hunger);
}
if (buffs.health) {
this.scene.statsSystem.health = Math.min(this.scene.statsSystem.maxHealth, this.scene.statsSystem.health + buffs.health);
}
}
// Temporary buffs
if (food.buffDuration > 0) {
this.applyTemporaryBuffs(buffs, food.buffDuration);
}
}
applyTemporaryBuffs(buffs, duration) {
// Apply buffs for duration
const buffData = {
buffs,
startTime: Date.now(),
duration: duration * 1000
};
// Store active buffs (would integrate with player stats)
console.log(`✨ Buffs active for ${duration}s:`, buffs);
// Schedule buff removal
setTimeout(() => {
console.log('⏰ Buffs expired');
}, duration * 1000);
}
// ========== SPOILAGE ==========
updateSpoilage(delta) {
const now = Date.now();
for (const food of this.foodItems.values()) {
const age = now - food.createdTime;
if (age > food.spoilTime) {
food.spoiled = true;
}
}
}
isSpoiled(food) {
const age = Date.now() - food.createdTime;
return age > food.spoilTime;
}
// ========== RECIPE DISCOVERY ==========
discoverRecipe(recipeId) {
const recipe = this.recipes.get(recipeId);
if (!recipe) return;
recipe.discovered = true;
this.knownRecipes.add(recipeId);
console.log(`📖 Discovered recipe: ${recipe.name}!`);
// Achievement
if (this.scene.uiGraphics && this.knownRecipes.size >= 10) {
this.scene.uiGraphics.unlockAchievement('master_chef');
}
this.saveProgress();
}
tryDiscoverRecipe(ingredients) {
// Try to match ingredients to unknown recipes
for (const [recipeId, recipe] of this.recipes.entries()) {
if (recipe.discovered) continue;
// Check if ingredients match
const matches = this.matchIngredients(ingredients, recipe.ingredients);
if (matches) {
this.discoverRecipe(recipeId);
return recipe;
}
}
return null;
}
matchIngredients(provided, required) {
const providedKeys = Object.keys(provided).sort();
const requiredKeys = Object.keys(required).sort();
if (providedKeys.length !== requiredKeys.length) return false;
for (let i = 0; i < providedKeys.length; i++) {
if (providedKeys[i] !== requiredKeys[i]) return false;
}
return true;
}
// ========== SKILL PROGRESSION ==========
addCookingXP(amount) {
this.cookingXP += amount;
// Level up check
const xpNeeded = this.getCookingXPForLevel(this.cookingLevel + 1);
if (this.cookingXP >= xpNeeded) {
this.levelUpCooking();
}
this.saveProgress();
}
getCookingXPForLevel(level) {
return Math.floor(100 * Math.pow(this.settings.xpScaling, level - 1));
}
levelUpCooking() {
this.cookingLevel++;
this.cookingXP = 0;
console.log(`🎉 Cooking level up! Now level ${this.cookingLevel}`);
// Visual effect
if (this.scene.visualEnhancements) {
const player = this.scene.player;
if (player) {
const pos = player.getPosition();
this.scene.visualEnhancements.createSparkleEffect(pos.x, pos.y);
}
}
this.saveProgress();
}
// ========== UPDATE ==========
update(delta) {
this.updateCooking(delta);
this.updateSpoilage(delta);
}
// ========== PERSISTENCE ==========
saveProgress() {
const data = {
cookingLevel: this.cookingLevel,
cookingXP: this.cookingXP,
knownRecipes: Array.from(this.knownRecipes)
};
localStorage.setItem('novafarma_cooking', JSON.stringify(data));
}
loadProgress() {
const saved = localStorage.getItem('novafarma_cooking');
if (saved) {
try {
const data = JSON.parse(saved);
this.cookingLevel = data.cookingLevel || 1;
this.cookingXP = data.cookingXP || 0;
this.knownRecipes = new Set(data.knownRecipes || []);
console.log('✅ Cooking progress loaded');
} catch (error) {
console.error('Failed to load cooking progress:', error);
}
}
}
destroy() {
this.saveProgress();
console.log('🍳 Cooking System destroyed');
}
}