ok
This commit is contained in:
431
EMERGENCY_SYSTEMS_RECOVERY/WeatherSystem.js
Normal file
431
EMERGENCY_SYSTEMS_RECOVERY/WeatherSystem.js
Normal file
@@ -0,0 +1,431 @@
|
||||
class WeatherSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// --- Time Configuration ---
|
||||
this.fullDaySeconds = 300; // 5 minutes = 24 game hours
|
||||
this.gameTime = 8; // Start at 8:00
|
||||
this.dayCount = 1;
|
||||
|
||||
// --- Weather Configuration ---
|
||||
this.currentWeather = 'clear';
|
||||
this.weatherDuration = 0;
|
||||
this.maxWeatherDuration = 10000; // Random duration logic handles this
|
||||
this.rainEmitter = null; // Replaced manual Array with Emitter
|
||||
|
||||
// --- SEASONS Configuration ---
|
||||
this.seasons = ['spring', 'summer', 'autumn', 'winter']; // Pomlad, Poletje, Jesen, Zima
|
||||
this.currentSeason = 'spring';
|
||||
this.daysPerSeason = 7; // Vsak letni čas traja 7 dni
|
||||
|
||||
// --- TEMPERATURE System ---
|
||||
this.baseTemp = 20; // Celsius
|
||||
this.currentTemp = 20;
|
||||
this.tempCheckTimer = 0;
|
||||
this.tempDamageInterval = 5000; // Damage every 5 seconds
|
||||
|
||||
// --- State ---
|
||||
this.currentPhase = 'day';
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Start weather cycle
|
||||
this.changeWeather();
|
||||
}
|
||||
|
||||
getOverlay() {
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (uiScene && uiScene.overlayGraphics) {
|
||||
return uiScene.overlayGraphics;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
// 1. Update Time
|
||||
this.updateTime(delta);
|
||||
|
||||
// 2. Update Weather Logic (Durations, Changes)
|
||||
this.updateWeatherLogic(delta);
|
||||
|
||||
// 2.5. Update Temperature System
|
||||
this.updateTemperature(delta);
|
||||
|
||||
// 3. Update Physics (Rain drops)
|
||||
this.updateWeatherPhysics(delta);
|
||||
|
||||
// 4. Render Atmosphere (Time + Weather)
|
||||
this.render();
|
||||
}
|
||||
|
||||
updateTime(delta) {
|
||||
const seconds = delta / 1000;
|
||||
const gameHoursPerRealSecond = 24 / this.fullDaySeconds;
|
||||
|
||||
this.gameTime += seconds * gameHoursPerRealSecond;
|
||||
|
||||
if (this.gameTime >= 24) {
|
||||
this.gameTime -= 24;
|
||||
this.dayCount++;
|
||||
console.log(`🌞 Day ${this.dayCount} started!`);
|
||||
|
||||
// Check for Season Change
|
||||
this.checkSeasonChange();
|
||||
|
||||
// DEMO MODE: DISABLED - unlimited play
|
||||
/*
|
||||
if (this.dayCount > 3) {
|
||||
this.triggerDemoEnd();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Update Phase
|
||||
const phase = this.getPhase(this.gameTime);
|
||||
if (phase !== this.currentPhase) {
|
||||
this.currentPhase = phase;
|
||||
console.log(`🌅 Time of Day: ${phase} (${Math.floor(this.gameTime)}:00)`);
|
||||
|
||||
// Trigger Bat Swarm at Dusk
|
||||
if (phase === 'dusk' && this.scene.worldEventSystem) {
|
||||
this.scene.worldEventSystem.spawnBatSwarm();
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger Night Owl at Midnight (00:00)
|
||||
// We check if seconds crossed 0.
|
||||
if (Math.abs(this.gameTime - 0.0) < 0.05) {
|
||||
// Only trigger once per night - check active flag or similar?
|
||||
// Actually, gameTime will pass 0 very quickly but maybe multiple frames.
|
||||
// We can use a flag resetting at day.
|
||||
if (!this.owlTriggered && this.scene.worldEventSystem) {
|
||||
this.scene.worldEventSystem.spawnNightOwl();
|
||||
this.owlTriggered = true;
|
||||
}
|
||||
}
|
||||
if (this.gameTime > 5) this.owlTriggered = false; // Reset flag at dawn
|
||||
|
||||
// Update UI Clock
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (uiScene && uiScene.clockText) {
|
||||
const hours = Math.floor(this.gameTime);
|
||||
const minutes = Math.floor((this.gameTime - hours) * 60);
|
||||
const timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
||||
const seasonIcons = { spring: '🌸', summer: '☀️', autumn: '🍂', winter: '❄️' };
|
||||
const seasonIcon = seasonIcons[this.currentSeason] || '';
|
||||
uiScene.clockText.setText(`${seasonIcon} Day ${this.dayCount} - ${timeString}`);
|
||||
}
|
||||
}
|
||||
|
||||
getPhase(hour) {
|
||||
if (hour >= 5 && hour < 7) return 'dawn';
|
||||
if (hour >= 7 && hour < 18) return 'day';
|
||||
if (hour >= 18 && hour < 20) return 'dusk';
|
||||
return 'night';
|
||||
}
|
||||
|
||||
updateWeatherLogic(delta) {
|
||||
this.weatherDuration += delta;
|
||||
if (this.weatherDuration > this.maxWeatherDuration) {
|
||||
this.changeWeather();
|
||||
}
|
||||
}
|
||||
|
||||
updateWeatherPhysics(delta) {
|
||||
// Optimisation: Physics now handled by Phaser Particles
|
||||
}
|
||||
|
||||
render() {
|
||||
const overlay = this.getOverlay();
|
||||
if (!overlay) return;
|
||||
|
||||
// IMPORTANT: Clear previous frame to avoid buildup
|
||||
overlay.clear();
|
||||
|
||||
const width = this.scene.scale.width;
|
||||
const height = this.scene.scale.height;
|
||||
|
||||
// --- LAYER 1: Day/Night Cycle ---
|
||||
this.renderDayNight(overlay, width, height);
|
||||
|
||||
// --- LAYER 2: Weather Effects (Fog, Rain darkness) ---
|
||||
this.renderWeatherEffects(overlay, width, height);
|
||||
|
||||
// --- LAYER 3: Season Tint ---
|
||||
this.renderSeasonOverlay(overlay, width, height);
|
||||
}
|
||||
|
||||
renderDayNight(overlay, width, height) {
|
||||
const hour = this.gameTime;
|
||||
|
||||
let color = 0x000033; // Default night
|
||||
let alpha = 0;
|
||||
|
||||
if (hour >= 0 && hour < 5) { // Deep Night
|
||||
color = 0x000033; alpha = 0.6;
|
||||
} else if (hour >= 5 && hour < 7) { // Dawn
|
||||
color = 0xFF6B35;
|
||||
const progress = (hour - 5) / 2;
|
||||
alpha = 0.6 - (progress * 0.6);
|
||||
} else if (hour >= 7 && hour < 18) { // Day
|
||||
alpha = 0;
|
||||
} else if (hour >= 18 && hour < 20) { // Dusk
|
||||
color = 0x8B4789;
|
||||
const progress = (hour - 18) / 2;
|
||||
alpha = progress * 0.5;
|
||||
} else if (hour >= 20 && hour < 24) { // Night
|
||||
color = 0x000033;
|
||||
const progress = (hour - 20) / 4;
|
||||
alpha = 0.5 + (progress * 0.1);
|
||||
}
|
||||
|
||||
if (alpha > 0) {
|
||||
overlay.fillStyle(color, alpha);
|
||||
overlay.fillRect(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
renderWeatherEffects(overlay, width, height) {
|
||||
// Fog
|
||||
if (this.currentWeather === 'fog') {
|
||||
overlay.fillStyle(0xcccccc, 0.4);
|
||||
overlay.fillRect(0, 0, width, height);
|
||||
}
|
||||
|
||||
// Rain / Storm
|
||||
if (this.currentWeather === 'rain' || this.currentWeather === 'storm') {
|
||||
const isDark = this.currentWeather === 'storm' ? 0.3 : 0.2;
|
||||
|
||||
// Additive darkness for storm
|
||||
overlay.fillStyle(0x000033, isDark);
|
||||
overlay.fillRect(0, 0, width, height);
|
||||
|
||||
// Rain drops are now particles (separate GameObject)
|
||||
}
|
||||
}
|
||||
|
||||
changeWeather() {
|
||||
this.clearWeather();
|
||||
|
||||
const rand = Math.random();
|
||||
if (rand < 0.6) {
|
||||
this.currentWeather = 'clear';
|
||||
this.maxWeatherDuration = Phaser.Math.Between(10000, 30000);
|
||||
} else if (rand < 0.8) {
|
||||
this.currentWeather = 'rain';
|
||||
this.startRain(false);
|
||||
this.maxWeatherDuration = Phaser.Math.Between(10000, 20000);
|
||||
} else if (rand < 0.9) {
|
||||
this.currentWeather = 'storm';
|
||||
this.startRain(true);
|
||||
this.maxWeatherDuration = Phaser.Math.Between(8000, 15000);
|
||||
} else {
|
||||
this.currentWeather = 'fog';
|
||||
this.maxWeatherDuration = Phaser.Math.Between(10000, 20000);
|
||||
}
|
||||
|
||||
this.weatherDuration = 0;
|
||||
console.log(`Weather changed to: ${this.currentWeather}`);
|
||||
}
|
||||
|
||||
startRain(heavy) {
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (!uiScene) return;
|
||||
|
||||
// Check Settings
|
||||
const quality = this.scene.settings ? this.scene.settings.particles : 'HIGH';
|
||||
if (quality === 'NONE') return;
|
||||
|
||||
// Ensure texture exists
|
||||
if (!this.scene.textures.exists('rain_drop')) {
|
||||
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
||||
graphics.fillStyle(0x88aaff, 1);
|
||||
graphics.fillRect(0, 0, 2, 8);
|
||||
graphics.generateTexture('rain_drop', 2, 8);
|
||||
graphics.destroy();
|
||||
}
|
||||
|
||||
// Clean up old
|
||||
if (this.rainEmitter) {
|
||||
this.rainEmitter.destroy();
|
||||
}
|
||||
|
||||
const width = this.scene.scale.width;
|
||||
|
||||
let pQuantity = heavy ? 5 : 2;
|
||||
let pFreq = heavy ? 10 : 30;
|
||||
|
||||
if (quality === 'LOW') {
|
||||
pQuantity = heavy ? 2 : 1;
|
||||
pFreq = heavy ? 50 : 100;
|
||||
}
|
||||
|
||||
// Use modern particles or fallback
|
||||
// Helper to support both if needed, but standard 3.60+ is:
|
||||
this.rainEmitter = uiScene.add.particles(0, 0, 'rain_drop', {
|
||||
x: { min: 0, max: width },
|
||||
y: -20,
|
||||
quantity: pQuantity,
|
||||
frequency: pFreq, // Emit every X ms
|
||||
lifespan: 1500,
|
||||
speedY: { min: heavy ? 600 : 400, max: heavy ? 900 : 600 },
|
||||
speedX: { min: -50, max: 0 }, // Slight wind
|
||||
scaleY: { min: 1.0, max: 2.0 },
|
||||
alpha: { start: 0.6, end: 0 },
|
||||
emitting: true
|
||||
});
|
||||
|
||||
// Depth just above overlay (-1000)
|
||||
this.rainEmitter.setDepth(-990);
|
||||
|
||||
// Play Sound
|
||||
if (this.scene.soundManager) {
|
||||
this.scene.soundManager.playRainSound();
|
||||
}
|
||||
}
|
||||
|
||||
clearWeather() {
|
||||
if (this.rainEmitter) {
|
||||
this.rainEmitter.destroy();
|
||||
this.rainEmitter = null;
|
||||
}
|
||||
|
||||
// Stop Sound
|
||||
if (this.scene.soundManager) {
|
||||
this.scene.soundManager.stopRainSound();
|
||||
}
|
||||
}
|
||||
|
||||
// --- Getters for Other Systems ---
|
||||
getCurrentHour() {
|
||||
return Math.floor(this.gameTime);
|
||||
}
|
||||
|
||||
getDayCount() {
|
||||
return this.dayCount;
|
||||
}
|
||||
|
||||
isNight() {
|
||||
const hour = this.gameTime;
|
||||
return hour >= 20 || hour < 5;
|
||||
}
|
||||
|
||||
isDay() {
|
||||
const hour = this.gameTime;
|
||||
return hour >= 7 && hour < 18;
|
||||
}
|
||||
|
||||
isHordeNight() {
|
||||
// Every 3rd night is a Horde Night
|
||||
return this.dayCount > 0 && this.dayCount % 3 === 0;
|
||||
}
|
||||
|
||||
checkSeasonChange() {
|
||||
const seasonIndex = Math.floor((this.dayCount - 1) / this.daysPerSeason) % 4;
|
||||
const newSeason = this.seasons[seasonIndex];
|
||||
|
||||
if (newSeason !== this.currentSeason) {
|
||||
this.currentSeason = newSeason;
|
||||
const seasonNames = { spring: '🌸 Pomlad', summer: '☀️ Poletje', autumn: '🍂 Jesen', winter: '❄️ Zima' };
|
||||
console.log(`🌍 Letni čas: ${seasonNames[newSeason]}`);
|
||||
}
|
||||
}
|
||||
|
||||
getSeason() {
|
||||
return this.currentSeason;
|
||||
}
|
||||
|
||||
getSeasonColor() {
|
||||
// Barve/overlay za letne čase
|
||||
const colors = {
|
||||
spring: { color: 0x90EE90, alpha: 0.1 }, // Svetlo zelena
|
||||
summer: { color: 0xFFFF00, alpha: 0.05 }, // Rumena
|
||||
autumn: { color: 0xFF8C00, alpha: 0.15 }, // Oranžna
|
||||
winter: { color: 0xE0F7FF, alpha: 0.25 } // Belo modra
|
||||
};
|
||||
return colors[this.currentSeason] || { color: 0xFFFFFF, alpha: 0 };
|
||||
}
|
||||
|
||||
renderSeasonOverlay(overlay, width, height) {
|
||||
const seasonData = this.getSeasonColor();
|
||||
if (seasonData.alpha > 0) {
|
||||
overlay.fillStyle(seasonData.color, seasonData.alpha);
|
||||
overlay.fillRect(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
updateTemperature(delta) {
|
||||
// Calculate base temperature from season
|
||||
const seasonTemps = {
|
||||
spring: 15,
|
||||
summer: 30,
|
||||
autumn: 10,
|
||||
winter: -5
|
||||
};
|
||||
|
||||
this.baseTemp = seasonTemps[this.currentSeason] || 20;
|
||||
|
||||
// Time of day variation
|
||||
const timeVar = Math.sin((this.gameTime / 24) * Math.PI * 2) * 5;
|
||||
this.currentTemp = this.baseTemp + timeVar;
|
||||
|
||||
// Temperature damage logic
|
||||
this.tempCheckTimer += delta;
|
||||
if (this.tempCheckTimer >= this.tempDamageInterval) {
|
||||
this.tempCheckTimer = 0;
|
||||
this.checkTemperatureDamage();
|
||||
}
|
||||
}
|
||||
|
||||
checkTemperatureDamage() {
|
||||
if (!this.scene.player) return;
|
||||
|
||||
const player = this.scene.player;
|
||||
const inventory = this.scene.inventorySystem;
|
||||
|
||||
// Check for winter coat protection
|
||||
const hasWinterCoat = inventory && inventory.hasItem('winter_coat');
|
||||
const hasSummerHat = inventory && inventory.hasItem('summer_hat');
|
||||
|
||||
// Cold damage (Winter)
|
||||
if (this.currentTemp < 0 && !hasWinterCoat) {
|
||||
player.takeDamage(5);
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: player.sprite.x,
|
||||
y: player.sprite.y - 40,
|
||||
text: '❄️ Freezing!',
|
||||
color: '#88D4FF'
|
||||
});
|
||||
}
|
||||
|
||||
// Heat damage (Summer)
|
||||
if (this.currentTemp > 35 && !hasSummerHat) {
|
||||
player.takeDamage(3);
|
||||
this.scene.events.emit('show-floating-text', {
|
||||
x: player.sprite.x,
|
||||
y: player.sprite.y - 40,
|
||||
text: '🔥 Overheating!',
|
||||
color: '#FF8844'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getTemperature() {
|
||||
return Math.round(this.currentTemp);
|
||||
}
|
||||
|
||||
triggerDemoEnd() {
|
||||
console.log('🎮 DEMO END - 3 Days Completed!');
|
||||
|
||||
// Pause game
|
||||
this.scene.physics.pause();
|
||||
|
||||
// Show demo end screen
|
||||
const uiScene = this.scene.scene.get('UIScene');
|
||||
if (uiScene) {
|
||||
uiScene.showDemoEndScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user