ok
This commit is contained in:
371
EMERGENCY_SYSTEMS_RECOVERY/SaveLoadSystem.js
Normal file
371
EMERGENCY_SYSTEMS_RECOVERY/SaveLoadSystem.js
Normal file
@@ -0,0 +1,371 @@
|
||||
/**
|
||||
* SAVE/LOAD SYSTEM & AGING ENGINE
|
||||
* Persistent storage for player progress, Kai aging, and companion states
|
||||
*/
|
||||
|
||||
class SaveLoadSystem {
|
||||
constructor() {
|
||||
this.saveKey = 'mrtva_dolina_save';
|
||||
this.currentSave = null;
|
||||
this.autoSaveInterval = 300000; // 5 minutes
|
||||
this.autoSaveTimer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* CREATE NEW SAVE FILE
|
||||
*/
|
||||
createNewSave() {
|
||||
this.currentSave = {
|
||||
version: '1.0.0',
|
||||
created: new Date().toISOString(),
|
||||
lastSaved: new Date().toISOString(),
|
||||
|
||||
// Player data
|
||||
player: {
|
||||
position: { x: 0, y: 0 },
|
||||
age_level: 1, // 1-9 (corresponds to age stages)
|
||||
current_age: 14, // Actual age in years
|
||||
age_sprite: 'kai_age14',
|
||||
inventory: [],
|
||||
equipped_tools: {
|
||||
weapon: null,
|
||||
tool: null
|
||||
},
|
||||
health: 100,
|
||||
stamina: 100,
|
||||
stats: {
|
||||
strength: 1,
|
||||
speed: 1,
|
||||
farming: 1
|
||||
}
|
||||
},
|
||||
|
||||
// Progress tracking
|
||||
progress: {
|
||||
memories_found: 0,
|
||||
total_memories: 100,
|
||||
quests_completed: [],
|
||||
quests_active: [],
|
||||
npcs_met: [],
|
||||
biomes_unlocked: ['grassland'],
|
||||
locations_discovered: [],
|
||||
enemies_defeated: 0,
|
||||
crops_harvested: 0,
|
||||
buildings_built: 0
|
||||
},
|
||||
|
||||
// Companions
|
||||
companions: {
|
||||
gronk: {
|
||||
unlocked: false,
|
||||
level: 1,
|
||||
xp: 0,
|
||||
stats: {}
|
||||
},
|
||||
susi: {
|
||||
unlocked: false,
|
||||
position: { x: 0, y: 0 },
|
||||
loyalty: 100
|
||||
}
|
||||
},
|
||||
|
||||
// Farm state
|
||||
farm: {
|
||||
crops: [],
|
||||
buildings: [],
|
||||
animals: [],
|
||||
resources: {
|
||||
wood: 0,
|
||||
stone: 0,
|
||||
cannabis_capital: 0
|
||||
}
|
||||
},
|
||||
|
||||
// Economic state
|
||||
economy: {
|
||||
money: 0,
|
||||
cannabis_seeds: 5, // Starting capital!
|
||||
cannabis_harvested: 0,
|
||||
total_earnings: 0
|
||||
},
|
||||
|
||||
// Game settings
|
||||
settings: {
|
||||
difficulty: 'normal',
|
||||
language: 'en',
|
||||
music_volume: 0.7,
|
||||
sfx_volume: 0.8
|
||||
},
|
||||
|
||||
// Playtime
|
||||
playtime: 0 // seconds
|
||||
};
|
||||
|
||||
console.log('💾 New save file created');
|
||||
return this.currentSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* SAVE GAME
|
||||
*/
|
||||
save() {
|
||||
if (!this.currentSave) {
|
||||
this.currentSave = this.createNewSave();
|
||||
}
|
||||
|
||||
this.currentSave.lastSaved = new Date().toISOString();
|
||||
|
||||
try {
|
||||
localStorage.setItem(this.saveKey, JSON.stringify(this.currentSave));
|
||||
console.log('💾 Game saved successfully');
|
||||
|
||||
// Show save notification
|
||||
this.showSaveNotification();
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('❌ Save failed:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LOAD GAME
|
||||
*/
|
||||
load() {
|
||||
try {
|
||||
const saved = localStorage.getItem(this.saveKey);
|
||||
if (!saved) {
|
||||
console.log('📂 No save file found, creating new...');
|
||||
return this.createNewSave();
|
||||
}
|
||||
|
||||
this.currentSave = JSON.parse(saved);
|
||||
console.log('📂 Game loaded successfully');
|
||||
console.log(' Age Level:', this.currentSave.player.age_level);
|
||||
console.log(' Memories:', this.currentSave.progress.memories_found + '/' + this.currentSave.progress.total_memories);
|
||||
|
||||
return this.currentSave;
|
||||
} catch (e) {
|
||||
console.error('❌ Load failed:', e);
|
||||
return this.createNewSave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UPDATE PLAYER DATA
|
||||
*/
|
||||
updatePlayer(data) {
|
||||
if (!this.currentSave) this.load();
|
||||
|
||||
this.currentSave.player = {
|
||||
...this.currentSave.player,
|
||||
...data
|
||||
};
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* UPDATE PROGRESS
|
||||
*/
|
||||
updateProgress(data) {
|
||||
if (!this.currentSave) this.load();
|
||||
|
||||
this.currentSave.progress = {
|
||||
...this.currentSave.progress,
|
||||
...data
|
||||
};
|
||||
|
||||
// Check if aging should trigger
|
||||
this.checkAgingProgress();
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* START AUTO-SAVE
|
||||
*/
|
||||
startAutoSave() {
|
||||
if (this.autoSaveTimer) {
|
||||
clearInterval(this.autoSaveTimer);
|
||||
}
|
||||
|
||||
this.autoSaveTimer = setInterval(() => {
|
||||
this.save();
|
||||
console.log('💾 Auto-save triggered');
|
||||
}, this.autoSaveInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* STOP AUTO-SAVE
|
||||
*/
|
||||
stopAutoSave() {
|
||||
if (this.autoSaveTimer) {
|
||||
clearInterval(this.autoSaveTimer);
|
||||
this.autoSaveTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AGING ENGINE - CHECK IF KAI SHOULD AGE UP
|
||||
*/
|
||||
checkAgingProgress() {
|
||||
if (!this.currentSave) return;
|
||||
|
||||
const memoriesFound = this.currentSave.progress.memories_found;
|
||||
const totalMemories = this.currentSave.progress.total_memories;
|
||||
const progress = (memoriesFound / totalMemories) * 100;
|
||||
|
||||
let newAgeLevel = 1;
|
||||
let newAge = 14;
|
||||
let newSprite = 'kai_age14';
|
||||
|
||||
// Age progression based on memory recovery
|
||||
if (progress >= 90) {
|
||||
newAgeLevel = 9;
|
||||
newAge = 60;
|
||||
newSprite = 'kai_age60';
|
||||
} else if (progress >= 75) {
|
||||
newAgeLevel = 7;
|
||||
newAge = 50;
|
||||
newSprite = 'kai_age50';
|
||||
} else if (progress >= 60) {
|
||||
newAgeLevel = 6;
|
||||
newAge = 40;
|
||||
newSprite = 'kai_age40';
|
||||
} else if (progress >= 50) {
|
||||
newAgeLevel = 5;
|
||||
newAge = 30;
|
||||
newSprite = 'kai_age30';
|
||||
} else if (progress >= 35) {
|
||||
newAgeLevel = 4;
|
||||
newAge = 25;
|
||||
newSprite = 'kai_age25';
|
||||
} else if (progress >= 25) {
|
||||
newAgeLevel = 3;
|
||||
newAge = 20;
|
||||
newSprite = 'kai_age20';
|
||||
} else if (progress >= 10) {
|
||||
newAgeLevel = 2;
|
||||
newAge = 16;
|
||||
newSprite = 'kai_age16';
|
||||
}
|
||||
|
||||
// Check if age changed
|
||||
if (newAgeLevel > this.currentSave.player.age_level) {
|
||||
this.triggerAging(newAgeLevel, newAge, newSprite);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TRIGGER AGING CUTSCENE
|
||||
*/
|
||||
triggerAging(newLevel, newAge, newSprite) {
|
||||
const oldLevel = this.currentSave.player.age_level;
|
||||
const oldAge = this.currentSave.player.current_age;
|
||||
|
||||
// Update save data
|
||||
this.currentSave.player.age_level = newLevel;
|
||||
this.currentSave.player.current_age = newAge;
|
||||
this.currentSave.player.age_sprite = newSprite;
|
||||
|
||||
console.log(`⏰ KAI AGES UP!`);
|
||||
console.log(` ${oldAge} → ${newAge} years old`);
|
||||
console.log(` Sprite: ${newSprite}`);
|
||||
|
||||
// Emit aging event for cutscene
|
||||
const event = new CustomEvent('kai-aging', {
|
||||
detail: {
|
||||
oldLevel: oldLevel,
|
||||
newLevel: newLevel,
|
||||
oldAge: oldAge,
|
||||
newAge: newAge,
|
||||
newSprite: newSprite,
|
||||
memoriesFound: this.currentSave.progress.memories_found
|
||||
}
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* SHOW SAVE NOTIFICATION
|
||||
*/
|
||||
showSaveNotification() {
|
||||
const event = new CustomEvent('game-saved', {
|
||||
detail: {
|
||||
time: new Date().toLocaleTimeString(),
|
||||
slot: 1
|
||||
}
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET CURRENT SAVE DATA
|
||||
*/
|
||||
getCurrentSave() {
|
||||
if (!this.currentSave) {
|
||||
this.load();
|
||||
}
|
||||
return this.currentSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE SAVE
|
||||
*/
|
||||
deleteSave() {
|
||||
if (confirm('Are you sure you want to delete your save file?')) {
|
||||
localStorage.removeItem(this.saveKey);
|
||||
this.currentSave = null;
|
||||
console.log('🗑️ Save file deleted');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPORT SAVE (for backup)
|
||||
*/
|
||||
exportSave() {
|
||||
if (!this.currentSave) return null;
|
||||
|
||||
const saveData = JSON.stringify(this.currentSave, null, 2);
|
||||
const blob = new Blob([saveData], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `mrtva_dolina_save_${Date.now()}.json`;
|
||||
a.click();
|
||||
|
||||
console.log('📤 Save exported');
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORT SAVE (from backup)
|
||||
*/
|
||||
importSave(fileInput) {
|
||||
const file = fileInput.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
const imported = JSON.parse(e.target.result);
|
||||
localStorage.setItem(this.saveKey, JSON.stringify(imported));
|
||||
this.currentSave = imported;
|
||||
console.log('📥 Save imported successfully');
|
||||
} catch (err) {
|
||||
console.error('❌ Import failed:', err);
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton instance
|
||||
const saveLoadSystem = new SaveLoadSystem();
|
||||
export default saveLoadSystem;
|
||||
Reference in New Issue
Block a user