@ -13642,11 +13642,32 @@
const playerLevel = playerStats.level;
const playerPos = L.latLng(userLocation.lat, userLocation.lng);
// Helper: check if player is near a geocache with a specific tag
function isNearTaggedLocation(tag, maxDist = 400) {
// Random offset 30-60 meters from player (calculate FIRST so we can check spawn position)
const angle = Math.random() * 2 * Math.PI;
const distance = 30 + Math.random() * 30; // 30-60 meters
// Convert meters to degrees (rough approximation)
const metersPerDegLat = 111320;
const metersPerDegLng = 111320 * Math.cos(userLocation.lat * Math.PI / 180);
const offsetLat = (distance * Math.cos(angle)) / metersPerDegLat;
const offsetLng = (distance * Math.sin(angle)) / metersPerDegLng;
// Calculate spawn position BEFORE filtering eligible types
const spawnLat = userLocation.lat + offsetLat;
const spawnLng = userLocation.lng + offsetLng;
const spawnPos = L.latLng(spawnLat, spawnLng);
// Helper: check if SPAWN POSITION is near a geocache with a specific tag
// Uses the tag's configured spawn_radius from OSM_TAGS
function isSpawnNearTaggedLocation(tag) {
// Get the spawn radius from OSM_TAGS config, default to 400m
const tagConfig = OSM_TAGS[tag];
const maxDist = tagConfig?.spawnRadius || 400;
for (const cache of geocaches) {
if (cache.tags & & cache.tags.includes(tag)) {
const dist = playerPos.distanceTo(L.latLng(cache.lat, cache.lng));
const dist = spawn Pos.distanceTo(L.latLng(cache.lat, cache.lng));
if (dist < = maxDist) return true;
}
}
@ -13661,8 +13682,8 @@
const spawnLoc = type.spawnLocation || 'anywhere';
if (spawnLoc === 'anywhere') return true;
// Monster has a location restriction - check if player is near matching geocache
return isNearTaggedLocation(spawnLoc);
// Monster has a location restriction - check if SPAWN POSITION is near matching geocache
return isSpawn NearTaggedLocation(spawnLoc);
});
if (eligibleTypes.length === 0) {
@ -13672,17 +13693,6 @@
const [typeId, monsterType] = eligibleTypes[Math.floor(Math.random() * eligibleTypes.length)];
// Random offset 30-60 meters from player
const angle = Math.random() * 2 * Math.PI;
const distance = 30 + Math.random() * 30; // 30-60 meters
// Convert meters to degrees (rough approximation)
const metersPerDegLat = 111320;
const metersPerDegLng = 111320 * Math.cos(userLocation.lat * Math.PI / 180);
const offsetLat = (distance * Math.cos(angle)) / metersPerDegLat;
const offsetLng = (distance * Math.sin(angle)) / metersPerDegLng;
// Calculate monster level:
// - Base is player level with slight variation (-1 to +1)
// - Must be at least the monster's minLevel
@ -13698,8 +13708,8 @@
type: typeId,
level: monsterLevel,
position: {
lat: userLocation.lat + offset Lat,
lng: userLocation.lng + offset Lng
lat: spawn Lat,
lng: spawn Lng
},
spawnTime: Date.now(),
hp: monsterType.baseHp + (monsterLevel - 1) * monsterType.levelScale.hp,