Files
novafarma/src/systems/AnaClueSystem.js

414 lines
20 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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)
});
}
}