/** * Daily Routine System for Villager AI (Simplified Version) * * This implementation manages villager daily routines including work, rest, and social interactions. * Uses simple arrays for positions instead of THREE.Vector3 to avoid import issues. */ class DailyRoutineManager { constructor() { this.schedules = new Map(); // Map of villager IDs to schedules this.currentTime = 0; // In-game time in hours (0-24) } /** * Set a schedule for a villager * @param {string} villagerId - Villager identifier * @param {Array} schedule - Array of schedule entries */ setSchedule(villagerId, schedule) { this.schedules.set(villagerId, schedule); } /** * Update the routine manager * @param {number} deltaTime - Time since last update in hours */ update(deltaTime) { this.currentTime += deltaTime; if (this.currentTime >= 24) { this.currentTime -= 24; // Wrap around to next day } } /** * Get current activity for a villager * @param {string} villagerId - Villager identifier * @returns {Object} Current activity */ getCurrentActivity(villagerId) { const schedule = this.schedules.get(villagerId); if (!schedule) return null; // Find the current activity based on time for (let i = schedule.length - 1; i >= 0; i--) { if (this.currentTime >= schedule[i].startTime) { return schedule[i]; } } // If no activity found, return the last one (for times before first activity) return schedule[schedule.length - 1]; } /** * Create a default schedule for a villager * @param {string} villagerId - Villager identifier * @param {Array} workLocation - Work location [x, y, z] * @param {Array} homeLocation - Home location [x, y, z] * @param {Array} socialLocations - Social locations [[x, y, z], ...] */ createDefaultSchedule(villagerId, workLocation, homeLocation, socialLocations) { const schedule = [ { startTime: 0, activity: 'sleep', location: homeLocation }, { startTime: 7, activity: 'eat', location: homeLocation }, { startTime: 8, activity: 'work', location: workLocation }, { startTime: 12, activity: 'eat', location: workLocation }, { startTime: 13, activity: 'work', location: workLocation }, { startTime: 17, activity: 'socialize', location: socialLocations[0] }, { startTime: 19, activity: 'eat', location: homeLocation }, { startTime: 20, activity: 'sleep', location: homeLocation } ]; this.setSchedule(villagerId, schedule); } } /** * Villager class with routine-based behavior (Simplified Version) */ class Villager { constructor(id, position) { this.id = id; this.position = position; // [x, y, z] array this.velocity = [0, 0, 0]; // [x, y, z] array this.maxSpeed = 2; this.energy = 100; this.hunger = 0; this.socialNeed = 0; this.state = 'idle'; // idle, working, sleeping, eating, socializing this.path = []; this.avoidanceRadius = 2; this.avoidanceWeight = 1.5; this.steeringWeight = 1.0; } /** * Update villager state * @param {DailyRoutineManager} routineManager - Routine manager * @param {VillagePathfinder} pathfinder - Pathfinding system * @param {number} deltaTime - Time since last update */ update(routineManager, pathfinder, deltaTime) { // Update needs this.updateNeeds(deltaTime); // Get current activity const activity = routineManager.getCurrentActivity(this.id); // Update state based on activity if (activity) { this.state = activity.activity; // If we have a location for this activity, pathfind to it if (activity.location && this.distanceTo(activity.location) > 1) { this.path = pathfinder.findPath(this.position, activity.location); } else { this.path = []; } } // Perform state-specific actions switch (this.state) { case 'sleep': this.sleep(deltaTime); break; case 'work': this.work(deltaTime); break; case 'eat': this.eat(deltaTime); break; case 'socialize': this.socialize(deltaTime); break; } } /** * Calculate distance to another position * @param {Array} other - Other position [x, y, z] * @returns {number} Distance */ distanceTo(other) { const dx = this.position[0] - other[0]; const dy = this.position[1] - other[1]; const dz = this.position[2] - other[2]; return Math.sqrt(dx * dx + dy * dy + dz * dz); } /** * Update villager needs over time * @param {number} deltaTime - Time since last update */ updateNeeds(deltaTime) { this.energy = Math.max(0, this.energy - 0.1 * deltaTime); this.hunger = Math.min(100, this.hunger + 0.05 * deltaTime); this.socialNeed = Math.min(100, this.socialNeed + 0.03 * deltaTime); } /** * Check if villager is tired * @returns {boolean} True if tired */ isTired() { return this.energy < 20; } /** * Check if villager should work * @returns {boolean} True if should work */ shouldWork() { return this.energy > 30 && this.hunger < 80; } /** * Check if villager should socialize * @returns {boolean} True if should socialize */ shouldSocialize() { return this.energy > 40 && this.socialNeed > 50; } /** * Sleep action * @param {number} deltaTime - Time since last update */ sleep(deltaTime) { this.energy = Math.min(100, this.energy + 0.5 * deltaTime); } /** * Work action * @param {number} deltaTime - Time since last update */ work(deltaTime) { this.energy = Math.max(0, this.energy - 0.2 * deltaTime); } /** * Eat action * @param {number} deltaTime - Time since last update */ eat(deltaTime) { this.hunger = Math.max(0, this.hunger - 0.8 * deltaTime); } /** * Socialize action * @param {number} deltaTime - Time since last update */ socialize(deltaTime) { this.socialNeed = Math.max(0, this.socialNeed - 0.6 * deltaTime); } /** * Idle action */ idle() { // Do nothing } } export { DailyRoutineManager, Villager };