Underwater Exploration Game

Underwater Exploration Game

Money
$0
Fuel
0
Total Dives
0

Start Expedition

Equipment Bay (Upgrades)

Captain's Log

Manage Equipment

Manage Dive Zones

No equipment configured.

"; } uegConfig.equipment.forEach((eq) => { const level = uegState.equipmentLevels[eq.id] || 1; const cost = calculateUpgradeCost(eq); const item = document.createElement("div"); item.className = "ueg-equipment-item"; item.innerHTML = `
${eq.name} LVL ${level}
Upgrade: ${formatCurrency( cost )}
`; equipmentBay.appendChild(item); }); } /** * Renders the dive log. */ function renderDiveLog() { if (!diveLog) return; diveLog.innerHTML = ""; if (uegState.diveLog.length === 0) { logDive("Welcome, Captain! Ready for your first dive.", "info"); return; } uegState.diveLog.forEach((entry) => { const item = document.createElement("div"); item.className = `ueg-log-entry ueg-log-${entry.type}`; item.textContent = entry.message; diveLog.appendChild(item); }); } /** * Renders the configuration lists. */ function renderConfigLists() { if (!configEquipmentList || !configZoneList) return; // 1. Render Equipment List configEquipmentList.innerHTML = ""; if (uegConfig.equipment.length === 0) { configEquipmentList.innerHTML = "

No equipment defined.

"; } uegConfig.equipment.forEach((eq) => { const item = document.createElement("div"); item.className = "ueg-list-item"; item.innerHTML = ` ${eq.name} Base Cost: ${formatCurrency( eq.baseCost )} Bonus: ${formatCurrency( eq.rewardBonus )}
`; configEquipmentList.appendChild(item); }); // 2. Render Zone List configZoneList.innerHTML = ""; if (uegConfig.zones.length === 0) { configZoneList.innerHTML = "

No dive zones defined.

"; } uegConfig.zones.forEach((zone) => { const item = document.createElement("div"); item.className = "ueg-list-item"; item.innerHTML = ` ${zone.name} Fuel: ${zone.fuelCost} Reward: ${formatCurrency( zone.minReward )} - ${formatCurrency(zone.maxReward)}
`; configZoneList.appendChild(item); }); } /** * Update navigation button states. */ function updateNavButtons() { if (!nextBtn || !prevBtn) return; if (currentTabId === "ueg-tab-dashboard") { prevBtn.disabled = true; nextBtn.disabled = false; } else if (currentTabId === "ueg-tab-config") { prevBtn.disabled = false; nextBtn.disabled = true; } } /** * Re-renders all UI components. */ function fullRefreshUI() { renderDashboard(); renderConfigLists(); renderDiveLog(); updateNavButtons(); } // === EVENT HANDLERS (Must be global for onclick) === window.uegShowTab = (tabId, element) => { // Hide all content container .querySelectorAll(".ueg-tab-content") .forEach((tab) => (tab.style.display = "none")); // Deactivate all links container .querySelectorAll(".ueg-tab-link") .forEach((link) => link.classList.remove("ueg-active")); // Show selected content const tabToShow = container.querySelector("#" + tabId); if (tabToShow) { tabToShow.style.display = "block"; } // Activate selected link if (element) { element.classList.add("ueg-active"); } currentTabId = tabId; updateNavButtons(); }; window.uegNavigateTabs = (isNext) => { const tabs = Array.from( container.querySelectorAll(".ueg-tab-link") ); const currentIdx = tabs.findIndex((tab) => tab.classList.contains("ueg-active") ); let newIdx = isNext ? currentIdx + 1 : currentIdx - 1; if (newIdx >= 0 && newIdx < tabs.length) { tabs[newIdx].click(); } }; // --- Config Tab Handlers --- window.uegAddEquipment = () => { if ( !newEqName || !newEqCost || !newEqMulti || !newEqBonus ) return; const name = newEqName.value.trim(); const baseCost = parseFloat(newEqCost.value); const costMultiplier = parseFloat(newEqMulti.value); const rewardBonus = parseFloat(newEqBonus.value); if ( !name || isNaN(baseCost) || isNaN(costMultiplier) || isNaN(rewardBonus) ) { alert("Please fill in all equipment fields with valid numbers."); return; } const newId = "e" + Date.now(); uegConfig.equipment.push({ id: newId, name, baseCost, costMultiplier, rewardBonus, }); uegState.equipmentLevels[newId] = 1; // Initialize level newEqName.value = ""; newEqCost.value = ""; newEqMulti.value = ""; newEqBonus.value = ""; renderConfigLists(); renderDashboard(); // Update equipment bay }; window.uegRemoveEquipment = (id) => { if ( !confirm("Are you sure you want to remove this equipment?") ) { return; } uegConfig.equipment = uegConfig.equipment.filter( (eq) => eq.id !== id ); delete uegState.equipmentLevels[id]; renderConfigLists(); renderDashboard(); // Update equipment bay }; window.uegAddZone = () => { if ( !newZoneName || !newZoneFuel || !newZoneMin || !newZoneMax ) return; const name = newZoneName.value.trim(); const fuelCost = parseFloat(newZoneFuel.value); const minReward = parseFloat(newZoneMin.value); const maxReward = parseFloat(newZoneMax.value); if ( !name || isNaN(fuelCost) || isNaN(minReward) || isNaN(maxReward) ) { alert("Please fill in all zone fields with valid numbers."); return; } if (minReward > maxReward) { alert("Min Reward cannot be greater than Max Reward."); return; } uegConfig.zones.push({ id: "z" + Date.now(), name, fuelCost, minReward, maxReward, }); newZoneName.value = ""; newZoneFuel.value = ""; newZoneMin.value = ""; newZoneMax.value = ""; renderConfigLists(); renderDashboard(); // Update zone dropdown }; window.uegRemoveZone = (id) => { if ( !confirm("Are you sure you want to remove this dive zone?") ) { return; } uegConfig.zones = uegConfig.zones.filter( (z) => z.id !== id ); renderConfigLists(); renderDashboard(); // Update zone dropdown }; // --- Dashboard Tab Handlers --- window.uegDoDive = () => { if (!zoneSelect) return; const zoneId = zoneSelect.value; if (!zoneId) { logDive("No dive zone selected!", "fail"); return; } const zone = uegConfig.zones.find( (z) => z.id === zoneId ); if (!zone) { logDive("Error: Selected zone not found.", "fail"); return; } // 1. Check fuel if (uegState.resources.fuel < zone.fuelCost) { logDive( `Dive failed: Not enough fuel for ${zone.name}. (Required: ${zone.fuelCost})`, "fail" ); renderDashboard(); return; } // 2. Pay cost uegState.resources.fuel -= zone.fuelCost; uegState.totalDives++; // 3. Calculate reward const baseReward = Math.floor( Math.random() * (zone.maxReward - zone.minReward + 1) ) + zone.minReward; const bonusReward = calculateTotalBonus(); const totalReward = baseReward + bonusReward; // 4. Get reward uegState.resources.money += totalReward; logDive( `Dive to ${ zone.name } successful! Found treasure worth ${formatCurrency( baseReward )} + ${formatCurrency( bonusReward )} (Bonus). Total: ${formatCurrency( totalReward )}.`, "success" ); renderDashboard(); }; window.uegUpgradeEquipment = (id) => { const eq = uegConfig.equipment.find((e) => e.id === id); if (!eq) { logDive("Error: Equipment not found.", "fail"); return; } const cost = calculateUpgradeCost(eq); // 1. Check money if (uegState.resources.money < cost) { logDive( `Upgrade failed: Not enough money for ${ eq.name }. (Required: ${formatCurrency(cost)})`, "fail" ); renderDashboard(); return; } // 2. Pay cost uegState.resources.money -= cost; // 3. Increment level uegState.equipmentLevels[id]++; logDive( `Upgraded ${eq.name} to LVL ${uegState.equipmentLevels[id]}!`, "upgrade" ); renderDashboard(); }; // --- PDF Download --- window.uegDownloadPDF = () => { if (!jsPDF) { alert("PDF library is not loaded. Please try again."); return; } try { const doc = new jsPDF(); const pageMargin = 15; const pageWidth = doc.internal.pageSize.getWidth(); const contentWidth = pageWidth - pageMargin * 2; let y = 20; // 1. Title doc.setFontSize(20); doc.text( "Captain's Status Report", pageWidth / 2, y, { align: "center" } ); y += 20; // 2. Current Status doc.setFontSize(16); doc.text("Current Resources", pageMargin, y); y += 8; doc.setFontSize(12); doc.text( `Money: ${formatCurrency(uegState.resources.money)}`, pageMargin, y ); y += 7; doc.text( `Fuel: ${formatNumber(uegState.resources.fuel)}`, pageMargin, y ); y += 7; doc.text( `Total Dives: ${formatNumber(uegState.totalDives)}`, pageMargin, y ); y += 15; // 3. Equipment Status doc.setFontSize(16); doc.text("Equipment Status", pageMargin, y); y += 8; doc.setFontSize(12); uegConfig.equipment.forEach((eq) => { doc.text( `${eq.name}: LVL ${ uegState.equipmentLevels[eq.id] || 1 }`, pageMargin, y ); y += 7; if (y > 270) { doc.addPage(); y = pageMargin; } }); y += 8; // 4. Dive Log doc.setFontSize(16); doc.text("Recent Log", pageMargin, y); y += 8; doc.setFontSize(10); const logEntries = uegState.diveLog.slice(0, 20); // Get last 20 logEntries.forEach((entry) => { if (y > 270) { doc.addPage(); y = pageMargin; } const splitText = doc.splitTextToSize( entry.message, contentWidth ); doc.text(splitText, pageMargin, y); y += splitText.length * 4 + 4; }); doc.save("Underwater_Exploration_Report.pdf"); } catch (e) { console.error("Error generating PDF:", e); alert( "An error occurred while generating the PDF." ); } }; // === INITIALIZATION === fullRefreshUI(); });