LifeSimulator/js/config.js

127 lines
3.8 KiB
JavaScript

/**
* Configuration & Settings Management
* Handles default values, slider bounds, custom defaults, and localStorage persistence.
*/
export const FACTORY_DEFAULTS = {
// Starting entity counts & limits
initialSheep: 25,
initialWolves: 3,
initialPlants: 35,
maxPlantCap: 90, // Hard cap to keep CPU lightweight and meadow balanced
// Sheep behavioral attributes
sheepHungerDepletionRate: 1.2, // per second (sheep graze frequently)
sheepGrazingReach: 18, // radius in pixels to snap up plants
sheepMatingCooldown: 22, // seconds between sheep births
// Wolf behavioral attributes & combat exertion
wolfLungeCost: 7, // Health expended per attack bite (fatigue/struggle)
wolfHungerDepletionRate: 1.3, // per second
wolfAttackDamage: 38, // damage per bite to sheep
wolfMatingCooldown: 35, // seconds between wolf litters
wolfMatingThreshold: 86, // minimum hunger required to seek mate
// Plant & flora dynamics
plantSeedRate: 8, // % chance for clustered mature plants to disperse seed
plantDryRate: 2.2, // moisture loss per second in clear weather
rainFrequency: 45, // 0 - 100%
decaySpeed: 1.0, // 0.2x to 3.0x multiplier on carcass decomposition
// Movement speeds (preset balance)
sheepMaxSpeed: 1.8,
sheepFleeSpeed: 2.8,
sheepPerceptionRadius: 160,
wolfMaxSpeed: 2.2,
wolfChaseSpeed: 4.1,
wolfPerceptionRadius: 280,
wolfAttackCooldown: 0.65,
// World constraints
worldWidth: 1280,
worldHeight: 760,
boundaryMargin: 40,
// Continuous Mode (Screen Saver / Endless Ecosystem)
continuousMode: false,
continuousSheepInterval: 14,
continuousWolfInterval: 32,
continuousMaxGroupSize: 3,
};
const STORAGE_KEY = 'LifeSimulator_Config_v2';
const CUSTOM_DEFAULTS_KEY = 'LifeSimulator_Custom_Defaults_v2';
export class ConfigManager {
constructor() {
this.current = this.load();
}
load() {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
const parsed = JSON.parse(saved);
return { ...FACTORY_DEFAULTS, ...parsed };
}
} catch (e) {
console.warn('Failed to load settings from localStorage:', e);
}
return { ...FACTORY_DEFAULTS };
}
save(newConfig) {
this.current = { ...this.current, ...newConfig };
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current));
} catch (e) {
console.warn('Failed to save settings to localStorage:', e);
}
return this.current;
}
saveAsNewDefaults(config) {
this.current = { ...this.current, ...config };
try {
localStorage.setItem(CUSTOM_DEFAULTS_KEY, JSON.stringify(this.current));
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current));
} catch (e) {
console.warn('Failed to save custom defaults:', e);
}
return this.current;
}
resetToDefaults() {
// Check if user set custom defaults, otherwise use factory defaults
let base = FACTORY_DEFAULTS;
try {
const custom = localStorage.getItem(CUSTOM_DEFAULTS_KEY);
if (custom) {
base = { ...FACTORY_DEFAULTS, ...JSON.parse(custom) };
}
} catch (e) {
console.warn('Failed to read custom defaults:', e);
}
this.current = { ...base };
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current));
} catch (e) {
console.warn('Failed to reset settings:', e);
}
return this.current;
}
resetToFactory() {
this.current = { ...FACTORY_DEFAULTS };
try {
localStorage.removeItem(CUSTOM_DEFAULTS_KEY);
localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current));
} catch (e) {
console.warn('Failed to reset to factory defaults:', e);
}
return this.current;
}
}
export const configManager = new ConfigManager();