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

4.9 KiB

name description type
Town Rendering & Equipment Slots Much bigger town buildings rendered via PixiJS Graphics on map, NPC rendering/interaction, wandering NPC encounters, extended equipment slots UI, daily tasks, achievements, nearby heroes, collision detection project

Updated on 2026-03-27:

Towns on Map (enlarged in March 2026 update):

  • GameRenderer.drawTowns() draws large ground planes (tan/brown dirt ellipses), then clusters of 5-14 houses spread over ~100px radius
  • Houses have 3 roof styles (pointed, flat, chimney), 2-3 windows, doors with knobs, optional fences and market stalls
  • _drawHouse() accepts roofStyle parameter (0=pointed, 1=flat, 2=pointed+chimney)
  • _drawFence() and _drawTownStall() add variety between houses
  • Town border circle: radius * TILE_WIDTH * 0.7 (was 0.35), scale factor: radius / 8 (was /12)
  • Town name label: 18px font (was 13px), positioned above house cluster
  • House positions: deterministic pseudo-random from town.id for consistent layout
  • GameEngine.setTowns() stores TownData[] and checks hero proximity each tick for enter/exit events
  • Town data comes from /towns API, converted via townToTownData() in App.tsx
  • TownData interface: id (number), centerX/centerY/radius/size, optional npcs: NPCData[]

NPC Rendering and Interaction (March 2026 update):

  • NPCData interface: id, name, type ('quest_giver'|'merchant'|'healer'), worldX, worldY
  • GameRenderer.drawNPCs() renders type-specific colored diamonds with floating icons (!/$/ +) and name labels
  • Quest givers: gold body, "!" icon; Merchants: green body, "$" icon; Healers: white body, "+" icon
  • Idle sway animation based on NPC id
  • GameEngine.setNPCs() stores all NPCs, _checkNPCProximity() fires onNearestNPCChange within 2 tiles
  • NPCInteraction.tsx: floating panel appears when hero near NPC, type-specific action button
  • App.tsx wires nearest NPC state, dismiss tracking, and opens NPCDialog for quest givers
  • Town NPC fetching: getTownNPCs() for each town, NPCs positioned at town.worldX + npc.offsetX

Wandering NPC Encounter (March 2026 update):

  • NPCEncounterEvent type in types.ts: type, npcName, message, cost
  • Encounter provider checks for type: "npc_event" response from requestEncounter
  • WanderingNPCPopup.tsx: modal with accept/decline, calls POST /api/v1/hero/npc-alms
  • giveNPCAlms() API returns hero + received item details

Extended Equipment (spec 6.3):

  • EquipmentItem interface with id/slot/formId/name/rarity/ilvl/primaryStat/statType
  • HeroState.equipment?: Record<string, EquipmentItem> optional map
  • HeroResponse.equipment added to API types
  • HeroPanel dynamically renders 5 display slots (main_hand, chest, head, feet, neck) with fallback to legacy weapon/armor fields
  • EquipmentPanel.tsx -- compact 5-column grid with tap-to-expand detail, rarity-colored borders

Daily Tasks (spec 10.1) -- now backend-driven:

  • DailyTasks.tsx -- expandable top-right panel with progress bars
  • Fetches from GET /api/v1/hero/daily-tasks via getDailyTasks() API
  • Claim button on completed unclaimed tasks calls POST /api/v1/hero/daily-tasks/{taskId}/claim
  • Refreshes after victories, buff activations, and claims
  • DailyTaskResponse interface in api.ts

Achievements (spec 10.3):

  • AchievementsPanel.tsx -- expandable panel (trophy icon, top-right at x=240)
  • Fetches from GET /api/v1/hero/achievements via getAchievements() API
  • Unlocked: gold border, checkmark, unlock date; Locked: grey with progress bar
  • After each victory, compares new achievements with previous state; shows toast for newly unlocked

Nearby Heroes (spec 2.3 shared world):

  • GET /api/v1/hero/nearby via getNearbyHeroes() API; polled every 5 seconds
  • GameEngine.setNearbyHeroes() stores NearbyHeroData[]
  • GameRenderer.drawNearbyHeroes() draws semi-transparent green diamonds with name+level labels and idle sway
  • NearbyHeroData interface in types.ts

Collision Detection (spec 2.2):

  • Procedural terrain/object generation extracted to src/game/procedural.ts (shared by renderer and engine)
  • isProcedurallyBlocked(wx, wy) checks if a tile has a blocking object (tree, bush, rock, ruin, stall, well)
  • Engine _isBlocked() checks server obstacle set first, falls back to procedural
  • In _simulateWalking: before applying position delta, checks next tile; if blocked, tries 90-degree turn, then reverses
  • GameEngine.populateObstacles() accepts server map objects for non-procedural maps

Why: MVP feature expansion per spec sections 2.2, 2.3, 2.4, 2.5, 6.3, 10.1, 10.3.

How to apply: Town rendering is in the ground layer (drawn after tiles, before entities). NPCs are in the entity layer for depth sorting. NPC proximity is checked every engine tick. Equipment UI extends legacy weapon/armor pattern. Daily tasks and achievements are now backend-driven. Collision uses procedural generation for the endless world.