385 lines
11 KiB
JavaScript
385 lines
11 KiB
JavaScript
/**
|
|
* SLEEP SYSTEM - Energy Regeneration & Bed Upgrades
|
|
* Part of: Home Upgrade & Customization System
|
|
* Created: January 4, 2026
|
|
*
|
|
* Features:
|
|
* - 3-tier bed system (sleeping bag → wooden → king-size)
|
|
* - Energy regeneration based on bed quality
|
|
* - Time skip mechanics (8 hours sleep)
|
|
* - Partner bonuses for married players
|
|
* - Dream sequences and nightmares
|
|
*/
|
|
|
|
class SleepSystem {
|
|
constructor(game) {
|
|
this.game = game;
|
|
this.player = game.player;
|
|
this.isSleeping = false;
|
|
this.currentBed = null;
|
|
|
|
// Bed types configuration
|
|
this.bedTypes = {
|
|
SLEEPING_BAG: {
|
|
id: 'sleeping_bag',
|
|
name: 'Sleeping Bag',
|
|
cost: 0,
|
|
unlocked: true,
|
|
energyRegen: 50, // Restores 50% energy
|
|
sleepDuration: 8, // hours
|
|
dreamChance: 0, // No dreams
|
|
nightmareChance: 0.1, // 10% nightmare chance
|
|
partnerBonus: false,
|
|
sprite: 'interior_bed_sleepingbag.png',
|
|
description: 'A basic sleeping bag. Uncomfortable but functional.'
|
|
},
|
|
WOODEN_BED: {
|
|
id: 'wooden_bed',
|
|
name: 'Wooden Bed',
|
|
cost: 2000,
|
|
requirements: {
|
|
farmhouseLevel: 1
|
|
},
|
|
unlocked: false,
|
|
energyRegen: 90, // Restores 90% energy
|
|
sleepDuration: 8,
|
|
dreamChance: 0.2, // 20% dream chance
|
|
nightmareChance: 0.05, // 5% nightmare chance
|
|
partnerBonus: false,
|
|
sprite: 'interior_bed_wooden.png',
|
|
description: 'A comfortable wooden bed. Much better than the floor!'
|
|
},
|
|
KING_SIZE_BED: {
|
|
id: 'king_size',
|
|
name: 'King-size Bed',
|
|
cost: 10000,
|
|
requirements: {
|
|
farmhouseLevel: 2,
|
|
married: true
|
|
},
|
|
unlocked: false,
|
|
energyRegen: 100, // Restores 100% energy
|
|
sleepDuration: 8,
|
|
dreamChance: 0.3, // 30% dream chance
|
|
nightmareChance: 0, // No nightmares!
|
|
partnerBonus: true, // +50 relationship points
|
|
spousePresent: false,
|
|
sprite: 'interior_bed_kingsize.png',
|
|
description: 'A luxurious king-size bed. Perfect for two!'
|
|
}
|
|
};
|
|
|
|
// Current player's bed (starts with sleeping bag)
|
|
this.playerBed = { ...this.bedTypes.SLEEPING_BAG };
|
|
|
|
// Sleep state
|
|
this.sleepStartTime = null;
|
|
this.sleepEndTime = null;
|
|
this.dreamSequence = null;
|
|
}
|
|
|
|
/**
|
|
* Check if player can use a specific bed type
|
|
*/
|
|
canUseBed(bedType) {
|
|
const bed = this.bedTypes[bedType];
|
|
|
|
// Check if unlocked
|
|
if (!bed.unlocked && bedType !== 'SLEEPING_BAG') {
|
|
return { canUse: false, reason: 'Bed not purchased yet' };
|
|
}
|
|
|
|
// Check requirements
|
|
if (bed.requirements) {
|
|
if (bed.requirements.farmhouseLevel &&
|
|
this.player.farmhouseLevel < bed.requirements.farmhouseLevel) {
|
|
return {
|
|
canUse: false,
|
|
reason: `Requires Farmhouse Level ${bed.requirements.farmhouseLevel}`
|
|
};
|
|
}
|
|
|
|
if (bed.requirements.married && !this.player.isMarried) {
|
|
return {
|
|
canUse: false,
|
|
reason: 'Requires marriage'
|
|
};
|
|
}
|
|
}
|
|
|
|
return { canUse: true };
|
|
}
|
|
|
|
/**
|
|
* Purchase a bed upgrade
|
|
*/
|
|
purchaseBed(bedType) {
|
|
const bed = this.bedTypes[bedType];
|
|
|
|
// Check if can purchase
|
|
if (bed.unlocked) {
|
|
return { success: false, message: 'You already own this bed!' };
|
|
}
|
|
|
|
// Check cost
|
|
if (this.player.money < bed.cost) {
|
|
return {
|
|
success: false,
|
|
message: `Not enough money! Need ${bed.cost}g`
|
|
};
|
|
}
|
|
|
|
// Check requirements
|
|
const canUse = this.canUseBed(bedType);
|
|
if (!canUse.canUse) {
|
|
return { success: false, message: canUse.reason };
|
|
}
|
|
|
|
// Purchase bed
|
|
this.player.money -= bed.cost;
|
|
bed.unlocked = true;
|
|
this.playerBed = { ...bed };
|
|
|
|
// Trigger furniture placement
|
|
this.game.emit('bedPurchased', {
|
|
bedType: bedType,
|
|
bed: bed
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
message: `Purchased ${bed.name} for ${bed.cost}g!`
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initiate sleep sequence
|
|
*/
|
|
sleep() {
|
|
// Check if already sleeping
|
|
if (this.isSleeping) {
|
|
return { success: false, message: 'Already sleeping!' };
|
|
}
|
|
|
|
// Check if tired enough (energy < 50%)
|
|
if (this.player.energy > this.player.maxEnergy * 0.5) {
|
|
return {
|
|
success: false,
|
|
message: "You're not tired enough to sleep yet."
|
|
};
|
|
}
|
|
|
|
// Start sleep
|
|
this.isSleeping = true;
|
|
this.sleepStartTime = this.game.time.currentTime;
|
|
this.sleepEndTime = this.game.time.currentTime + (this.playerBed.sleepDuration * 3600); // Convert to seconds
|
|
|
|
// Roll for dream/nightmare
|
|
this.dreamSequence = this.rollForDream();
|
|
|
|
// Trigger sleep animation
|
|
this.game.emit('sleepStarted', {
|
|
bed: this.playerBed,
|
|
duration: this.playerBed.sleepDuration,
|
|
dreamSequence: this.dreamSequence
|
|
});
|
|
|
|
// Fast-forward time
|
|
this.game.time.skipTime(this.playerBed.sleepDuration);
|
|
|
|
// Wake up after duration
|
|
setTimeout(() => {
|
|
this.wakeUp();
|
|
}, 100); // Instant wake-up after time skip
|
|
|
|
return { success: true };
|
|
}
|
|
|
|
/**
|
|
* Roll for dream or nightmare
|
|
*/
|
|
rollForDream() {
|
|
const rand = Math.random();
|
|
|
|
// Check nightmare first
|
|
if (rand < this.playerBed.nightmareChance) {
|
|
return {
|
|
type: 'nightmare',
|
|
sequence: this.getRandomNightmare()
|
|
};
|
|
}
|
|
|
|
// Check dream
|
|
if (rand < this.playerBed.dreamChance + this.playerBed.nightmareChance) {
|
|
return {
|
|
type: 'dream',
|
|
sequence: this.getRandomDream()
|
|
};
|
|
}
|
|
|
|
return null; // No dream
|
|
}
|
|
|
|
/**
|
|
* Get random dream sequence
|
|
*/
|
|
getRandomDream() {
|
|
const dreams = [
|
|
{
|
|
id: 'memory_ana',
|
|
title: 'Memory of Ana',
|
|
description: 'You dream of Ana, smiling in the sunlight...',
|
|
effect: { mood: +10 }
|
|
},
|
|
{
|
|
id: 'farming_success',
|
|
title: 'Bountiful Harvest',
|
|
description: 'You dream of your crops growing tall and strong.',
|
|
effect: { farming_xp: 50 }
|
|
},
|
|
{
|
|
id: 'zombie_peace',
|
|
title: 'Peaceful Workers',
|
|
description: 'Your zombie workers are happy and productive.',
|
|
effect: { loyalty: +5 }
|
|
}
|
|
];
|
|
|
|
return dreams[Math.floor(Math.random() * dreams.length)];
|
|
}
|
|
|
|
/**
|
|
* Get random nightmare sequence
|
|
*/
|
|
getRandomNightmare() {
|
|
const nightmares = [
|
|
{
|
|
id: 'ana_loss',
|
|
title: 'The Loss',
|
|
description: 'Fragments of that terrible day flash before you...',
|
|
effect: { mood: -20 }
|
|
},
|
|
{
|
|
id: 'zombie_attack',
|
|
title: 'Undead Uprising',
|
|
description: 'Your workers turn hostile, advancing slowly...',
|
|
effect: { energy: -10 }
|
|
},
|
|
{
|
|
id: 'crop_failure',
|
|
title: 'Withered Fields',
|
|
description: 'Your entire farm crumbles to dust.',
|
|
effect: { mood: -10 }
|
|
}
|
|
];
|
|
|
|
return nightmares[Math.floor(Math.random() * nightmares.length)];
|
|
}
|
|
|
|
/**
|
|
* Wake up from sleep
|
|
*/
|
|
wakeUp() {
|
|
if (!this.isSleeping) return;
|
|
|
|
// Calculate energy restoration
|
|
const energyRestored = (this.player.maxEnergy * this.playerBed.energyRegen) / 100;
|
|
this.player.energy = Math.min(
|
|
this.player.maxEnergy,
|
|
this.player.energy + energyRestored
|
|
);
|
|
|
|
// Partner bonus (if married & king-size bed)
|
|
if (this.playerBed.partnerBonus && this.player.isMarried) {
|
|
const spouse = this.game.npcs.getSpouse();
|
|
if (spouse) {
|
|
spouse.addRelationshipPoints(50);
|
|
this.game.showMessage(`${spouse.name} cuddles closer. +50 ❤️`);
|
|
}
|
|
}
|
|
|
|
// Apply dream/nightmare effects
|
|
if (this.dreamSequence) {
|
|
this.applyDreamEffects(this.dreamSequence);
|
|
}
|
|
|
|
// Update state
|
|
this.isSleeping = false;
|
|
this.currentBed = null;
|
|
this.dreamSequence = null;
|
|
|
|
// Trigger wake-up event
|
|
this.game.emit('wakeUp', {
|
|
energyRestored: energyRestored,
|
|
newEnergy: this.player.energy,
|
|
time: this.game.time.currentTime
|
|
});
|
|
|
|
// New day announcements
|
|
this.game.showMessage(`Good morning! Energy restored: ${Math.floor(energyRestored)}`);
|
|
}
|
|
|
|
/**
|
|
* Apply dream/nightmare effects
|
|
*/
|
|
applyDreamEffects(dreamSequence) {
|
|
const sequence = dreamSequence.sequence;
|
|
|
|
// Show dream/nightmare message
|
|
const typeIcon = dreamSequence.type === 'dream' ? '✨' : '💀';
|
|
this.game.showMessage(`${typeIcon} ${sequence.title}: ${sequence.description}`);
|
|
|
|
// Apply effects
|
|
if (sequence.effect.mood) {
|
|
this.player.mood += sequence.effect.mood;
|
|
}
|
|
if (sequence.effect.energy) {
|
|
this.player.energy += sequence.effect.energy;
|
|
}
|
|
if (sequence.effect.farming_xp) {
|
|
this.player.addXP('farming', sequence.effect.farming_xp);
|
|
}
|
|
if (sequence.effect.loyalty && this.game.zombieWorkers) {
|
|
this.game.zombieWorkers.addGlobalLoyalty(sequence.effect.loyalty);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if it's a good time to sleep
|
|
*/
|
|
canSleepNow() {
|
|
const hour = this.game.time.getHour();
|
|
|
|
// Can sleep between 8 PM (20:00) and 2 AM (02:00)
|
|
if ((hour >= 20 && hour <= 23) || (hour >= 0 && hour <= 2)) {
|
|
return { canSleep: true };
|
|
}
|
|
|
|
return {
|
|
canSleep: false,
|
|
message: "It's not nighttime yet. Sleep between 8 PM - 2 AM."
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get current bed info for UI
|
|
*/
|
|
getCurrentBedInfo() {
|
|
return {
|
|
...this.playerBed,
|
|
isSleeping: this.isSleeping,
|
|
canSleep: this.canSleepNow().canSleep
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Update (called every frame)
|
|
*/
|
|
update(deltaTime) {
|
|
// Sleep system update logic (if needed)
|
|
// Currently handled by events and timers
|
|
}
|
|
}
|
|
|
|
|