-- Server-authoritative movement: hero movement state + roads graph. -- Hero movement columns. ALTER TABLE heroes ADD COLUMN IF NOT EXISTS destination_town_id BIGINT REFERENCES towns(id); ALTER TABLE heroes ADD COLUMN IF NOT EXISTS current_town_id BIGINT REFERENCES towns(id); ALTER TABLE heroes ADD COLUMN IF NOT EXISTS move_state TEXT NOT NULL DEFAULT 'walking'; -- move_state: 'walking', 'resting', 'in_town', 'fighting', 'dead' -- Roads connect towns in a linear chain. CREATE TABLE IF NOT EXISTS roads ( id BIGSERIAL PRIMARY KEY, from_town_id BIGINT NOT NULL REFERENCES towns(id), to_town_id BIGINT NOT NULL REFERENCES towns(id), distance DOUBLE PRECISION NOT NULL, UNIQUE(from_town_id, to_town_id) ); -- Pre-computed waypoints along each road. CREATE TABLE IF NOT EXISTS road_waypoints ( id BIGSERIAL PRIMARY KEY, road_id BIGINT NOT NULL REFERENCES roads(id) ON DELETE CASCADE, seq INT NOT NULL, x DOUBLE PRECISION NOT NULL, y DOUBLE PRECISION NOT NULL, UNIQUE(road_id, seq) ); -- Seed roads between the 7 towns in order. -- Town positions (from 000006_quest_system.sql): -- Willowdale (50, 15) id=1 -- Thornwatch (200, 60) id=2 -- Ashengard (400, 120) id=3 -- Redcliff (650, 195) id=4 -- Boghollow (900, 270) id=5 -- Cinderkeep (1200, 360) id=6 -- Starfall (1550, 465) id=7 -- Forward roads (1->2, 2->3, ... 6->7). INSERT INTO roads (from_town_id, to_town_id, distance) VALUES (1, 2, 156.0), (2, 3, 210.0), (3, 4, 260.0), (4, 5, 260.0), (5, 6, 312.0), (6, 7, 365.0) ON CONFLICT DO NOTHING; -- Reverse roads (2->1, 3->2, ... 7->6). INSERT INTO roads (from_town_id, to_town_id, distance) VALUES (2, 1, 156.0), (3, 2, 210.0), (4, 3, 260.0), (5, 4, 260.0), (6, 5, 312.0), (7, 6, 365.0) ON CONFLICT DO NOTHING; -- Waypoints are generated at application startup via the RoadGraph loader -- using interpolation between town positions with jitter. This avoids -- storing thousands of rows and keeps generation deterministic per road seed.