LEGENDARY NIGHT! P22-P25 complete - 4 new systems (2,300 LOC) - Smart Zombies, Tools, Blueprints, Ana Clues!
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
/**
|
||||
* BLUEPRINT SYSTEM
|
||||
* 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) {
|
||||
@@ -16,17 +22,94 @@ class BlueprintSystem {
|
||||
this.unlockedRecipes.add('pickaxe');
|
||||
this.unlockedRecipes.add('hoe');
|
||||
this.unlockedRecipes.add('sword');
|
||||
this.unlockedRecipes.add('furnace');
|
||||
this.unlockedRecipes.add('mint');
|
||||
this.unlockedRecipes.add('grave');
|
||||
|
||||
// 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_scooter_part': 'scooter_engine', // Example special part
|
||||
'blueprint_grave': 'gravestone'
|
||||
'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}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,16 +122,24 @@ class BlueprintSystem {
|
||||
}
|
||||
|
||||
this.unlockedRecipes.add(recipeId);
|
||||
console.log(`📜 UNLOCKED RECIPE: ${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 RECIPE: ${recipeId.toUpperCase()}!`,
|
||||
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;
|
||||
}
|
||||
@@ -60,6 +151,21 @@ class BlueprintSystem {
|
||||
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
|
||||
*/
|
||||
@@ -70,33 +176,292 @@ class BlueprintSystem {
|
||||
const success = this.unlockRecipe(recipeId);
|
||||
if (success) {
|
||||
// Consume item
|
||||
this.scene.inventorySystem.removeItem(itemId, 1);
|
||||
if (this.scene.inventorySystem) {
|
||||
this.scene.inventorySystem.removeItem(itemId, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to get a blueprint drop from mining/killing
|
||||
* @param {string} source 'mining', 'combat', 'chest'
|
||||
* 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
|
||||
*/
|
||||
tryDropBlueprint(x, y, source) {
|
||||
let chance = 0.05; // 5% base chance
|
||||
if (source === 'boss') chance = 1.0;
|
||||
if (source === 'chest') chance = 0.3;
|
||||
tryDiscover(method, x, y, questId = null) {
|
||||
const discoveryData = this.discoveryMethods[method];
|
||||
if (!discoveryData) {
|
||||
console.log(`❌ Unknown discovery method: ${method}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.random() < chance) {
|
||||
// Select random locked blueprint
|
||||
const allBlueprints = Object.keys(this.blueprints);
|
||||
const dropItem = allBlueprints[Math.floor(Math.random() * allBlueprints.length)];
|
||||
// Roll for discovery
|
||||
if (Math.random() > discoveryData.chance) {
|
||||
return false; // No discovery
|
||||
}
|
||||
|
||||
// Check if user already has it unlocked? Maybe drop anyway for trading?
|
||||
// For now, simple drop.
|
||||
// Select blueprint from method's pool
|
||||
let availableBlueprints = discoveryData.blueprints;
|
||||
|
||||
if (this.scene.interactionSystem) {
|
||||
this.scene.interactionSystem.spawnLoot(x, y, dropItem, 1);
|
||||
console.log(`📜 Dropped Blueprint: ${dropItem}`);
|
||||
// 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';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user