Two issues caused objects to float relative to dungeon map:
1. rotAngle used (heading + PI) but canvas uses (PI - heading)
- these differ: sin(x+PI) = -sin(x) vs sin(PI-x) = sin(x)
2. Object dy was negated, but 180° heading offset already handles N/S
- double N/S flip caused objects to drift with heading changes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UB applies HeadingToQuaternion(heading - 180) for dungeon rendering.
The layer has Y increasing downward, and the 180° offset flips N/S.
Reverted coordinates to Version 1 (X mirror, Y direct) which had
correct tile connections, and added the 180° heading offset that UB
uses to fix N/S orientation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version 1 (X mirror, Y direct) had correct tile connections but N/S
flipped. Previous attempts to fix N/S also changed rotation handling
which broke tiles. This commit reverts tile processing (no flip),
reverts rotation (exact UB values), and only adds Y negation to
Version 1's working coordinates. No other changes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UB's tiles were authored for a mirrored-X rendering space. Instead of
mirroring coordinates (which breaks positioning), flip each tile image
horizontally during pre-processing and negate the cell rotation angles
to compensate. Cell and object positions remain direct (no mirroring).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UB mirrors both cell positions and player position within layer space,
so relative offset is direct (mirrors cancel out). Removed X negation.
Added float tolerance for rotation quaternion W component comparison
(was using strict equality which fails on floating point values).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Negate Y delta for dungeon tiles and objects so north points up
(AC Y+ = north, canvas Y+ = down)
- Wrap early COM calls in try/catch to prevent RPC_E_SERVERFAULT
during state transitions (portal loading, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UB uses mirrored X: x = -(cell.X - playerX), direct Y: y = cell.Y - playerY.
Applied same transform to tile rendering, object positioning, and
entity list distance calculations in dungeon mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Process each tile through canvas pixel manipulation:
- White pixels → transparent (same as UB's MakeTransparent)
- Remap UB's 5 source colors (walls, inner walls, ramps, floors, stairs)
to readable display colors on dark background
- Black outlines made semi-transparent
- Current floor at 85% opacity, other floors at 12%
- Non-current floors drawn first, current floor on top
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract 614 UB tile BMPs into dungeon_tiles.json (287KB base64 bundle).
Frontend loads tiles once, then draws them rotated per-cell using
environment IDs. Falls back to colored rectangles if tiles not loaded.
Current floor at 70% opacity, other floors at 15%.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Backend: dungeon_map event handler with permanent in-memory cache
by landblock ID, request_dungeon_map for late-joining browsers
- Frontend: render dungeon cells as colored rectangles when in dungeon,
multi-level Z support (current floor bright, others dimmed),
automatic overworld/dungeon switching based on is_dungeon flag,
raw physics coordinate positioning for dungeon objects
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Draws a rotated/scaled slice of the overworld map behind radar dots.
Map clips to the radar circle, rotates with heading-up mode, and
renders at 40% opacity so dots remain visible on top.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace range dropdown with smooth scroll-wheel zoom on canvas
- Click dot on canvas to select it (white ring + name label)
- Click row in entity list to select on canvas
- Click again to deselect
- Selected row highlighted with blue accent in list
- Auto-scrolls list to keep selected row visible
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AC heading is standard clockwise (0=N, 90=E). Both compass labels
and object rotation need positive heading — previous negation broke
the compass while fixing objects. Now both use the same sign.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AC's Actions.Heading uses opposite rotation from standard math
angles (confirmed by UtilityBelt's HeadingToQuaternion negation).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Compass is now always heading-up: player facing direction is fixed
pointing up, N/E/S/W labels rotate around the edge as player turns
- Fix: reopening a closed radar window now resends start_radar command
so streaming resumes without needing a full page refresh
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Browser can open a radar window per character that streams nearby
monsters, players, NPCs, portals, and other objects in real-time.
On-demand activation via start_radar/stop_radar commands through
the existing WebSocket command channel.
- Backend: nearby_objects event handler with in-memory cache and broadcast
- Frontend: canvas mini-map + entity list table in draggable window
- Radar button added to player list alongside Chat/Stats/Inventory/Char
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Widen the inventory layout so the backpack column no longer crowds the paperdoll, and base mana active/inactive display on the live data currently available from inventory payloads.
Grow the inventory window and mana panel dynamically based on tracked item count so all mana entries remain visible without introducing a scrollable panel.
Adjust the inventory mana panel to fit beside the backpack column without overlap, prevent the panel from scrolling, shrink composite icons correctly, and refine mana-state derivation using existing item spell data.
Move the Mana panel to the right of the backpack column, widen the inventory window, and switch to a smaller Mag-Tools-style row layout with compact icons and status dots.
Derive equipped item mana state and time-remaining data in inventory-service, then render a Mana panel inside the inventory window with live icon, state, mana, and countdown display.
- Fix remaining f-string SQL injection in process_inventory (same pattern
as single-item endpoints: parameterized ANY(:ids) queries)
- Add null guard for item_id in backend delta remove handler
- Add response status logging for inventory service HTTP calls
- Fix frontend ID fallback consistency in updateInventoryLive
- Replace debug print() with logger.debug()
- Add comment for Decal Slot_Decal magic number
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace f-string SQL interpolation with parameterized ANY(:ids) queries
- Populate slot column from IntValues[231735296] (Decal Slot key)
- Add startup migration to add container_id/slot columns to existing DB
- Extract createInventorySlot() for reuse by initial load and live deltas
- Add updateInventoryLive() handler for WebSocket inventory_delta messages
- Add inventory_delta case to browser WebSocket message dispatcher
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the AC stone-themed single-scroll character window with a TreeStats-
style tabbed interface. Two side-by-side tab containers: left (Attributes,
Skills, Titles) and right (Augmentations, Ratings, Other), plus an Allegiance
section below. Exact TreeStats color palette (#000022 bg, #af7a30 gold
borders, purple specialized, teal trained). Backend accepts new properties
and titles fields in character_stats message for JSONB storage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactor showStatsWindow, showInventoryWindow, and showChatWindow to use
a shared createWindow() helper that handles existence checks, z-index
management, header/close button creation, and makeDraggable setup. Each
function now only contains its unique content creation logic.
Added .window-content CSS class to style.css, style-ac.css, and the
christmas theme to maintain flex layout through the new wrapper div.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add POLL_RARES_MS, POLL_KILLS_MS, POLL_HEALTH_MS, NOTIFICATION_DURATION_MS,
GLOW_DURATION_MS, MAX_HEATMAP_POINTS, and HEATMAP_HOURS constants to replace
hardcoded values throughout script.js for better maintainability.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>