This commit is contained in:
2026-01-16 02:43:46 +01:00
parent bc2225ad64
commit 3ae8d39f9c
218 changed files with 87850 additions and 353 deletions

View File

@@ -0,0 +1,398 @@
/**
* GAME MANAGER - AUTO-SAVE SYSTEM
* "The Silent Protector" - Never lose progress!
*/
class GameManager {
constructor(scene) {
this.scene = scene;
this.saveKey = 'mrtva_dolina_save'; // Slot_0
// Auto-save state
this.lastAutoSave = Date.now();
this.autoSaveInterval = 5 * 60 * 1000; // 5 minutes
this.isSaving = false;
// Save indicator
this.saveIndicator = null;
// Initialize
this.init();
}
init() {
console.log('💾 GameManager initialized - Auto-save active');
// Start periodic auto-save timer
this.startPeriodicAutoSave();
// Listen for scene transitions
this.scene.events.on('shutdown', () => this.onSceneTransition());
// Listen for progression events
this.listenForProgressionEvents();
}
/**
* TRIGGER 1: SCENE TRANSITION SAVE
*/
onSceneTransition() {
console.log('🚪 Scene transition detected - Auto-saving...');
this.autoSaveGame('Scene Transition');
}
/**
* TRIGGER 2: PROGRESSION MILESTONE SAVE
*/
listenForProgressionEvents() {
// Listen for aging events
this.scene.events.on('kai-aged', (data) => {
console.log(`⏰ Kai aged to ${data.newAge} - Auto-saving...`);
this.autoSaveGame('Aging Milestone');
});
// Listen for memory found
this.scene.events.on('memory-found', (data) => {
console.log(`📸 Memory found (${data.id}) - Auto-saving...`);
this.autoSaveGame('Memory Found');
});
// Listen for Gronk level up
if (window.gronkStats) {
window.addEventListener('gronk-levelup', (e) => {
console.log(`💨 Gronk level ${e.detail.level} - Auto-saving...`);
this.autoSaveGame('Gronk Level Up');
});
}
// Listen for companion unlocks
window.addEventListener('companion-unlocked', (e) => {
console.log(`🐕 Companion unlocked (${e.detail.name}) - Auto-saving...`);
this.autoSaveGame('Companion Unlock');
});
}
/**
* TRIGGER 3: PERIODIC AUTO-SAVE (5 Minutes)
*/
startPeriodicAutoSave() {
this.periodicTimer = this.scene.time.addEvent({
delay: this.autoSaveInterval,
callback: () => {
const timeSinceLastSave = Date.now() - this.lastAutoSave;
if (timeSinceLastSave >= this.autoSaveInterval) {
console.log('⏱️ 5 minutes elapsed - Auto-saving...');
this.autoSaveGame('Periodic (5min)');
}
},
loop: true
});
}
/**
* AUTO-SAVE GAME (Silent, no interruption)
*/
autoSaveGame(reason = 'Manual') {
if (this.isSaving) {
console.log('⚠️ Save already in progress, skipping...');
return;
}
this.isSaving = true;
console.log(`💾 AUTO-SAVING (${reason})...`);
// Show save indicator
this.showSaveIndicator();
try {
// Gather save data
const saveData = this.gatherSaveData();
// Save to LocalStorage (Slot_0)
localStorage.setItem(this.saveKey, JSON.stringify(saveData));
// Update timestamp
this.lastAutoSave = Date.now();
console.log('✅ Auto-save complete!');
console.log(` Reason: ${reason}`);
console.log(` Size: ${JSON.stringify(saveData).length} bytes`);
} catch (error) {
console.error('❌ Auto-save failed:', error);
} finally {
this.isSaving = false;
}
}
/**
* GATHER ALL SAVE DATA
*/
gatherSaveData() {
const data = {
version: '1.0.0',
lastSaved: new Date().toISOString(),
playtime: this.getPlaytime(),
// Player data
player: this.getPlayerData(),
// Progress
progress: this.getProgressData(),
// Companions
companions: this.getCompanionData(),
// Farm state
farm: this.getFarmData(),
// Economy
economy: this.getEconomyData(),
// Current scene
currentScene: this.scene.scene.key
};
return data;
}
/**
* GET PLAYER DATA
*/
getPlayerData() {
// Get PlayerStats if exists
let playerStats = null;
if (this.scene.playerStats) {
playerStats = this.scene.playerStats.getAgeInfo();
} else {
// Load from LocalStorage
const stored = localStorage.getItem('player_stats');
if (stored) {
playerStats = JSON.parse(stored);
}
}
return {
position: this.getPlayerPosition(),
age_level: playerStats?.level || 1,
current_age: playerStats?.age || 14,
age_sprite: playerStats?.sprite || 'kai_age14',
inventory: this.getInventory(),
health: 100,
stamina: 100,
equipped_tools: {}
};
}
/**
* GET PROGRESS DATA
*/
getProgressData() {
return {
memories_found: this.getMemoriesFound(),
total_memories: 100,
quests_completed: [],
npcs_met: [],
biomes_unlocked: ['grassland']
};
}
/**
* GET COMPANION DATA
*/
getCompanionData() {
const companions = {
gronk: {
unlocked: false,
level: 1,
xp: 0
},
susi: {
unlocked: false,
position: { x: 0, y: 0 },
loyalty: 0
}
};
// Check Gronk stats
if (window.gronkStats) {
const gronkData = gronkStats.getStats();
companions.gronk = {
unlocked: true,
level: gronkData.level,
xp: gronkData.xp
};
}
// Check Susi unlock
const susiUnlocked = localStorage.getItem('susi_unlocked');
if (susiUnlocked === 'true') {
companions.susi.unlocked = true;
}
return companions;
}
/**
* GET FARM DATA
*/
getFarmData() {
return {
crops: [],
buildings: [],
animals: [],
resources: {}
};
}
/**
* GET ECONOMY DATA
*/
getEconomyData() {
return {
money: 0,
cannabis_seeds: 5, // Starting capital!
cannabis_harvested: 0
};
}
/**
* HELPER: Get player position
*/
getPlayerPosition() {
if (this.scene.player) {
return {
x: this.scene.player.x,
y: this.scene.player.y
};
}
return { x: 640, y: 360 }; // Default center
}
/**
* HELPER: Get inventory
*/
getInventory() {
// TODO: Get from inventory system
return [];
}
/**
* HELPER: Get memories found
*/
getMemoriesFound() {
const stored = localStorage.getItem('player_stats');
if (stored) {
const data = JSON.parse(stored);
return data.memoriesFound || 0;
}
return 0;
}
/**
* HELPER: Get playtime
*/
getPlaytime() {
const stored = localStorage.getItem('playtime');
if (stored) {
return parseInt(stored) + Math.floor(this.scene.time.now / 1000);
}
return Math.floor(this.scene.time.now / 1000);
}
/**
* SHOW SAVE INDICATOR (Spinning Longboard)
*/
showSaveIndicator() {
if (this.saveIndicator) {
return; // Already showing
}
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
// Create longboard emoji as indicator
this.saveIndicator = this.scene.add.text(
width - 80,
height - 80,
'🛹',
{
fontSize: '32px'
}
);
this.saveIndicator.setScrollFactor(0);
this.saveIndicator.setDepth(9999);
this.saveIndicator.setAlpha(0);
// Add "Saving..." text
const savingText = this.scene.add.text(
width - 140,
height - 50,
'Saving...',
{
fontSize: '14px',
fontFamily: 'Georgia, serif',
color: '#f4e4c1',
stroke: '#000000',
strokeThickness: 3
}
);
savingText.setScrollFactor(0);
savingText.setDepth(9999);
savingText.setAlpha(0);
// Fade in
this.scene.tweens.add({
targets: [this.saveIndicator, savingText],
alpha: 0.8,
duration: 300
});
// Spin animation
this.scene.tweens.add({
targets: this.saveIndicator,
angle: 360,
duration: 1000,
repeat: 1
});
// Fade out after 2 seconds
this.scene.time.delayedCall(2000, () => {
this.scene.tweens.add({
targets: [this.saveIndicator, savingText],
alpha: 0,
duration: 500,
onComplete: () => {
if (this.saveIndicator) {
this.saveIndicator.destroy();
this.saveIndicator = null;
}
if (savingText) {
savingText.destroy();
}
}
});
});
}
/**
* MANUAL SAVE (for explicit save points)
*/
manualSave() {
console.log('💾 Manual save requested...');
this.autoSaveGame('Manual Save');
}
/**
* CLEANUP
*/
destroy() {
if (this.periodicTimer) {
this.periodicTimer.remove();
}
console.log('💾 GameManager destroyed');
}
}
export default GameManager;

View File

@@ -0,0 +1,446 @@
/**
* MASTER GAME SYSTEMS MANAGER
* Centralized coordinator for all game systems
* Created: January 4, 2026
*
* Integrates:
* - Sleep System
* - Crafting Tables System
* - Bakery Shop System
* - Barber Shop System
* - Lawyer Office System
* - Zombie Miner Automation System
* - Town Growth System
* - NPC Privacy System
* - Existing Mining System
*/
class MasterGameSystemsManager {
constructor(game) {
this.game = game;
this.scene = game.scene;
console.log('🎮 Initializing Master Game Systems Manager...');
// Initialize all systems
this.initializeSystems();
// Set up cross-system event listeners
this.setupEventListeners();
console.log('✅ Master Game Systems Manager initialized!');
}
/**
* Initialize all game systems
*/
initializeSystems() {
// HOME & SLEEP
this.sleepSystem = new SleepSystem(this.game);
console.log(' ✓ Sleep System');
// CRAFTING
this.craftingSystem = new CraftingTablesSystem(this.game);
console.log(' ✓ Crafting Tables System');
// TOWN BUILDINGS
this.bakerySystem = new BakeryShopSystem(this.game);
console.log(' ✓ Bakery Shop System');
this.barberSystem = new BarberShopSystem(this.game);
console.log(' ✓ Barber Shop System');
this.lawyerSystem = new LawyerOfficeSystem(this.game);
console.log(' ✓ Lawyer Office System');
// MINING & AUTOMATION
this.zombieMinerSystem = new ZombieMinerAutomationSystem(this.game);
console.log(' ✓ Zombie Miner Automation System');
// TOWN GROWTH
this.townGrowthSystem = new TownGrowthSystem(this.game);
console.log(' ✓ Town Growth System');
// NPC SYSTEMS
this.npcPrivacySystem = new NPCPrivacySystem(this.game);
console.log(' ✓ NPC Privacy System');
// Register all systems globally
this.registerSystems();
}
/**
* Register systems to game registry
*/
registerSystems() {
this.game.registry.set('sleepSystem', this.sleepSystem);
this.game.registry.set('craftingSystem', this.craftingSystem);
this.game.registry.set('bakerySystem', this.bakerySystem);
this.game.registry.set('barberSystem', this.barberSystem);
this.game.registry.set('lawyerSystem', this.lawyerSystem);
this.game.registry.set('zombieMinerSystem', this.zombieMinerSystem);
this.game.registry.set('townGrowthSystem', this.townGrowthSystem);
this.game.registry.set('npcPrivacySystem', this.npcPrivacySystem);
console.log(' ✓ All systems registered to game registry');
}
/**
* Set up cross-system event listeners
*/
setupEventListeners() {
// TOWN GROWTH → SERVICES
this.game.events.on('serviceUnlocked', (data) => {
this.onServiceUnlocked(data);
});
// MARRIAGE → LAWYER AUTO-UNLOCK
this.game.events.on('marriageComplete', () => {
this.lawyerSystem.checkAutoUnlock();
});
// RELATIONSHIP CHANGE → LAWYER AUTO-UNLOCK
this.game.events.on('relationshipChanged', (data) => {
if (data.hearts <= 3) {
this.lawyerSystem.checkAutoUnlock();
}
});
// BUILDING UNLOCKED → TOWN GROWTH
this.game.events.on('buildingUnlocked', (data) => {
this.townGrowthSystem.checkPopulationUnlocks();
});
// ZOMBIE HIRED → TOWN GROWTH CHECK
this.game.events.on('zombieWorkerHired', () => {
this.townGrowthSystem.checkPopulationUnlocks();
});
// SLEEP → ZOMBIE LOYALTY DECAY PAUSE
this.game.events.on('sleepStarted', () => {
this.pauseZombieLoyaltyDecay = true;
});
this.game.events.on('wakeUp', () => {
this.pauseZombieLoyaltyDecay = false;
});
console.log(' ✓ Cross-system event listeners configured');
}
/**
* Handle service unlock
*/
onServiceUnlocked(data) {
const { serviceId, population } = data;
console.log(`🏛️ Service unlocked: ${serviceId} at pop ${population}`);
// Trigger service-specific initialization
switch (serviceId) {
case 'market':
this.initializeMarket();
break;
case 'hospital':
this.initializeHospital();
break;
case 'school':
this.initializeSchool();
break;
case 'bank':
this.initializeBank();
break;
case 'museum':
this.initializeMuseum();
break;
case 'theater':
this.initializeTheater();
break;
}
}
/**
* Service initializers (placeholders for future implementation)
*/
initializeMarket() {
console.log(' → Market initialized');
// TODO: Implement market system
}
initializeHospital() {
console.log(' → Hospital initialized');
// TODO: Implement hospital system
}
initializeSchool() {
console.log(' → School initialized');
// TODO: Implement school system
}
initializeBank() {
console.log(' → Bank initialized');
// TODO: Implement bank system
}
initializeMuseum() {
console.log(' → Museum initialized');
// TODO: Implement museum system
}
initializeTheater() {
console.log(' → Theater initialized');
// TODO: Implement theater system
}
/**
* Update all systems (called every frame)
*/
update(time, delta) {
const deltaSeconds = delta / 1000;
// Update systems that need per-frame updates
this.sleepSystem.update(deltaSeconds);
this.craftingSystem.update(deltaSeconds);
// Update zombie miners (if not paused by sleep)
if (!this.pauseZombieLoyaltyDecay) {
this.zombieMinerSystem.update(deltaSeconds);
}
}
/**
* Hourly update (called when game hour changes)
*/
onHourChange(hour) {
// Update time-sensitive systems
this.bakerySystem.update();
this.townGrowthSystem.update();
// Check for automation collection reminders
if (hour % 4 === 0) { // Every 4 hours
this.checkAutomationReminders();
}
}
/**
* Check automation reminders
*/
checkAutomationReminders() {
// Zombie miner automation
if (this.zombieMinerSystem.automationActive) {
const hours = this.zombieMinerSystem.getHoursSinceLastCollection();
if (hours >= 8) {
this.game.showNotification({
title: '⛏️ Automation Ready',
text: `${hours.toFixed(0)}h of mining ready to collect!`,
icon: '⛏️'
});
}
}
}
/**
* Daily update (called at midnight)
*/
onDayChange(day) {
console.log(`📅 Day ${day} - Running daily system updates...`);
// Town growth check
this.townGrowthSystem.update();
// Restock shops
this.bakerySystem.restockInventory();
// Birthday cake deliveries
this.bakerySystem.checkBirthdayCakeDeliveries();
}
/**
* Save all systems state
*/
saveAllSystems() {
return {
version: '1.0',
timestamp: Date.now(),
systems: {
sleep: {
playerBed: this.sleepSystem.playerBed,
unlockedBeds: Object.entries(this.sleepSystem.bedTypes)
.filter(([_, bed]) => bed.unlocked)
.map(([key, _]) => key)
},
crafting: {
currentTable: this.craftingSystem.currentTable.id,
unlockedRecipes: this.craftingSystem.unlockedRecipes,
largeTableUnlocked: this.craftingSystem.tables.LARGE.unlocked
},
bakery: {
isUnlocked: this.bakerySystem.isUnlocked,
inventory: this.bakerySystem.inventory,
birthdayOrders: this.bakerySystem.birthdayCakeOrders
},
barber: {
isUnlocked: this.barberSystem.isUnlocked,
playerAppearance: this.barberSystem.playerAppearance,
savedLooks: this.barberSystem.savedLooks,
visitCount: this.barberSystem.visitCount
},
lawyer: {
isUnlocked: this.lawyerSystem.isUnlocked,
hasPrenup: this.lawyerSystem.hasPrenup,
divorceHistory: this.lawyerSystem.divorceHistory,
counselingInProgress: this.lawyerSystem.counselingInProgress
},
zombieMiners: {
miners: this.zombieMinerSystem.zombieMiners,
equipment: this.zombieMinerSystem.zombieEquipment,
lastCollectionTime: this.zombieMinerSystem.lastCollectionTime
},
townGrowth: {
population: this.townGrowthSystem.population,
populationSlots: this.townGrowthSystem.populationSlots,
villages: this.townGrowthSystem.villages,
services: this.townGrowthSystem.services
},
npcPrivacy: {
npcHomes: this.npcPrivacySystem.npcHomes,
visitHistory: this.npcPrivacySystem.visitHistory,
lastVisitTimes: this.npcPrivacySystem.lastVisitTimes
}
}
};
}
/**
* Load all systems state
*/
loadAllSystems(saveData) {
if (!saveData || !saveData.systems) {
console.warn('No save data to load');
return false;
}
try {
const systems = saveData.systems;
// Load sleep system
if (systems.sleep) {
systems.sleep.unlockedBeds.forEach(bedKey => {
this.sleepSystem.bedTypes[bedKey].unlocked = true;
});
}
// Load crafting system
if (systems.crafting) {
this.craftingSystem.tables.LARGE.unlocked = systems.crafting.largeTableUnlocked;
this.craftingSystem.unlockedRecipes = systems.crafting.unlockedRecipes || [];
}
// Load bakery
if (systems.bakery) {
this.bakerySystem.isUnlocked = systems.bakery.isUnlocked;
this.bakerySystem.birthdayCakeOrders = systems.bakery.birthdayOrders || [];
}
// Load barber
if (systems.barber) {
this.barberSystem.isUnlocked = systems.barber.isUnlocked;
this.barberSystem.playerAppearance = systems.barber.playerAppearance;
this.barberSystem.savedLooks = systems.barber.savedLooks || [];
this.barberSystem.visitCount = systems.barber.visitCount || 0;
}
// Load lawyer
if (systems.lawyer) {
this.lawyerSystem.isUnlocked = systems.lawyer.isUnlocked;
this.lawyerSystem.hasPrenup = systems.lawyer.hasPrenup || false;
this.lawyerSystem.divorceHistory = systems.lawyer.divorceHistory || [];
this.lawyerSystem.counselingInProgress = systems.lawyer.counselingInProgress || false;
}
// Load zombie miners
if (systems.zombieMiners) {
this.zombieMinerSystem.zombieMiners = systems.zombieMiners.miners || [];
this.zombieMinerSystem.zombieEquipment = systems.zombieMiners.equipment || {};
this.zombieMinerSystem.lastCollectionTime = systems.zombieMiners.lastCollectionTime;
this.zombieMinerSystem.updateAutomationYield();
}
// Load town growth
if (systems.townGrowth) {
this.townGrowthSystem.population = systems.townGrowth.population;
this.townGrowthSystem.populationSlots = systems.townGrowth.populationSlots;
this.townGrowthSystem.villages = systems.townGrowth.villages || [];
this.townGrowthSystem.services = systems.townGrowth.services || {};
}
// Load NPC privacy
if (systems.npcPrivacy) {
this.npcPrivacySystem.npcHomes = systems.npcPrivacy.npcHomes || {};
this.npcPrivacySystem.visitHistory = systems.npcPrivacy.visitHistory || {};
this.npcPrivacySystem.lastVisitTimes = systems.npcPrivacy.lastVisitTimes || {};
}
console.log('✅ All systems loaded from save data');
return true;
} catch (error) {
console.error('❌ Error loading systems:', error);
return false;
}
}
/**
* Get all systems status (for debug/admin panel)
*/
getAllSystemsStatus() {
return {
sleep: {
active: true,
currentBed: this.sleepSystem.playerBed.name,
isSleeping: this.sleepSystem.isSleeping
},
crafting: {
active: true,
currentTable: this.craftingSystem.currentTable.name,
isCrafting: this.craftingSystem.isCrafting,
queueLength: this.craftingSystem.craftingQueue.length
},
bakery: {
active: this.bakerySystem.isUnlocked,
isOpen: this.bakerySystem.isOpen,
stockLevel: Object.values(this.bakerySystem.inventory)
.reduce((sum, item) => sum + item.stock, 0)
},
barber: {
active: this.barberSystem.isUnlocked,
isOpen: this.barberSystem.isOpen,
currentStyle: this.barberSystem.playerAppearance.hairstyle
},
lawyer: {
active: this.lawyerSystem.isUnlocked,
counselingActive: this.lawyerSystem.counselingInProgress,
hasPrenup: this.lawyerSystem.hasPrenup
},
zombieMiners: {
active: this.zombieMinerSystem.automationActive,
minerCount: this.zombieMinerSystem.zombieMiners.length,
yieldPerHour: this.zombieMinerSystem.totalYieldPerHour
},
townGrowth: {
active: true,
population: this.townGrowthSystem.population,
maxPopulation: this.townGrowthSystem.maxPopulation,
status: this.townGrowthSystem.getTownStatus()
},
npcPrivacy: {
active: true,
homesGenerated: Object.keys(this.npcPrivacySystem.npcHomes).length
}
};
}
}