You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

14 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

HikeMap is a location-based RPG web application with trail/GPS track editing capabilities. Players walk in the real world to explore, battle monsters, and level up their characters. The frontend is a single-page application in index.html with a Node.js/Express backend in server.js.

Development

docker-compose up -d

Access at http://localhost:880

Local Development

npm install
node server.js

Then open http://localhost:8080

Architecture

File Structure

File Purpose
index.html Frontend SPA (CSS, HTML, JavaScript)
server.js Express API server, WebSocket handling
database.js SQLite database layer (better-sqlite3)
animations.js Combat/monster animation definitions
docker-compose.yml Container configuration
hikemap.db SQLite database (auto-created)
SKILLS.md Complete skills documentation

Asset Directories

Directory Purpose
mapgameimgs/monsters/ Monster sprites (50px and 100px versions)
mapgameimgs/bases/ Home base icons
mapgameimgs/skills/ Custom skill icons (uploaded via admin)
mapgameimgs/cacheicons/ Geocache type icons
mapgamemusic/ Background music tracks
sfx/ Sound effects (combat, spawns, etc.)

Key Libraries

  • Frontend: MapLibre GL JS 4.1.0 (WebGL vector maps), Turf.js (geospatial math)
  • Backend: Express, better-sqlite3, jsonwebtoken, ws (WebSocket)
  • Note: Codebase has Leaflet compatibility shims for gradual migration

RPG System

Core Concepts

Character Creation:

  • Player chooses Race (Human, Elf, Dwarf, Halfling) and Class (Trail Runner)
  • Race provides stat bonuses, Class determines skills and growth

Stats:

Stat Description
HP Health points - reach 0 and you die
MP Mana points - used for skills
ATK Attack power
DEF Defense (reduces damage taken)
Accuracy Hit chance modifier
Dodge Evasion chance

Home Base:

  • Set by player, 20-meter radius (HOME_BASE_RADIUS)
  • 3x HP regeneration when at home
  • Required to respawn after death
  • Skill loadout can only be changed at home

Fog of War:

  • Canvas-based overlay that hides unexplored areas
  • Two reveal zones: homebase radius and player explore radius
  • Geocaches only visible/interactable in revealed areas
  • Multipliers can modify reveal radius (via utility skills)
  • Hard-edged cutout (no gradient layers)

Virtual Movement Mode:

  • Developer/testing feature for moving without real GPS
  • WASD/arrow keys move virtual position on map
  • Winch tethering system: walking away from virtual position reels it back
  • Prevents unlimited virtual exploration - real GPS movement matters
  • Toggle via developer tools panel

Combat System

Monster Spawning:

  • Monsters spawn while walking (configurable distance)
  • No spawns within home base radius
  • Multiple monsters can accumulate (entourage)
  • Spawn sound effect plays when monster appears (sfx/ directory)

Combat Flow:

  1. Player taps monster to engage
  2. Turn-based combat with skill selection
  3. Hit/miss calculated per skill accuracy
  4. XP awarded on victory
  5. Death sends player to respawn state

Damage Formula:

damage = (skillPower * playerATK / 100) - enemyDEF
hitChance = skillAccuracy + (attackerAccuracy - 90) - defenderDodge

Animation System (animations.js):

  • Separate file defines all combat animations
  • Player animations: attack, skill, miss, death
  • Monster animations: attack, skill, miss, death, idle, bouncy, various flips
  • Each animation has: duration, loop, easing, keyframes
  • Combat timing syncs damage with animation "hit" moment (500ms delay)
  • Skills can override default animation via animation field

Skill System

Skill Tiers: Skills unlock at level milestones (2, 3, 4, 5, 6, 7)

Skill Types:

  • damage: Deal damage to enemies
  • heal: Restore HP
  • buff: Temporary stat boosts (defense, accuracy)
  • utility: Out-of-combat effects (MP regen boost)
  • status: Apply effects like poison

Loadout System:

  • On level-up: ALL offered skills unlock, player picks one to activate
  • unlockedSkills: Everything learned
  • activeSkills: Currently equipped (one per tier)
  • Swap active skills at home base only

See SKILLS.md for complete skill reference.

Custom Skill Icons:

  • Upload via admin panel (/admin.html)
  • Stored in mapgameimgs/skills/ directory
  • Database field: skills.icon stores filename
  • Falls back to emoji if no custom icon set

Classes

Trail Runner (currently the only class):

Base Stat Value Per Level
HP 100 +10
MP 50 +5
ATK 12 +2
DEF 8 +1
Accuracy 90 -
Dodge 15 -

Races

Race HP MP ATK DEF
Human +5 +5 +0 +0
Elf -5 +15 +0 -2
Dwarf +15 -5 +0 +3
Halfling -5 +0 +2 +5

Monsters

Current Monster Types:

Monster Level Range Notes
Moop 1-5 Basic enemy
Fancy Moop 1-5 Higher ATK
Fanciest Moop 3-5 Stronger variant
Sub Par Moop 1-1 Very weak, tutorial enemy

MOOP = Matter Out Of Place (litter-themed enemies)


Database Schema (database.js)

Key Tables

Users & Auth:

  • users: id, username, password_hash, is_admin, created_at

RPG Stats:

  • rpg_stats: player_id, name, race, class, level, xp, hp, maxHp, mp, maxMp, atk, def, home_base_lat/lng, unlocked_skills, active_skills, is_dead, home_base_icon

Skills:

  • skills: id, name, description, type, mp_cost, base_power, accuracy, hit_count, target, status_effect
  • class_skills: Links skills to classes with unlock_level and choice_group
  • class_skill_names: Class-specific skill renames

Monsters:

  • monster_types: id, name, icon, base_hp/atk/def, xp_reward, level scaling, dialogues

Buffs:

  • player_buffs: Active buffs with expiry times (e.g., Second Wind)

Important Methods

// database.js key methods
db.getRpgStats(userId)        // Get player stats
db.saveRpgStats(userId, stats) // Save player stats
db.resetUserProgress(userId)   // Admin: reset player
db.swapActiveSkill(userId, tier, newSkillId) // Swap loadout

API Endpoints (server.js)

Authentication

Method Endpoint Description
POST /api/auth/register Create account
POST /api/auth/login Login, returns JWT

RPG

Method Endpoint Description
GET /api/user/has-character Check if character exists
POST /api/user/character Create character
GET /api/user/rpg-stats Get player stats
PUT /api/user/rpg-stats Save player stats
POST /api/user/swap-skill Swap active skill (at home)
POST /api/user/activate-buff Activate utility skill
GET /api/user/buffs Get active buffs

Game Data

Method Endpoint Description
GET /api/skills All skills
GET /api/classes All classes with skills
GET /api/monster-types All monster types
GET /api/spawn-settings Monster spawn config

Admin

Method Endpoint Description
POST /api/admin/reset-progress/:userId Reset player
POST /api/admin/reset-homebase/:userId Clear home base
PUT /api/admin/spawn-settings Update spawn config

Frontend Structure (index.html)

Line Ranges (approximate)

Lines Content
1-3000 CSS styles
3000-3700 HTML structure
3700-4500 Constants, state, skill definitions
4500-10000 Map, track editing, geocaches
10000-11000 Character creation, sheet
11000-12000 Stats management, saving
12000-13500 Combat system, monsters

Key State Variables

// RPG State
playerStats         // Player RPG data
combatState         // Active combat info
monsterEntourage    // Spawned monsters
statsLoadedFromServer // Prevents stale saves
pendingSkillChoice  // Level-up skill selection

// GPS & Virtual Movement
userLocation        // Current position (real or virtual)
realGpsPosition     // Actual GPS coordinates
testPosition        // Virtual position when in test mode
gpsTestMode         // Virtual movement enabled flag
previousWinchRealGps // Winch system - tracks real GPS for tethering

// Fog of War
fogCanvas           // Canvas element for fog overlay
fogCtx              // 2D context for fog drawing
fogSystemReady      // Flag indicating fog can render
exploreRadiusMultiplier  // Skill-modified explore radius
homebaseRadiusMultiplier // Skill-modified homebase radius

Key Functions

// RPG & Combat
initializePlayerStats(username)  // Load from server
savePlayerStats()                // Save to server
showSkillChoiceModal(level)      // Level-up skill pick
swapSkillFromHomebase(tier, id)  // Change loadout
startCombat(monsters)            // Begin combat
useSkill(skillId)                // Execute skill in combat

// Fog of War
updateFogOfWar()                 // Redraw fog overlay
isInRevealedArea(lat, lng)       // Check if location visible
initFogOfWar()                   // Create fog canvas

// Virtual Movement & Winch
enableVirtualMovement()          // Enter virtual GPS mode
disableVirtualMovement()         // Return to real GPS
simulateGpsPosition()            // Update map with virtual position
applyWinchTether(newRealPosition) // Reel in virtual when walking away

// Animations (from animations.js)
getAnimation(animationId)        // Get animation definition
getAnimationList()               // List monster animations
getPlayerAnimationList()         // List player animations

Data Persistence

Server-Authoritative Model:

  1. On page load, fetch stats from server
  2. statsLoadedFromServer flag prevents premature saves
  3. Auto-save every 30 seconds after initial load
  4. beforeunload uses sendBeacon for reliable final save
  5. localStorage used as read-only backup

Critical: Never save to server until statsLoadedFromServer = true


Common Tasks

Adding a New Skill

  1. Insert into skills table (database.js or admin panel)
  2. Add to class_skills with unlock_level and choice_group
  3. Optionally add class rename in class_skill_names
  4. Add icon/calculate function in SKILLS constant if special behavior needed

Adding a New Class

  1. Insert into classes table
  2. Create class_skills entries for skill progression
  3. Add class_skill_names for thematic renames
  4. Update getClassIcon() for display

Adding a New Monster

  1. Insert into monster_types via admin panel or database
  2. Set level range, stats, dialogues
  3. Optionally add to monster_skills for special abilities

Troubleshooting

Docker: Restart vs Rebuild

Most source files are volume-mounted in docker-compose.yml, so changes are reflected without rebuilding.

Action required by file type:

File Action Notes
index.html Rebuild container Volume mount may not sync live
admin.html Rebuild container Volume mount may not sync live
service-worker.js Rebuild container + bump cache version Volume mount may not sync live
server.js Rebuild container Volume mount may not sync live
database.js Rebuild container Volume mount may not sync live
mapgameimgs/* Browser refresh Volume-mounted
mapgamemusic/* Browser refresh Volume-mounted
sfx/* Browser refresh Volume-mounted
hikemap.db Nothing Volume-mounted, persists outside container

IMPORTANT: Despite being volume-mounted, code files (index.html, server.js, etc.) often require a container rebuild to reflect changes. Always rebuild when in doubt.

Files requiring full rebuild (docker-compose up -d --build):

File Why Rebuild?
package.json New npm dependencies need installing
Dockerfile Build process changes
manifest.json Not volume-mounted
icon-*.png Not volume-mounted
.env Not volume-mounted
.well-known/* Not volume-mounted
default.kml Not volume-mounted
docker-compose.yml Container config changes

Commands:

# Restart container (fast - for server.js/database.js changes)
docker restart hikemap_hikemap_1

# Full rebuild (slow - only when needed)
docker-compose up -d --build

# If rebuild fails with volume errors:
docker ps -a | grep hike  # Find container ID
docker rm <container_id>
docker-compose up -d --build

Cache Issues

After server-side changes, users may need to clear browser cache:

  1. Increment CACHE_NAME version in service-worker.js
  2. Hard refresh in browser (Ctrl+Shift+R)
  3. Or clear site data in browser DevTools

Common Issues

"Changes not appearing after edit"

  • Client files (html/js): Just refresh browser
  • Server files (server.js, database.js): Run docker restart hikemap_hikemap_1
  • Did you bump the service worker cache version?

"API returns old data"

  • Check container is running: docker ps | grep hike
  • Restart container: docker restart hikemap_hikemap_1
  • Check container logs: docker logs hikemap_hikemap_1

"Database changes lost after rebuild"

  • The hikemap.db file is mounted as a volume and persists
  • Schema changes are applied via migrations in database.js on startup