diff --git a/index.html b/index.html
index 8012213..8c9a594 100644
--- a/index.html
+++ b/index.html
@@ -4185,7 +4185,8 @@
// Fog of War state variables (must be declared before use)
let fogCanvas = null;
let fogCtx = null;
- let playerRevealRadius = 800;
+ let playerRevealRadius = 800; // Homebase reveal radius (meters)
+ let playerExploreRadius = 50; // Player's personal reveal radius when exploring (meters)
// Initialize fog of war canvas (directly in map container for simple viewport alignment)
function initFogOfWar() {
@@ -4260,52 +4261,96 @@
fogCtx.fillStyle = 'rgba(0, 0, 0, 0.6)';
fogCtx.fillRect(0, 0, width, height);
- // If no homebase set, full fog
- if (!playerStats || playerStats.homeBaseLat == null || playerStats.homeBaseLng == null) {
- return;
+ // Homebase reveal (only if homebase exists)
+ if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
+ // Calculate reveal circle center using container coordinates (viewport-relative)
+ const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
+ const centerPoint = map.latLngToContainerPoint(homeLatLng);
+
+ // Calculate radius in pixels using map projection
+ const edgeLatLng = destinationPoint(homeLatLng, playerRevealRadius, 90);
+ const edgePoint = map.latLngToContainerPoint(edgeLatLng);
+ const radiusPixels = Math.abs(edgePoint.x - centerPoint.x);
+
+ // Cut out revealed area using composite operation
+ fogCtx.save();
+ fogCtx.globalCompositeOperation = 'destination-out';
+
+ // Create gradient for soft edge
+ const gradient = fogCtx.createRadialGradient(
+ centerPoint.x, centerPoint.y, radiusPixels * 0.85,
+ centerPoint.x, centerPoint.y, radiusPixels
+ );
+ gradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
+ gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
+
+ fogCtx.beginPath();
+ fogCtx.arc(centerPoint.x, centerPoint.y, radiusPixels, 0, Math.PI * 2);
+ fogCtx.fillStyle = gradient;
+ fogCtx.fill();
+
+ fogCtx.restore();
}
- // Calculate reveal circle center using container coordinates (viewport-relative)
- const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
- const centerPoint = map.latLngToContainerPoint(homeLatLng);
+ // Secondary reveal: Player's explore radius when outside homebase
+ if (userLocation) {
+ const playerLatLng = L.latLng(userLocation.lat, userLocation.lng);
+
+ // Check if player is outside homebase radius (or no homebase)
+ let isOutsideHomebase = true;
+ if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
+ const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
+ const distToHome = playerLatLng.distanceTo(homeLatLng);
+ isOutsideHomebase = distToHome > playerRevealRadius;
+ }
- // Calculate radius in pixels using map projection
- const edgeLatLng = destinationPoint(homeLatLng, playerRevealRadius, 90);
- const edgePoint = map.latLngToContainerPoint(edgeLatLng);
- const radiusPixels = Math.abs(edgePoint.x - centerPoint.x);
+ if (isOutsideHomebase) {
+ const playerPoint = map.latLngToContainerPoint(playerLatLng);
+ const playerEdge = destinationPoint(playerLatLng, playerExploreRadius, 90);
+ const playerEdgePoint = map.latLngToContainerPoint(playerEdge);
+ const playerRadiusPixels = Math.abs(playerEdgePoint.x - playerPoint.x);
- // Cut out revealed area using composite operation
- fogCtx.save();
- fogCtx.globalCompositeOperation = 'destination-out';
+ fogCtx.save();
+ fogCtx.globalCompositeOperation = 'destination-out';
- // Create gradient for soft edge
- const gradient = fogCtx.createRadialGradient(
- centerPoint.x, centerPoint.y, radiusPixels * 0.85,
- centerPoint.x, centerPoint.y, radiusPixels
- );
- gradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
- gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
+ const playerGradient = fogCtx.createRadialGradient(
+ playerPoint.x, playerPoint.y, playerRadiusPixels * 0.85,
+ playerPoint.x, playerPoint.y, playerRadiusPixels
+ );
+ playerGradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
+ playerGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
- fogCtx.beginPath();
- fogCtx.arc(centerPoint.x, centerPoint.y, radiusPixels, 0, Math.PI * 2);
- fogCtx.fillStyle = gradient;
- fogCtx.fill();
+ fogCtx.beginPath();
+ fogCtx.arc(playerPoint.x, playerPoint.y, playerRadiusPixels, 0, Math.PI * 2);
+ fogCtx.fillStyle = playerGradient;
+ fogCtx.fill();
- fogCtx.restore();
+ fogCtx.restore();
+ }
+ }
}
- // Check if a location is within the revealed area
+ // Check if a location is within the revealed area (homebase or player explore radius)
function isInRevealedArea(lat, lng) {
- // If no homebase, nothing is revealed
- if (!playerStats || playerStats.homeBaseLat == null || playerStats.homeBaseLng == null) {
- return false;
+ const checkPoint = L.latLng(lat, lng);
+
+ // Check homebase radius
+ if (playerStats && playerStats.homeBaseLat != null && playerStats.homeBaseLng != null) {
+ const homeLatLng = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng);
+ if (homeLatLng.distanceTo(checkPoint) <= playerRevealRadius) {
+ return true;
+ }
}
- // Calculate distance from homebase
- const distance = L.latLng(playerStats.homeBaseLat, playerStats.homeBaseLng)
- .distanceTo(L.latLng(lat, lng));
+ // Check player's explore radius
+ if (userLocation) {
+ const playerLatLng = L.latLng(userLocation.lat, userLocation.lng);
+ if (playerLatLng.distanceTo(checkPoint) <= playerExploreRadius) {
+ return true;
+ }
+ }
- return distance <= playerRevealRadius;
+ return false;
}
// Hook fog updates to map events (fog will be initialized lazily)
@@ -5586,9 +5631,10 @@
// Check for monster clear at home base
checkHomeBaseMonsterClear();
- // Update geocache visibility based on new location
+ // Update geocache visibility and fog of war based on new location
if (navMode) {
updateGeocacheVisibility();
+ updateFogOfWar();
}
// Update or create marker
@@ -15680,6 +15726,9 @@
statsSyncState.inCombat = false;
flushStatsSync();
+ // Update fog of war to reflect current position after combat
+ updateFogOfWar();
+
// If victory music isn't playing, switch to appropriate ambient music
if (gameMusic.currentTrack !== 'victory' || gameMusic.victory.paused) {
const distToHome = getDistanceToHome();