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.

100 lines
4.3 KiB
SQL

-- Migration 000026: Town buildings — server-driven layout for towns.
-- Each NPC gets an assigned building; buildings have typed appearances per NPC role.
-- ============================================================
-- Town buildings: persistent structures placed in towns.
-- ============================================================
CREATE TABLE IF NOT EXISTS town_buildings (
id BIGSERIAL PRIMARY KEY,
town_id BIGINT NOT NULL REFERENCES towns(id) ON DELETE CASCADE,
building_type TEXT NOT NULL CHECK (building_type IN (
'house.quest_giver', 'house.merchant', 'house.healer',
'decoration.well', 'decoration.stall', 'decoration.signpost'
)),
offset_x DOUBLE PRECISION NOT NULL DEFAULT 0,
offset_y DOUBLE PRECISION NOT NULL DEFAULT 0,
facing TEXT NOT NULL DEFAULT 'south' CHECK (facing IN ('north','south','east','west')),
footprint_w DOUBLE PRECISION NOT NULL DEFAULT 2.0,
footprint_h DOUBLE PRECISION NOT NULL DEFAULT 2.0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_town_buildings_town ON town_buildings(town_id);
-- ============================================================
-- Link NPCs to their buildings (nullable for migration transition).
-- ============================================================
ALTER TABLE npcs ADD COLUMN IF NOT EXISTS building_id BIGINT REFERENCES town_buildings(id) ON DELETE SET NULL;
-- ============================================================
-- Seed buildings for all existing towns, then link NPCs.
-- Layout strategy per town:
-- - NPC buildings are placed in a semicircle around the town center
-- - quest_giver at ~10 o'clock, merchant at ~2 o'clock, healer at ~6 o'clock
-- - A well decoration at center, signpost near entrance
-- ============================================================
-- Helper: create buildings for each town with NPCs, using deterministic offsets by NPC type.
-- quest_giver houses: upper-left zone
-- merchant houses: upper-right zone
-- healer houses: lower-center zone
DO $$
DECLARE
t RECORD;
n RECORD;
new_building_id BIGINT;
btype TEXT;
ox DOUBLE PRECISION;
oy DOUBLE PRECISION;
npc_idx INTEGER;
BEGIN
FOR t IN SELECT id, radius FROM towns ORDER BY id LOOP
npc_idx := 0;
FOR n IN SELECT id, type FROM npcs WHERE town_id = t.id ORDER BY id LOOP
-- Determine building type from NPC type
btype := 'house.' || n.type;
-- Spread NPCs in a semicircle; scale offset by town radius
-- Each NPC gets a distinct angular position
CASE n.type
WHEN 'quest_giver' THEN
ox := -0.45 * t.radius;
oy := -0.25 * t.radius;
WHEN 'merchant' THEN
ox := 0.45 * t.radius;
oy := -0.25 * t.radius;
WHEN 'healer' THEN
ox := 0.0;
oy := 0.45 * t.radius;
ELSE
ox := npc_idx * 2.0;
oy := 0.0;
END CASE;
-- Stagger if multiple NPCs of same type (add small offset per index)
ox := ox + (npc_idx % 3) * 1.5;
INSERT INTO town_buildings (town_id, building_type, offset_x, offset_y, facing, footprint_w, footprint_h)
VALUES (t.id, btype, ox, oy, 'south', 2.5, 2.0)
RETURNING id INTO new_building_id;
-- Link NPC to their building
UPDATE npcs SET building_id = new_building_id WHERE id = n.id;
-- Move NPC offset to be at the building entrance (slightly in front)
UPDATE npcs SET offset_x = ox, offset_y = oy + 1.2 WHERE id = n.id;
npc_idx := npc_idx + 1;
END LOOP;
-- Add a well decoration at town center
INSERT INTO town_buildings (town_id, building_type, offset_x, offset_y, facing, footprint_w, footprint_h)
VALUES (t.id, 'decoration.well', 0, 0, 'south', 1.5, 1.5);
-- Add a signpost near the entrance (south edge)
INSERT INTO town_buildings (town_id, building_type, offset_x, offset_y, facing, footprint_w, footprint_h)
VALUES (t.id, 'decoration.signpost', 0, 0.6 * t.radius, 'south', 0.5, 0.5);
END LOOP;
END $$;