468 lines
16 KiB
JavaScript
468 lines
16 KiB
JavaScript
/**
|
||
* BLUEPRINT SYSTEM (EXPANDED)
|
||
* Manages unlocking crafting recipes via Blueprint items.
|
||
*
|
||
* EXPANSION FEATURES (P24):
|
||
* - 9 Discovery Methods: Museum, Digging (5%), Beaches, Chests, Boss Drops, NPC Gifts, Quest Rewards, Fishing, Ancient Ruins
|
||
* - Building Requirements: Cannot build structures without blueprints
|
||
* - Weapon/Bow Shop Unlocks: Via Wasteland Military Base & Forest Hunter's Lodge quests
|
||
* - Blueprint UI/Tracker: Collection progress, gallery view
|
||
*/
|
||
class BlueprintSystem {
|
||
constructor(scene) {
|
||
this.scene = scene;
|
||
this.unlockedRecipes = new Set(); // Stores IDs of unlocked recipes
|
||
|
||
// Default unlocked recipes (Basic tools & structures)
|
||
this.unlockedRecipes.add('stick');
|
||
this.unlockedRecipes.add('plank');
|
||
this.unlockedRecipes.add('chest');
|
||
this.unlockedRecipes.add('fence');
|
||
this.unlockedRecipes.add('axe');
|
||
this.unlockedRecipes.add('pickaxe');
|
||
this.unlockedRecipes.add('hoe');
|
||
this.unlockedRecipes.add('sword');
|
||
|
||
// Blueprint Categories
|
||
this.categories = {
|
||
basic: ['fence', 'chest', 'campfire', 'torch'],
|
||
buildings: ['house', 'barn', 'greenhouse', 'workshop', 'silo', 'coop', 'stable'],
|
||
advanced: ['furnace', 'anvil', 'loom', 'brewery', 'laboratory'],
|
||
weapons: ['iron_sword', 'steel_sword', 'katana', 'flame_sword', 'plasma_rifle'],
|
||
bows: ['wooden_bow', 'composite_bow', 'crossbow', 'explosive_bow', 'laser_bow'],
|
||
vehicles: ['scooter', 'atv', 'tractor', 'helicopter'],
|
||
special: ['portal_repair', 'time_machine', 'cloning_vat']
|
||
};
|
||
|
||
// Blueprint Definitions (Item ID -> Recipe ID)
|
||
this.blueprints = {
|
||
// Basic
|
||
'blueprint_campfire': 'campfire',
|
||
'blueprint_torch': 'torch',
|
||
|
||
// Buildings (REQUIRED to build!)
|
||
'blueprint_house': 'house',
|
||
'blueprint_barn': 'barn',
|
||
'blueprint_greenhouse': 'greenhouse',
|
||
'blueprint_workshop': 'workshop',
|
||
'blueprint_silo': 'silo',
|
||
'blueprint_chicken_coop': 'coop',
|
||
'blueprint_stable': 'stable',
|
||
|
||
// Advanced
|
||
'blueprint_furnace': 'furnace',
|
||
'blueprint_anvil': 'anvil',
|
||
'blueprint_loom': 'loom',
|
||
'blueprint_brewery': 'brewery',
|
||
'blueprint_laboratory': 'laboratory',
|
||
|
||
// Weapons (Unlocked via Wasteland Military Base quest)
|
||
'blueprint_iron_sword': 'iron_sword',
|
||
'blueprint_steel_sword': 'steel_sword',
|
||
'blueprint_katana': 'katana',
|
||
'blueprint_flame_sword': 'flame_sword',
|
||
'blueprint_plasma_rifle': 'plasma_rifle',
|
||
|
||
// Bows (Unlocked via Forest Hunter's Lodge quest)
|
||
'blueprint_wooden_bow': 'wooden_bow',
|
||
'blueprint_composite_bow': 'composite_bow',
|
||
'blueprint_crossbow': 'crossbow',
|
||
'blueprint_explosive_bow': 'explosive_bow',
|
||
'blueprint_laser_bow': 'laser_bow',
|
||
|
||
// Vehicles
|
||
'blueprint_scooter': 'scooter_engine',
|
||
'blueprint_atv': 'atv',
|
||
'blueprint_tractor': 'tractor',
|
||
'blueprint_helicopter': 'helicopter',
|
||
|
||
// Special
|
||
'blueprint_portal_repair': 'portal_repair',
|
||
'blueprint_time_machine': 'time_machine',
|
||
'blueprint_cloning_vat': 'cloning_vat'
|
||
};
|
||
|
||
// Discovery Methods (9 methods!)
|
||
this.discoveryMethods = {
|
||
museum: { chance: 1.0, blueprints: ['blueprint_anvil', 'blueprint_loom', 'blueprint_time_machine'] },
|
||
digging: { chance: 0.05, blueprints: ['blueprint_house', 'blueprint_barn', 'blueprint_furnace'] },
|
||
beach: { chance: 0.15, blueprints: ['blueprint_workshop', 'blueprint_laboratory'] },
|
||
chest: { chance: 0.30, blueprints: Object.keys(this.blueprints) },
|
||
boss: { chance: 1.0, blueprints: ['blueprint_plasma_rifle', 'blueprint_laser_bow', 'blueprint_cloning_vat'] },
|
||
npc_gift: { chance: 1.0, blueprints: ['blueprint_greenhouse', 'blueprint_brewery', 'blueprint_stable'] },
|
||
quest: { chance: 1.0, blueprints: [] }, // Set by specific quests
|
||
fishing: { chance: 0.08, blueprints: ['blueprint_campfire', 'blueprint_scooter'] },
|
||
ruins: { chance: 0.20, blueprints: ['blueprint_katana', 'blueprint_portal_repair', 'blueprint_helicopter'] }
|
||
};
|
||
|
||
// Quest-locked blueprints
|
||
this.questLocks = {
|
||
'wasteland_military_base_complete': ['blueprint_iron_sword', 'blueprint_steel_sword', 'blueprint_katana', 'blueprint_flame_sword', 'blueprint_plasma_rifle'],
|
||
'forest_hunters_lodge_complete': ['blueprint_wooden_bow', 'blueprint_composite_bow', 'blueprint_crossbow', 'blueprint_explosive_bow', 'blueprint_laser_bow']
|
||
};
|
||
|
||
// Collection tracking
|
||
this.totalBlueprints = Object.keys(this.blueprints).length;
|
||
this.discovered = 0;
|
||
|
||
// UI state
|
||
this.showingGallery = false;
|
||
|
||
console.log('📜 Blueprint System (EXPANDED) initialized!');
|
||
console.log(`📊 Total Blueprints: ${this.totalBlueprints}`);
|
||
}
|
||
|
||
/**
|
||
* Unlock a recipe
|
||
*/
|
||
unlockRecipe(recipeId) {
|
||
if (this.unlockedRecipes.has(recipeId)) {
|
||
console.log(`ℹ️ Recipe ${recipeId} already unlocked.`);
|
||
return false;
|
||
}
|
||
|
||
this.unlockedRecipes.add(recipeId);
|
||
this.discovered++;
|
||
|
||
console.log(`📜 UNLOCKED RECIPE: ${recipeId} (${this.discovered}/${this.totalBlueprints})`);
|
||
|
||
// Notification
|
||
this.scene.events.emit('show-floating-text', {
|
||
x: this.scene.player.sprite.x,
|
||
y: this.scene.player.sprite.y - 100,
|
||
text: `NEW BLUEPRINT: ${recipeId.toUpperCase()}!`,
|
||
color: '#00FFFF'
|
||
});
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Blueprint Discovered!',
|
||
message: `${recipeId.toUpperCase()} unlocked! (${this.discovered}/${this.totalBlueprints})`,
|
||
icon: '📜'
|
||
});
|
||
|
||
if (this.scene.soundManager) this.scene.soundManager.playSuccess();
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Check if unlocked
|
||
*/
|
||
isUnlocked(recipeId) {
|
||
return this.unlockedRecipes.has(recipeId);
|
||
}
|
||
|
||
/**
|
||
* Check if can build (buildings require blueprints!)
|
||
*/
|
||
canBuild(recipeId) {
|
||
const buildingCategories = [...this.categories.buildings, ...this.categories.advanced, ...this.categories.special];
|
||
|
||
// If it's a building, check blueprint
|
||
if (buildingCategories.includes(recipeId)) {
|
||
return this.isUnlocked(recipeId);
|
||
}
|
||
|
||
// Other items can be built without blueprint (but blueprint improves them)
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Use a blueprint item from inventory
|
||
*/
|
||
useBlueprint(itemId) {
|
||
const recipeId = this.blueprints[itemId];
|
||
if (!recipeId) return false;
|
||
|
||
const success = this.unlockRecipe(recipeId);
|
||
if (success) {
|
||
// Consume item
|
||
if (this.scene.inventorySystem) {
|
||
this.scene.inventorySystem.removeItem(itemId, 1);
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Try to discover blueprint via specific method
|
||
* @param {string} method - 'museum', 'digging', 'beach', 'chest', 'boss', 'npc_gift', 'quest', 'fishing', 'ruins'
|
||
* @param {number} x - X position
|
||
* @param {number} y - Y position
|
||
* @param {string} questId - Optional quest ID for quest-specific blueprints
|
||
*/
|
||
tryDiscover(method, x, y, questId = null) {
|
||
const discoveryData = this.discoveryMethods[method];
|
||
if (!discoveryData) {
|
||
console.log(`❌ Unknown discovery method: ${method}`);
|
||
return false;
|
||
}
|
||
|
||
// Roll for discovery
|
||
if (Math.random() > discoveryData.chance) {
|
||
return false; // No discovery
|
||
}
|
||
|
||
// Select blueprint from method's pool
|
||
let availableBlueprints = discoveryData.blueprints;
|
||
|
||
// Filter out already unlocked
|
||
availableBlueprints = availableBlueprints.filter(bp => {
|
||
const recipeId = this.blueprints[bp];
|
||
return recipeId && !this.isUnlocked(recipeId);
|
||
});
|
||
|
||
if (availableBlueprints.length === 0) {
|
||
console.log('ℹ️ All blueprints from this method already discovered!');
|
||
return false;
|
||
}
|
||
|
||
const blueprintItem = availableBlueprints[Math.floor(Math.random() * availableBlueprints.length)];
|
||
|
||
// Spawn blueprint item
|
||
if (this.scene.interactionSystem) {
|
||
this.scene.interactionSystem.spawnLoot(x, y, blueprintItem, 1);
|
||
console.log(`📜 Discovered Blueprint: ${blueprintItem} via ${method}!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Blueprint Found!',
|
||
message: `Discovered ${blueprintItem}!`,
|
||
icon: '📜'
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Unlock quest-specific blueprints
|
||
*/
|
||
unlockQuestBlueprints(questId) {
|
||
const blueprints = this.questLocks[questId];
|
||
if (!blueprints) {
|
||
console.log(`ℹ️ No blueprints locked behind quest: ${questId}`);
|
||
return [];
|
||
}
|
||
|
||
const unlocked = [];
|
||
|
||
blueprints.forEach(blueprintItem => {
|
||
const recipeId = this.blueprints[blueprintItem];
|
||
if (recipeId) {
|
||
this.unlockRecipe(recipeId);
|
||
unlocked.push(recipeId);
|
||
}
|
||
});
|
||
|
||
if (unlocked.length > 0) {
|
||
console.log(`🎉 Quest "${questId}" unlocked ${unlocked.length} blueprints!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Quest Blueprints Unlocked!',
|
||
message: `${unlocked.length} new blueprints available!`,
|
||
icon: '🎉'
|
||
});
|
||
}
|
||
|
||
return unlocked;
|
||
}
|
||
|
||
/**
|
||
* Get NPC gift blueprint
|
||
*/
|
||
getNPCGift(npcName) {
|
||
const giftBlueprints = this.discoveryMethods.npc_gift.blueprints;
|
||
const available = giftBlueprints.filter(bp => {
|
||
const recipeId = this.blueprints[bp];
|
||
return recipeId && !this.isUnlocked(recipeId);
|
||
});
|
||
|
||
if (available.length === 0) return null;
|
||
|
||
const blueprintItem = available[Math.floor(Math.random() * available.length)];
|
||
|
||
console.log(`🎁 ${npcName} gifted blueprint: ${blueprintItem}!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Gift from ' + npcName,
|
||
message: `Received ${blueprintItem}!`,
|
||
icon: '🎁'
|
||
});
|
||
|
||
return blueprintItem;
|
||
}
|
||
|
||
/**
|
||
* Dig for blueprint (5% chance)
|
||
*/
|
||
digForBlueprint(x, y) {
|
||
return this.tryDiscover('digging', x, y);
|
||
}
|
||
|
||
/**
|
||
* Beach combing for blueprint (15% chance)
|
||
*/
|
||
beachComb(x, y) {
|
||
return this.tryDiscover('beach', x, y);
|
||
}
|
||
|
||
/**
|
||
* Fishing for blueprint (8% chance)
|
||
*/
|
||
fishForBlueprint(x, y) {
|
||
return this.tryDiscover('fishing', x, y);
|
||
}
|
||
|
||
/**
|
||
* Explore ancient ruins for blueprint (20% chance)
|
||
*/
|
||
exploreRuins(x, y) {
|
||
return this.tryDiscover('ruins', x, y);
|
||
}
|
||
|
||
/**
|
||
* Open chest for blueprint (30% chance)
|
||
*/
|
||
openChest(x, y) {
|
||
return this.tryDiscover('chest', x, y);
|
||
}
|
||
|
||
/**
|
||
* Boss drops blueprint (100% chance, rare blueprints)
|
||
*/
|
||
bossDrop(x, y) {
|
||
return this.tryDiscover('boss', x, y);
|
||
}
|
||
|
||
/**
|
||
* Museum visit (specific blueprints, 100% chance)
|
||
*/
|
||
visitMuseum() {
|
||
const museumBlueprints = this.discoveryMethods.museum.blueprints;
|
||
const available = museumBlueprints.filter(bp => {
|
||
const recipeId = this.blueprints[bp];
|
||
return recipeId && !this.isUnlocked(recipeId);
|
||
});
|
||
|
||
if (available.length === 0) {
|
||
console.log('ℹ️ All museum blueprints already acquired!');
|
||
return null;
|
||
}
|
||
|
||
const blueprintItem = available[0]; // Give first available
|
||
|
||
console.log(`🏛️ Museum blueprint acquired: ${blueprintItem}!`);
|
||
|
||
this.scene.events.emit('notification', {
|
||
title: 'Museum Discovery!',
|
||
message: `Acquired ${blueprintItem}!`,
|
||
icon: '🏛️'
|
||
});
|
||
|
||
return blueprintItem;
|
||
}
|
||
|
||
/**
|
||
* Get collection progress
|
||
*/
|
||
getProgress() {
|
||
return {
|
||
discovered: this.discovered,
|
||
total: this.totalBlueprints,
|
||
percentage: Math.round((this.discovered / this.totalBlueprints) * 100)
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Get blueprints by category
|
||
*/
|
||
getBlueprintsByCategory(category) {
|
||
if (!this.categories[category]) return [];
|
||
|
||
return this.categories[category].map(recipeId => {
|
||
return {
|
||
recipeId: recipeId,
|
||
unlocked: this.isUnlocked(recipeId)
|
||
};
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Show blueprint gallery UI
|
||
*/
|
||
showGallery() {
|
||
this.showingGallery = true;
|
||
|
||
const progress = this.getProgress();
|
||
|
||
console.log('📚 BLUEPRINT GALLERY');
|
||
console.log(`Progress: ${progress.discovered}/${progress.total} (${progress.percentage}%)`);
|
||
console.log('─────────────────────────────────');
|
||
|
||
Object.keys(this.categories).forEach(category => {
|
||
const blueprints = this.getBlueprintsByCategory(category);
|
||
const unlocked = blueprints.filter(bp => bp.unlocked).length;
|
||
|
||
console.log(`${category.toUpperCase()}: ${unlocked}/${blueprints.length}`);
|
||
blueprints.forEach(bp => {
|
||
const icon = bp.unlocked ? '✅' : '🔒';
|
||
console.log(` ${icon} ${bp.recipeId}`);
|
||
});
|
||
});
|
||
|
||
// Emit UI event for rendering
|
||
this.scene.events.emit('show-blueprint-gallery', {
|
||
progress: progress,
|
||
categories: this.categories,
|
||
getBlueprintsByCategory: (cat) => this.getBlueprintsByCategory(cat)
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Hide blueprint gallery UI
|
||
*/
|
||
hideGallery() {
|
||
this.showingGallery = false;
|
||
this.scene.events.emit('hide-blueprint-gallery');
|
||
}
|
||
|
||
/**
|
||
* Get hint for locked blueprint
|
||
*/
|
||
getHint(recipeId) {
|
||
// Find blueprint item for this recipe
|
||
const blueprintItem = Object.keys(this.blueprints).find(key => this.blueprints[key] === recipeId);
|
||
if (!blueprintItem) return 'Unknown';
|
||
|
||
// Check which discovery method has it
|
||
for (const [method, data] of Object.entries(this.discoveryMethods)) {
|
||
if (data.blueprints.includes(blueprintItem)) {
|
||
const hints = {
|
||
museum: 'Visit the Museum',
|
||
digging: 'Try digging (5% chance)',
|
||
beach: 'Search beaches (15% chance)',
|
||
chest: 'Open chests (30% chance)',
|
||
boss: 'Defeat bosses (100% chance)',
|
||
npc_gift: 'Befriend NPCs',
|
||
quest: 'Complete quests',
|
||
fishing: 'Go fishing (8% chance)',
|
||
ruins: 'Explore ancient ruins (20% chance)'
|
||
};
|
||
return hints[method] || 'Unknown method';
|
||
}
|
||
}
|
||
|
||
// Check quest locks
|
||
for (const [questId, blueprints] of Object.entries(this.questLocks)) {
|
||
if (blueprints.includes(blueprintItem)) {
|
||
return `Complete quest: ${questId}`;
|
||
}
|
||
}
|
||
|
||
return 'Discover through exploration';
|
||
}
|
||
}
|
||
|