import { ref, computed, onMounted, onUnmounted } from 'vue'; export function usePetSystem() { // --- State --- const stage = ref('egg'); // egg, baby, adult const state = ref('idle'); // idle, sleep, eating, sick, dead, refuse // --- Stats --- const stats = ref({ hunger: 100, // 0-100 (0 = Starving) happiness: 100, // 0-100 (0 = Depressed) health: 100, // 0-100 (0 = Sick risk) weight: 500, // grams age: 0, // days poopCount: 0 // Number of poops on screen }); // --- Internal Timers --- let gameLoopId = null; const TICK_RATE = 3000; // 3 seconds per tick const isCleaning = ref(false); // --- Actions --- function feed() { if (state.value === 'sleep' || state.value === 'dead' || stage.value === 'egg' || isCleaning.value) return false; if (state.value === 'sick' || stats.value.hunger >= 90) { // Refuse food if sick or full triggerState('refuse', 2000); return false; } // Eat triggerState('eating', 3000); // Animation duration stats.value.hunger = Math.min(100, stats.value.hunger + 20); stats.value.weight += 50; // Chance to poop after eating if (Math.random() < 0.3) { setTimeout(() => { if (stats.value.poopCount < 4) { stats.value.poopCount++; } }, 4000); } return true; } function play() { if (state.value !== 'idle' || stage.value === 'egg' || isCleaning.value) return false; stats.value.happiness = Math.min(100, stats.value.happiness + 15); stats.value.weight -= 10; // Exercise burns calories stats.value.hunger = Math.max(0, stats.value.hunger - 5); return true; } function clean() { if (stats.value.poopCount > 0 && !isCleaning.value) { isCleaning.value = true; // Delay removal for animation setTimeout(() => { stats.value.poopCount = 0; stats.value.happiness += 10; isCleaning.value = false; }, 2000); // 2 seconds flush animation return true; } return false; } function sleep() { if (isCleaning.value) return; if (state.value === 'idle') { state.value = 'sleep'; } else if (state.value === 'sleep') { state.value = 'idle'; // Wake up } } // --- Game Loop --- function tick() { if (state.value === 'dead' || stage.value === 'egg') return; // Decrease stats naturally if (state.value !== 'sleep') { stats.value.hunger = Math.max(0, stats.value.hunger - 2); stats.value.happiness = Math.max(0, stats.value.happiness - 1); } else { // Slower decay when sleeping stats.value.hunger = Math.max(0, stats.value.hunger - 0.5); } // Random poop generation (5% chance per tick) if (state.value !== 'sleep' && Math.random() < 0.05 && stats.value.poopCount < 4 && !isCleaning.value) { stats.value.poopCount++; } // Health Logic (Poop hurts health) if (stats.value.poopCount > 0) { stats.value.health = Math.max(0, stats.value.health - (2 * stats.value.poopCount)); } if (stats.value.hunger === 0) { stats.value.health = Math.max(0, stats.value.health - 5); } // Sickness Check if (stats.value.health < 30 && state.value !== 'sick') { if (Math.random() < 0.3) { state.value = 'sick'; } } // Death Check if (stats.value.health === 0) { state.value = 'dead'; } // Evolution / Growth (Simple Age increment) // In a real game, 1 day might be 24h, here maybe every 100 ticks? // For now, let's just say age increases slowly. } // --- Helpers --- function triggerState(tempState, duration) { const previousState = state.value; state.value = tempState; setTimeout(() => { if (state.value === tempState) { // Only revert if state hasn't changed again state.value = previousState === 'sleep' ? 'idle' : 'idle'; } }, duration); } function hatchEgg() { if (stage.value === 'egg') { stage.value = 'baby'; // or 'adult' for now since we only have that sprite // Let's map 'baby' to our 'adult' sprite for now, or just use 'adult' stage.value = 'adult'; state.value = 'idle'; stats.value.hunger = 50; stats.value.happiness = 50; stats.value.health = 100; stats.value.poopCount = 0; isCleaning.value = false; } } function reset() { stage.value = 'egg'; state.value = 'idle'; isCleaning.value = false; stats.value = { hunger: 100, happiness: 100, health: 100, weight: 500, age: 0, poopCount: 0 }; } // --- Lifecycle --- onMounted(() => { gameLoopId = setInterval(tick, TICK_RATE); }); onUnmounted(() => { if (gameLoopId) clearInterval(gameLoopId); }); return { stage, state, stats, isCleaning, feed, play, clean, sleep, hatchEgg, reset }; }