LEGENDARY NIGHT! P22-P25 complete - 4 new systems (2,300 LOC) - Smart Zombies, Tools, Blueprints, Ana Clues!

This commit is contained in:
2025-12-23 21:28:55 +01:00
parent 4d1428b523
commit 8939c51edb
5 changed files with 1954 additions and 68 deletions

View File

@@ -0,0 +1,413 @@
/**
* ANA'S CLUE SYSTEM
* Manages the 50 collectible clues left by Ana across the world.
*
* Features:
* - 50 Collectibles: 15 Messages, 12 Photos, 23 Personal Items
* - Story Integration: Each clue reveals plot and lore
* - Emotional Cutscenes: Kai's reactions and Twin Bond activations
* - Progressive Discovery: Clues unlock as player explores biomes
* - Collection UI: Track progress, view discovered clues
*/
class AnaClueSystem {
constructor(scene) {
this.scene = scene;
// Clue categories
this.categories = {
messages: [], // 15 handwritten messages
photos: [], // 12 photographs
items: [] // 23 personal items
};
// All 50 clues
this.allClues = this.initializeClues();
// Discovered clues
this.discovered = new Set();
// Story progression
this.storyUnlocks = {
5: 'act1_context', // First 5 clues unlock Act 1 context
10: 'zmaj_volk_reveal', // Giant Troll King reveal
15: 'twin_bond_boost', // Twin Bond strengthens
25: 'act2_context', // Act 2 context unlocked
35: 'final_location_hint', // Hint to Ana's location
50: 'true_ending_unlock' // True ending unlocked
};
// Clue locations (biome-specific)
this.clueLocations = new Map();
console.log('💜 Ana\'s Clue System initialized!');
console.log(`📊 Total Clues: ${this.allClues.length}`);
}
/**
* Initialize all 50 clues
*/
initializeClues() {
const clues = [];
// 15 MESSAGES
const messages = [
{ id: 'msg_01', type: 'message', title: 'First Note', biome: 'forest', content: 'Kai, if you find this... I\'m sorry. They took me. Stay safe. -Ana' },
{ id: 'msg_02', type: 'message', title: 'Hidden Trail', biome: 'wasteland', content: 'Following them west. Trail of red flowers marks my path.' },
{ id: 'msg_03', type: 'message', title: 'The Creatures', biome: 'swamp', content: 'The zombies... they\'re not mindless. I saw intelligence in their eyes.' },
{ id: 'msg_04', type: 'message', title: 'The King', biome: 'mountains', content: 'The Giant Troll King. That\'s who leads them. I heard his name.' },
{ id: 'msg_05', type: 'message', title: 'Hope Valley', biome: 'hope_valley', content: 'Hope Valley was beautiful once. We could rebuild it together.' },
{ id: 'msg_06', type: 'message', title: 'Twin Bond', biome: 'crystal_caves', content: 'I can feel you searching for me. Our bond is strong, Kai.' },
{ id: 'msg_07', type: 'message', title: 'The Portals', biome: 'portal_ruins', content: 'Ancient portals everywhere. If we repair them, we could travel instantly.' },
{ id: 'msg_08', type: 'message', title: 'Laboratory Notes', biome: 'laboratory', content: 'Found a lab. Research on "domestication" of the infected. Disturbing.' },
{ id: 'msg_09', type: 'message', title: 'The Cure', biome: 'medical_facility', content: 'There might be a cure. Research was close before the fall.' },
{ id: 'msg_10', type: 'message', title: 'Family Dreams', biome: 'abandoned_house', content: 'I dream of a family, Kai. Children playing in safe fields.' },
{ id: 'msg_11', type: 'message', title: 'The Atlanteans', biome: 'atlantis', content: 'Underwater ruins! Advanced civilization. Atlantis was REAL!' },
{ id: 'msg_12', type: 'message', title: 'Chernobyl Warning', biome: 'chernobyl', content: 'Radiation zone ahead. Be careful if you follow me here.' },
{ id: 'msg_13', type: 'message', title: 'Amazon Expedition', biome: 'amazon', content: 'The jungle is dense but alive. So much biodiversity!' },
{ id: 'msg_14', type: 'message', title: 'Final Warning', biome: 'dark_fortress', content: 'Don\'t come for me, Kai. Too dangerous. Save yourself!' },
{ id: 'msg_15', type: 'message', title: 'True Feelings', biome: 'final_castle', content: 'I know you won\'t listen. You never do. I love you, brother.' }
];
// 12 PHOTOS
const photos = [
{ id: 'photo_01', type: 'photo', title: 'Family Portrait', biome: 'forest', description: 'Photo of Kai and Ana as children, smiling.' },
{ id: 'photo_02', type: 'photo', title: 'Attack Night', biome: 'wasteland', description: 'Blurry photo of Giant Troll King during the attack.' },
{ id: 'photo_03', type: 'photo', title: 'Hope Valley (Before)', biome: 'hope_valley', description: 'Beautiful town before the apocalypse.' },
{ id: 'photo_04', type: 'photo', title: 'First Zombie', biome: 'swamp', description: 'Photo of a Level 1 zombie, looking confused.' },
{ id: 'photo_05', type: 'photo', title: 'Portal Network Map', biome: 'portal_ruins', description: 'Hand-drawn map showing portal locations.' },
{ id: 'photo_06', type: 'photo', title: 'Laboratory Interior', biome: 'laboratory', description: 'High-tech lab equipment, still functional.' },
{ id: 'photo_07', type: 'photo', title: 'Ana\'s Journal', biome: 'mountains', description: 'Close-up of Ana\'s handwriting.' },
{ id: 'photo_08', type: 'photo', title: 'Atlantean Artifact', biome: 'atlantis', description: 'Glowing crystal technology from Atlantis.' },
{ id: 'photo_09', type: 'photo', title: 'Reactor Core', biome: 'chernobyl', description: 'Damaged reactor, eerie green glow.' },
{ id: 'photo_10', type: 'photo', title: 'Jungle Temple', biome: 'amazon', description: 'Ancient temple overgrown with vines.' },
{ id: 'photo_11', type: 'photo', title: 'The Captor', biome: 'dark_fortress', description: 'Shadowy figure—Ana\'s captor.' },
{ id: 'photo_12', type: 'photo', title: 'Final Message', biome: 'final_castle', description: 'Ana holding a "Find Me" sign, tears in eyes.' }
];
// 23 PERSONAL ITEMS
const items = [
{ id: 'item_01', type: 'item', title: 'Ana\'s Bracelet', biome: 'forest', description: 'Silver bracelet with twin symbols.' },
{ id: 'item_02', type: 'item', title: 'Torn Dress Piece', biome: 'wasteland', description: 'Fragment of Ana\'s favorite dress.' },
{ id: 'item_03', type: 'item', title: 'Hairpin', biome: 'swamp', description: 'Ana\'s decorative hairpin, muddy but intact.' },
{ id: 'item_04', type: 'item', title: 'Pocket Watch', biome: 'mountains', description: 'Father\'s pocket watch, Ana always carried it.' },
{ id: 'item_05', type: 'item', title: 'Compass', biome: 'hope_valley', description: 'Engraved compass: "To Ana, find your way home."' },
{ id: 'item_06', type: 'item', title: 'Childhood Toy', biome: 'abandoned_house', description: 'Small stuffed rabbit from childhood.' },
{ id: 'item_07', type: 'item', title: 'Music Box', biome: 'crystal_caves', description: 'Delicate music box, plays Ana\'s favorite song.' },
{ id: 'item_08', type: 'item', title: 'Sketchbook', biome: 'portal_ruins', description: 'Ana\'s art sketchbook, filled with drawings.' },
{ id: 'item_09', type: 'item', title: 'Necklace', biome: 'laboratory', description: 'Mother\'s necklace, Ana\'s most treasured item.' },
{ id: 'item_10', type: 'item', title: 'Diary Page', biome: 'medical_facility', description: 'Torn diary page describing her fears.' },
{ id: 'item_11', type: 'item', title: 'Herb Pouch', biome: 'forest', description: 'Pouch of medicinal herbs Ana collected.' },
{ id: 'item_12', type: 'item', title: 'Glove (Left)', biome: 'wasteland', description: 'One of Ana\'s gloves, left behind.' },
{ id: 'item_13', type: 'item', title: 'Glove (Right)', biome: 'dark_fortress', description: 'The matching right glove.' },
{ id: 'item_14', type: 'item', title: 'Lucky Coin', biome: 'atlantis', description: 'Old coin Ana considered lucky.' },
{ id: 'item_15', type: 'item', title: 'Ribbon', biome: 'chernobyl', description: 'Purple ribbon from Ana\'s hair.' },
{ id: 'item_16', type: 'item', title: 'Boot Buckle', biome: 'amazon', description: 'Buckle from Ana\'s boot, broken off.' },
{ id: 'item_17', type: 'item', title: 'Locket', biome: 'mountains', description: 'Heart-shaped locket with Kai\'s photo inside.' },
{ id: 'item_18', type: 'item', title: 'Handkerchief', biome: 'swamp', description: 'Embroidered handkerchief, Ana\'s initials.' },
{ id: 'item_19', type: 'item', title: 'Map Fragment', biome: 'portal_ruins', description: 'Piece of a larger map, Ana\'s notes.' },
{ id: 'item_20', type: 'item', title: 'Flower Press', biome: 'hope_valley', description: 'Ana pressed flowers in this book.' },
{ id: 'item_21', type: 'item', title: 'Candle Stub', biome: 'crystal_caves', description: 'Half-burned candle, Ana used for light.' },
{ id: 'item_22', type: 'item', title: 'Broken Mirror', biome: 'laboratory', description: 'Shattered hand mirror, Ana\'s reflection.' },
{ id: 'item_23', type: 'item', title: 'Final Letter', biome: 'final_castle', description: 'Sealed letter: "Open only when you find me."' }
];
// Combine all clues
clues.push(...messages, ...photos, ...items);
// Store by category
this.categories.messages = messages;
this.categories.photos = photos;
this.categories.items = items;
return clues;
}
/**
* Place clues in the world
*/
placeCluesInWorld() {
this.allClues.forEach(clue => {
// Determine position based on biome (placeholder logic)
const position = this.getBiomePosition(clue.biome);
this.clueLocations.set(clue.id, position);
// Spawn clue object in world (visual representation)
if (this.scene.interactionSystem) {
this.scene.interactionSystem.spawnClue(position.x, position.y, clue);
}
});
console.log(`📍 Placed ${this.allClues.length} clues across the world!`);
}
/**
* Get position for a biome (placeholder)
*/
getBiomePosition(biome) {
// In real implementation, would use biome system
const biomePositions = {
forest: { x: 1000, y: 1000 },
wasteland: { x: 3000, y: 1500 },
swamp: { x: 2000, y: 3000 },
mountains: { x: 4000, y: 500 },
hope_valley: { x: 500, y: 500 },
crystal_caves: { x: 3500, y: 2500 },
portal_ruins: { x: 2500, y: 2000 },
laboratory: { x: 3200, y: 1800 },
medical_facility: { x: 2800, y: 2200 },
abandoned_house: { x: 1500, y: 1200 },
atlantis: { x: 5000, y: 4000 },
chernobyl: { x: 5500, y: 2000 },
amazon: { x: 4500, y: 3500 },
dark_fortress: { x: 6000, y: 1000 },
final_castle: { x: 7000, y: 500 }
};
return biomePositions[biome] || { x: 0, y: 0 };
}
/**
* Discover a clue
*/
discoverClue(clueId) {
if (this.discovered.has(clueId)) {
console.log(' Clue already discovered!');
return false;
}
const clue = this.allClues.find(c => c.id === clueId);
if (!clue) {
console.log(`❌ Clue not found: ${clueId}`);
return false;
}
this.discovered.add(clueId);
console.log(`💜 DISCOVERED: ${clue.title} (${this.discovered.size}/50)`);
// Play discovery cutscene
this.playDiscoveryCutscene(clue);
// Check story progression
this.checkStoryUnlocks();
// Trigger Twin Bond reaction
if (this.scene.twinBondSystem) {
this.scene.twinBondSystem.triggerClueReaction(clue);
}
return true;
}
/**
* Play emotional discovery cutscene
*/
playDiscoveryCutscene(clue) {
console.log(`🎬 CUTSCENE: Discovering "${clue.title}"`);
// Emotional reaction based on clue type
let kaiReaction = '';
switch (clue.type) {
case 'message':
kaiReaction = this.getMessageReaction(clue);
break;
case 'photo':
kaiReaction = this.getPhotoReaction(clue);
break;
case 'item':
kaiReaction = this.getItemReaction(clue);
break;
}
// Show cutscene UI
this.scene.events.emit('show-cutscene', {
type: 'clue_discovery',
clue: clue,
reaction: kaiReaction,
bondActivation: this.discovered.size % 5 === 0 // Twin Bond activates every 5 clues
});
// Play emotional music
if (this.scene.soundManager) {
this.scene.soundManager.playEmotionalTheme();
}
console.log(`💭 Kai: "${kaiReaction}"`);
}
/**
* Get Kai's reaction to a message
*/
getMessageReaction(clue) {
const reactions = {
msg_01: "Ana... I'll find you. I promise.",
msg_02: "Red flowers... I'll follow your trail anywhere.",
msg_03: "Intelligence? Could we... coexist with them?",
msg_04: "The Giant Troll King. I'll face him for you, Ana.",
msg_05: "We WILL rebuild Hope Valley together. I swear it.",
msg_06: "I feel you too, Ana. Our bond will guide me.",
msg_07: "Portals... this could change everything!",
msg_08: "Domestication? This changes how I see them...",
msg_09: "A cure! There's still hope for this world!",
msg_10: "A family... Ana, we'll have that future together.",
msg_11: "Atlantis! Your curiosity never stopped, did it?",
msg_12: "Radiation won't stop me. Nothing will.",
msg_13: "Even captured, you appreciate nature's beauty...",
msg_14: "I'll NEVER give up on you, Ana. Never!",
msg_15: "I love you too, sister. I'm coming for you."
};
return reactions[clue.id] || "Ana... another piece of you found.";
}
/**
* Get Kai's reaction to a photo
*/
getPhotoReaction(clue) {
const reactions = {
photo_01: "*tears up* We were so innocent back then...",
photo_02: "So that's the monster who took you...",
photo_03: "Hope Valley was paradise. It will be again.",
photo_04: "Even then, you saw them differently than others.",
photo_05: "Your map will help me repair them all!",
photo_06: "You documented everything. So thorough, Ana.",
photo_07: "Your handwriting... I'd recognize it anywhere.",
photo_08: "Atlantean tech! This could save us all!",
photo_09: "You went to Chernobyl?! Ana...",
photo_10: "Ancient mysteries. You loved this stuff.",
photo_11: "*clenches fist* I see you, captor. I'm coming.",
photo_12: "*breaks down* I'm coming, Ana. Hold on!"
};
return reactions[clue.id] || "Another memory of you...";
}
/**
* Get Kai's reaction to an item
*/
getItemReaction(clue) {
const reactions = {
item_01: "*holds bracelet* I have the matching one...",
item_09: "*clutches necklace* Mother's necklace! You kept it safe.",
item_13: "*pairs gloves* Both found. You left a trail for me.",
item_17: "*opens locket* My photo... you carried me with you.",
item_23: "*trembling hands* I'll open this when I find you, Ana."
};
return reactions[clue.id] || `${clue.title}... you were here.`;
}
/**
* Check if story unlocks should trigger
*/
checkStoryUnlocks() {
const count = this.discovered.size;
Object.keys(this.storyUnlocks).forEach(threshold => {
const unlockId = this.storyUnlocks[threshold];
if (count >= parseInt(threshold)) {
this.unlockStoryEvent(unlockId, parseInt(threshold));
}
});
}
/**
* Unlock story event
*/
unlockStoryEvent(eventId, clueCount) {
console.log(`🎭 STORY UNLOCK: ${eventId} (${clueCount} clues)`);
const events = {
act1_context: {
title: 'Act 1 Revealed',
message: 'The attack, the kidnapping... the full picture emerges.',
reward: 'Twin Bond Level +1'
},
zmaj_volk_reveal: {
title: 'Giant Troll King\'s Identity',
message: 'The true nature of the captor revealed.',
reward: 'Boss Location Marked'
},
twin_bond_boost: {
title: 'Twin Bond Strengthens',
message: 'Your psychic connection with Ana intensifies!',
reward: 'Twin Bond abilities enhanced'
},
act2_context: {
title: 'Act 2 Begins',
message: 'Ana\'s journey takes unexpected turns...',
reward: 'New locations unlocked'
},
final_location_hint: {
title: 'Ana\'s Location',
message: 'You sense where she is... the final castle.',
reward: 'Final Castle location revealed'
},
true_ending_unlock: {
title: 'ALL CLUES FOUND!',
message: 'Every piece of Ana discovered. True Ending available!',
reward: 'True Ending unlocked'
}
};
const event = events[eventId];
if (event) {
this.scene.events.emit('story-unlock', event);
if (this.scene.soundManager) {
this.scene.soundManager.playDramatic();
}
}
}
/**
* Get collection progress
*/
getProgress() {
return {
total: this.allClues.length,
discovered: this.discovered.size,
percentage: Math.round((this.discovered.size / this.allClues.length) * 100),
messages: this.getTypeProgress('message'),
photos: this.getTypeProgress('photo'),
items: this.getTypeProgress('item')
};
}
/**
* Get progress by type
*/
getTypeProgress(type) {
const typeClues = this.allClues.filter(c => c.type === type);
const discovered = typeClues.filter(c => this.discovered.has(c.id)).length;
return {
total: typeClues.length,
discovered: discovered,
percentage: Math.round((discovered / typeClues.length) * 100)
};
}
/**
* Show collection UI
*/
showCollectionUI() {
const progress = this.getProgress();
console.log('💜 ANA\'S CLUES COLLECTION');
console.log(`Total: ${progress.discovered}/${progress.total} (${progress.percentage}%)`);
console.log('─────────────────────────────────');
console.log(`📝 Messages: ${progress.messages.discovered}/${progress.messages.total} (${progress.messages.percentage}%)`);
console.log(`📷 Photos: ${progress.photos.discovered}/${progress.photos.total} (${progress.photos.percentage}%)`);
console.log(`💎 Items: ${progress.items.discovered}/${progress.items.total} (${progress.items.percentage}%)`);
// Emit UI event
this.scene.events.emit('show-clue-collection', {
progress: progress,
clues: this.allClues,
discovered: Array.from(this.discovered)
});
}
}