"use client"; import { useState, useEffect, useCallback, useMemo } from "react"; import { Planet, Starship } from "@/types/swapi"; import { fetchGameData } from "@/services/swapi"; import { LogEntry } from "@/components/EventLog"; import { t } from "@/content/locales"; export function useGameEngine() { const [allPlanets, setAllPlanets] = useState([]); const [planets, setPlanets] = useState([]); const [starships, setStarships] = useState([]); const [loading, setLoading] = useState(true); const [gameStarted, setGameStarted] = useState(false); const [isGameOver, setIsGameOver] = useState(false); const [isVictory, setIsVictory] = useState(false); const [credits, setCredits] = useState(100); const [hp, setHp] = useState(10); const [currentLocationId, setCurrentLocationId] = useState(""); const [selectedPlanet, setSelectedPlanet] = useState(null); const [isProcessing, setIsProcessing] = useState(false); const [isRerouting, setIsRerouting] = useState(false); const [activeEnemy, setActiveEnemy] = useState(null); const [logs, setLogs] = useState([]); const [power, setPower] = useState({ engines: 3, lasers: 3, shields: 3, }); const MAX_POWER = 9; const WIN_THRESHOLD = 100000; const selectRandomSector = useCallback( (all: Planet[], count: number = 15) => { const shuffled = [...all].sort(() => 0.5 - Math.random()); return shuffled.slice(0, count); }, [], ); const currentPlanet = useMemo( () => planets.find((p) => p.id === currentLocationId) || null, [planets, currentLocationId], ); // --- Log Helper --- const addLog = useCallback( (message: string, type: LogEntry["type"] = "info") => { const newLog: LogEntry = { id: Math.random().toString(36).substring(2, 9), message, type, timestamp: new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", }), }; setLogs((prev) => [...prev, newLog]); }, [], ); // --- Actions --- const updatePower = (newSettings: typeof power) => { if (!activeEnemy) { setPower(newSettings); return; } setIsRerouting(true); addLog(t.ENGINE.SYSTEMS.REROUTING, "info"); setTimeout(() => { setPower(newSettings); if (Math.random() > 0.7) { const damage = 1; setHp((prev) => Math.max(0, prev - damage)); addLog( t.ENGINE.SYSTEMS.REROUTE_FAIL(activeEnemy.name, damage), "danger", ); } else { addLog(t.ENGINE.SYSTEMS.REROUTE_SUCCESS, "success"); } setIsRerouting(false); }, 600); }; const startGame = () => { setGameStarted(true); addLog(t.ENGINE.BOOT.WELCOME, "info"); }; const executeJump = async () => { if (!selectedPlanet || selectedPlanet.id === currentLocationId) return; setIsProcessing(true); addLog( `${t.ENGINE.JUMP.INIT(selectedPlanet.name)} ${t.ENGINE.DICE.ROLLING_1W6}`, "info", ); setTimeout(() => { const roll = Math.floor(Math.random() * 6) + 1; const rollInfo = t.ENGINE.DICE.RESULT_1W6(roll); if (roll >= 5) { const randomShip = starships[Math.floor(Math.random() * starships.length)]; setActiveEnemy(randomShip); addLog( `${rollInfo} ${t.ENGINE.JUMP.INTERCEPTION(randomShip.name)}`, "danger", ); } else { const reward = 150; setCredits((prev) => prev + reward); setCurrentLocationId(selectedPlanet.id); addLog( `${rollInfo} ${t.ENGINE.JUMP.SUCCESS(selectedPlanet.name, reward)}`, "success", ); } setIsProcessing(false); setSelectedPlanet(null); }, 1200); }; const executeEscape = () => { if (!activeEnemy) return; setIsProcessing(true); addLog(t.ENGINE.ESCAPE.INIT, "info"); setTimeout(() => { const roll = Math.floor(Math.random() * 6) + 1; const engineBonus = Math.floor(power.engines / 2); const total = roll + engineBonus; if (total >= 5) { setActiveEnemy(null); addLog( `${t.ENGINE.DICE.RESULT_TOTAL(total, engineBonus)} ${t.ENGINE.ESCAPE.SUCCESS}`, "success", ); } else { const damage = 2; setHp((prev) => Math.max(0, prev - damage)); addLog( `${t.ENGINE.DICE.RESULT_TOTAL(total, engineBonus)} ${t.ENGINE.ESCAPE.FAIL(activeEnemy.name, damage)}`, "danger", ); } setIsProcessing(false); }, 800); }; const handleAttack = () => { if (!activeEnemy) return; setIsProcessing(true); addLog(t.ENGINE.COMBAT.INIT(activeEnemy.name), "info"); setTimeout(() => { const d1 = Math.floor(Math.random() * 6) + 1; const d2 = Math.floor(Math.random() * 6) + 1; const laserBonus = Math.floor(power.lasers / 2); const total = d1 + d2 + laserBonus; if (total >= activeEnemy.ds) { const newHp = (activeEnemy.hp || 1) - 1; if (newHp <= 0) { const loot = 300; setCredits((prev) => prev + loot); setActiveEnemy(null); addLog(t.ENGINE.COMBAT.VICTORY(activeEnemy.name, loot), "success"); } else { setActiveEnemy({ ...activeEnemy, hp: newHp }); addLog(t.ENGINE.COMBAT.HIT(activeEnemy.name, newHp), "success"); } } else { const engineBonus = Math.floor(power.engines / 2); const evasionRoll = Math.floor(Math.random() * 6) + 1; if (evasionRoll + engineBonus >= 5) { addLog(t.ENGINE.COMBAT.EVASION(evasionRoll, engineBonus), "success"); } else { const rawDiff = activeEnemy.ds - total; const shieldBonus = Math.floor(power.shields / 2); const dmg = Math.max(0, rawDiff - shieldBonus); setHp((prev) => Math.max(0, prev - dmg)); addLog(t.ENGINE.COMBAT.COUNTER(activeEnemy.name, dmg), "danger"); } } setIsProcessing(false); }, 1000); }; const handleRepair = () => { const missingHp = 10 - hp; const cost = missingHp * 20; if (missingHp <= 0) return; if (credits >= cost) { setCredits((prev) => prev - cost); setHp(10); addLog( t.ENGINE.REPAIR.SUCCESS(currentPlanet?.name || "Unknown", cost), "success", ); } else { addLog(t.ENGINE.REPAIR.INSUFFICIENT_FUNDS, "danger"); } }; // --- Effects --- useEffect(() => { async function initGame() { try { setLoading(true); const { planets: p, starships: s } = await fetchGameData(); setAllPlanets(p); setStarships(s); const initialSector = selectRandomSector(p, 15); setPlanets(initialSector); if (initialSector.length > 0) setCurrentLocationId(initialSector[0].id); addLog(t.ENGINE.BOOT.SUCCESS, "success"); } catch (error) { console.error(error); addLog(t.ENGINE.BOOT.ERROR, "danger"); } finally { setLoading(false); } } initGame(); }, [addLog, selectRandomSector]); useEffect(() => { if (hp <= 0 && !isGameOver) { setIsGameOver(true); addLog(t.ENGINE.SYSTEMS.CRITICAL_FAILURE, "danger"); } }, [hp, isGameOver, addLog]); useEffect(() => { if (credits >= WIN_THRESHOLD && !isVictory) { setIsVictory(true); addLog(t.VICTORY.MESSAGE, "success"); } }, [credits, isVictory, addLog]); const restartGame = () => { setHp(10); setCredits(100); setPower({ engines: 3, lasers: 3, shields: 3 }); setIsGameOver(false); setIsVictory(false); setActiveEnemy(null); setSelectedPlanet(null); setLogs([]); const newSector = selectRandomSector(allPlanets, 15); setPlanets(newSector); if (newSector.length > 0) setCurrentLocationId(newSector[0].id); addLog(t.ENGINE.BOOT.RESTART, "success"); addLog(t.ENGINE.SYSTEMS.SECTOR_UPDATE, "info"); }; return { planets, starships, loading, gameStarted, startGame, credits, hp, currentLocationId, currentPlanet, selectedPlanet, setSelectedPlanet, executeEscape, executeJump, handleAttack, handleRepair, isJumping: isProcessing, isRerouting, activeEnemy, power, updatePower, maxPower: MAX_POWER, logs, isGameOver, restartGame, isVictory, WIN_THRESHOLD, }; }