278 lines
8.4 KiB
JavaScript
278 lines
8.4 KiB
JavaScript
/**
|
|
* Galaxy Strike Online - Server Crafting System
|
|
* Manages crafting recipes, materials, and item creation
|
|
*/
|
|
|
|
class CraftingSystem {
|
|
constructor() {
|
|
this.recipes = new Map();
|
|
this.playerCrafting = new Map(); // userId -> crafting data
|
|
this.initializeRecipes();
|
|
}
|
|
|
|
initializeRecipes() {
|
|
// Basic weapon recipes
|
|
this.addRecipe('basic_blaster', {
|
|
name: 'Basic Blaster',
|
|
type: 'weapon',
|
|
rarity: 'common',
|
|
description: 'A simple blaster for beginners',
|
|
materials: {
|
|
'iron_ore': 5,
|
|
'copper_wire': 3,
|
|
'energy_crystal': 1
|
|
},
|
|
results: {
|
|
'basic_blaster': 1,
|
|
'experience': 25
|
|
},
|
|
skillRequired: 1,
|
|
craftingTime: 5000 // 5 seconds
|
|
});
|
|
|
|
// Advanced weapon recipes
|
|
this.addRecipe('plasma_cannon', {
|
|
name: 'Plasma Cannon',
|
|
type: 'weapon',
|
|
rarity: 'rare',
|
|
description: 'A powerful plasma-based weapon',
|
|
materials: {
|
|
'iron_ore': 15,
|
|
'copper_wire': 10,
|
|
'energy_crystal': 5,
|
|
'rare_metal': 3
|
|
},
|
|
results: {
|
|
'plasma_cannon': 1,
|
|
'experience': 100
|
|
},
|
|
skillRequired: 10,
|
|
craftingTime: 15000 // 15 seconds
|
|
});
|
|
|
|
// Armor recipes
|
|
this.addRecipe('basic_armor', {
|
|
name: 'Basic Armor',
|
|
type: 'armor',
|
|
rarity: 'common',
|
|
description: 'Light protection for beginners',
|
|
materials: {
|
|
'iron_ore': 8,
|
|
'copper_wire': 2
|
|
},
|
|
results: {
|
|
'basic_armor': 1,
|
|
'experience': 30
|
|
},
|
|
skillRequired: 2,
|
|
craftingTime: 8000 // 8 seconds
|
|
});
|
|
|
|
// Consumable recipes
|
|
this.addRecipe('health_kit', {
|
|
name: 'Health Kit',
|
|
type: 'consumable',
|
|
rarity: 'common',
|
|
description: 'Restores health when used',
|
|
materials: {
|
|
'iron_ore': 2,
|
|
'energy_crystal': 1
|
|
},
|
|
results: {
|
|
'health_kit': 3,
|
|
'experience': 10
|
|
},
|
|
skillRequired: 1,
|
|
craftingTime: 2000 // 2 seconds
|
|
});
|
|
}
|
|
|
|
addRecipe(id, recipe) {
|
|
this.recipes.set(id, {
|
|
id,
|
|
...recipe,
|
|
createdAt: new Date().toISOString()
|
|
});
|
|
}
|
|
|
|
getRecipe(id) {
|
|
return this.recipes.get(id);
|
|
}
|
|
|
|
getAllRecipes() {
|
|
return Array.from(this.recipes.values());
|
|
}
|
|
|
|
getRecipesByType(type) {
|
|
return Array.from(this.recipes.values()).filter(recipe => recipe.type === type);
|
|
}
|
|
|
|
getRecipesByRarity(rarity) {
|
|
return Array.from(this.recipes.values()).filter(recipe => recipe.rarity === rarity);
|
|
}
|
|
|
|
initializePlayerData(userId) {
|
|
if (!this.playerCrafting.has(userId)) {
|
|
this.playerCrafting.set(userId, {
|
|
skill: 1,
|
|
experience: 0,
|
|
knownRecipes: new Set(['basic_blaster', 'health_kit']), // Start with basic recipes
|
|
craftingHistory: [],
|
|
totalCrafted: 0
|
|
});
|
|
}
|
|
return this.playerCrafting.get(userId);
|
|
}
|
|
|
|
getPlayerData(userId) {
|
|
return this.playerCrafting.get(userId) || this.initializePlayerData(userId);
|
|
}
|
|
|
|
canCraft(userId, recipeId, playerInventory) {
|
|
const recipe = this.getRecipe(recipeId);
|
|
if (!recipe) {
|
|
return { canCraft: false, reason: 'Recipe not found' };
|
|
}
|
|
|
|
const playerData = this.getPlayerData(userId);
|
|
|
|
// Check skill requirement
|
|
if (playerData.skill < recipe.skillRequired) {
|
|
return { canCraft: false, reason: 'Insufficient crafting skill' };
|
|
}
|
|
|
|
// Check materials
|
|
for (const [material, amount] of Object.entries(recipe.materials)) {
|
|
const playerAmount = playerInventory[material] || 0;
|
|
if (playerAmount < amount) {
|
|
return { canCraft: false, reason: `Insufficient ${material}` };
|
|
}
|
|
}
|
|
|
|
return { canCraft: true };
|
|
}
|
|
|
|
async craftItem(userId, recipeId, playerInventory) {
|
|
const canCraftResult = this.canCraft(userId, recipeId, playerInventory);
|
|
if (!canCraftResult.canCraft) {
|
|
throw new Error(canCraftResult.reason);
|
|
}
|
|
|
|
const recipe = this.getRecipe(recipeId);
|
|
const playerData = this.getPlayerData(userId);
|
|
|
|
// Remove materials from inventory
|
|
for (const [material, amount] of Object.entries(recipe.materials)) {
|
|
playerInventory[material] = (playerInventory[material] || 0) - amount;
|
|
}
|
|
|
|
// Add results to inventory
|
|
for (const [item, amount] of Object.entries(recipe.results)) {
|
|
if (item !== 'experience') {
|
|
playerInventory[item] = (playerInventory[item] || 0) + amount;
|
|
}
|
|
}
|
|
|
|
// Add experience and update stats
|
|
const experienceGained = recipe.results.experience || 0;
|
|
playerData.experience += experienceGained;
|
|
playerData.totalCrafted += 1;
|
|
|
|
// Check for skill up
|
|
const oldSkill = playerData.skill;
|
|
const newSkill = this.calculateSkillLevel(playerData.experience);
|
|
playerData.skill = newSkill;
|
|
|
|
// Record crafting history
|
|
playerData.craftingHistory.push({
|
|
recipeId,
|
|
timestamp: new Date().toISOString(),
|
|
experienceGained,
|
|
skillUp: newSkill > oldSkill
|
|
});
|
|
|
|
// Keep only last 100 crafting records
|
|
if (playerData.craftingHistory.length > 100) {
|
|
playerData.craftingHistory = playerData.craftingHistory.slice(-100);
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
recipe,
|
|
results: recipe.results,
|
|
experienceGained,
|
|
newSkill,
|
|
skillUp: newSkill > oldSkill,
|
|
playerInventory
|
|
};
|
|
}
|
|
|
|
calculateSkillLevel(experience) {
|
|
// Simple skill progression: 100 XP per level
|
|
return Math.floor(experience / 100) + 1;
|
|
}
|
|
|
|
learnRecipe(userId, recipeId) {
|
|
const recipe = this.getRecipe(recipeId);
|
|
if (!recipe) {
|
|
throw new Error('Recipe not found');
|
|
}
|
|
|
|
const playerData = this.getPlayerData(userId);
|
|
playerData.knownRecipes.add(recipeId);
|
|
|
|
return {
|
|
success: true,
|
|
recipeId,
|
|
recipeName: recipe.name
|
|
};
|
|
}
|
|
|
|
getPlayerKnownRecipes(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
return Array.from(playerData.knownRecipes).map(recipeId => this.getRecipe(recipeId));
|
|
}
|
|
|
|
getCraftingStats(userId) {
|
|
const playerData = this.getPlayerData(userId);
|
|
return {
|
|
skill: playerData.skill,
|
|
experience: playerData.experience,
|
|
totalCrafted: playerData.totalCrafted,
|
|
knownRecipesCount: playerData.knownRecipes.size,
|
|
recentCrafting: playerData.craftingHistory.slice(-10)
|
|
};
|
|
}
|
|
|
|
discoverRecipe(userId, recipeId) {
|
|
const recipe = this.getRecipe(recipeId);
|
|
if (!recipe) {
|
|
throw new Error('Recipe not found');
|
|
}
|
|
|
|
const playerData = this.getPlayerData(userId);
|
|
|
|
if (playerData.knownRecipes.has(recipeId)) {
|
|
return { success: false, reason: 'Recipe already known' };
|
|
}
|
|
|
|
// Chance to discover based on skill level
|
|
const discoveryChance = Math.min(0.1 + (playerData.skill * 0.05), 0.5);
|
|
const discovered = Math.random() < discoveryChance;
|
|
|
|
if (discovered) {
|
|
playerData.knownRecipes.add(recipeId);
|
|
return {
|
|
success: true,
|
|
recipeId,
|
|
recipeName: recipe.name,
|
|
discovered: true
|
|
};
|
|
}
|
|
|
|
return { success: false, discovered: false };
|
|
}
|
|
}
|
|
|
|
module.exports = CraftingSystem;
|