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.
198 lines
10 KiB
SQL
198 lines
10 KiB
SQL
-- Migration 000006: Quest system — towns, NPCs, quests, hero quest tracking.
|
|
|
|
-- ============================================================
|
|
-- Towns: fixed settlements along the hero's travel road.
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS towns (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
name TEXT NOT NULL UNIQUE,
|
|
biome TEXT NOT NULL,
|
|
world_x DOUBLE PRECISION NOT NULL,
|
|
world_y DOUBLE PRECISION NOT NULL,
|
|
radius DOUBLE PRECISION NOT NULL DEFAULT 8.0,
|
|
level_min INT NOT NULL DEFAULT 1,
|
|
level_max INT NOT NULL DEFAULT 100,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
-- ============================================================
|
|
-- NPCs: non-hostile characters in towns.
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS npcs (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
town_id BIGINT NOT NULL REFERENCES towns(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
type TEXT NOT NULL CHECK (type IN ('quest_giver', 'merchant', 'healer')),
|
|
offset_x DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
offset_y DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_npcs_town ON npcs(town_id);
|
|
|
|
-- ============================================================
|
|
-- Quests: template definitions offered by quest-giver NPCs.
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS quests (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
npc_id BIGINT NOT NULL REFERENCES npcs(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
type TEXT NOT NULL CHECK (type IN ('kill_count', 'visit_town', 'collect_item')),
|
|
target_count INT NOT NULL DEFAULT 1,
|
|
target_enemy_type TEXT, -- NULL = any enemy (for kill_count)
|
|
target_town_id BIGINT REFERENCES towns(id), -- for visit_town quests
|
|
drop_chance DOUBLE PRECISION NOT NULL DEFAULT 0.3, -- for collect_item
|
|
min_level INT NOT NULL DEFAULT 1,
|
|
max_level INT NOT NULL DEFAULT 100,
|
|
reward_xp BIGINT NOT NULL DEFAULT 0,
|
|
reward_gold BIGINT NOT NULL DEFAULT 0,
|
|
reward_potions INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_quests_npc ON quests(npc_id);
|
|
|
|
-- ============================================================
|
|
-- Hero quests: per-hero progress tracking.
|
|
-- ============================================================
|
|
CREATE TABLE IF NOT EXISTS hero_quests (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
hero_id BIGINT NOT NULL REFERENCES heroes(id) ON DELETE CASCADE,
|
|
quest_id BIGINT NOT NULL REFERENCES quests(id) ON DELETE CASCADE,
|
|
status TEXT NOT NULL DEFAULT 'accepted'
|
|
CHECK (status IN ('accepted', 'completed', 'claimed')),
|
|
progress INT NOT NULL DEFAULT 0,
|
|
accepted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
completed_at TIMESTAMPTZ,
|
|
claimed_at TIMESTAMPTZ,
|
|
UNIQUE (hero_id, quest_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hero_quests_hero ON hero_quests(hero_id);
|
|
CREATE INDEX IF NOT EXISTS idx_hero_quests_status ON hero_quests(hero_id, status);
|
|
|
|
-- ============================================================
|
|
-- Seed data: towns
|
|
-- ============================================================
|
|
INSERT INTO towns (name, biome, world_x, world_y, radius, level_min, level_max) VALUES
|
|
('Willowdale', 'meadow', 50, 15, 8.0, 1, 5),
|
|
('Thornwatch', 'forest', 200, 60, 8.0, 5, 10),
|
|
('Ashengard', 'ruins', 400, 120, 8.0, 10, 16),
|
|
('Redcliff', 'canyon', 650, 195, 8.0, 16, 22),
|
|
('Boghollow', 'swamp', 900, 270, 8.0, 22, 28),
|
|
('Cinderkeep', 'volcanic', 1200, 360, 8.0, 28, 34),
|
|
('Starfall', 'astral', 1550, 465, 8.0, 34, 40);
|
|
|
|
-- ============================================================
|
|
-- Seed data: NPCs (2-3 per town)
|
|
-- ============================================================
|
|
INSERT INTO npcs (town_id, name, type, offset_x, offset_y) VALUES
|
|
-- Willowdale (meadow)
|
|
(1, 'Elder Maren', 'quest_giver', -2.0, 1.0),
|
|
(1, 'Peddler Finn', 'merchant', 3.0, 0.0),
|
|
(1, 'Sister Asha', 'healer', 0.0, -2.5),
|
|
-- Thornwatch (forest)
|
|
(2, 'Guard Halric', 'quest_giver', -3.0, 0.5),
|
|
(2, 'Trader Wynn', 'merchant', 2.0, 2.0),
|
|
-- Ashengard (ruins)
|
|
(3, 'Scholar Orin', 'quest_giver', 1.0, -2.0),
|
|
(3, 'Bone Merchant', 'merchant', -2.0, 3.0),
|
|
(3, 'Priestess Liora', 'healer', 3.0, 1.0),
|
|
-- Redcliff (canyon)
|
|
(4, 'Foreman Brak', 'quest_giver', -1.0, 2.0),
|
|
(4, 'Miner Supplies', 'merchant', 2.5, -1.0),
|
|
-- Boghollow (swamp)
|
|
(5, 'Witch Nessa', 'quest_giver', 0.0, 3.0),
|
|
(5, 'Swamp Trader', 'merchant', -3.0, -1.0),
|
|
(5, 'Marsh Healer Ren', 'healer', 2.0, 0.0),
|
|
-- Cinderkeep (volcanic)
|
|
(6, 'Forge-master Kael','quest_giver', -2.5, 0.0),
|
|
(6, 'Ember Merchant', 'merchant', 1.0, 2.5),
|
|
-- Starfall (astral)
|
|
(7, 'Seer Aelith', 'quest_giver', 0.0, -3.0),
|
|
(7, 'Void Trader', 'merchant', 3.0, 1.0),
|
|
(7, 'Astral Mender', 'healer', -2.0, 2.0);
|
|
|
|
-- ============================================================
|
|
-- Seed data: quests
|
|
-- ============================================================
|
|
|
|
-- Willowdale quests (Elder Maren, npc_id = 1)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(1, 'Wolf Cull',
|
|
'The wolves near Willowdale are getting bolder. Thin their numbers.',
|
|
'kill_count', 5, 'wolf', NULL, 0.0, 1, 5, 30, 15, 0),
|
|
(1, 'Boar Hunt',
|
|
'Wild boars are trampling the crops. Take care of them.',
|
|
'kill_count', 8, 'boar', NULL, 0.0, 2, 6, 50, 25, 1),
|
|
(1, 'Deliver to Thornwatch',
|
|
'Carry this supply manifest to Guard Halric in Thornwatch.',
|
|
'visit_town', 1, NULL, 2, 0.0, 1, 10, 40, 20, 0);
|
|
|
|
-- Thornwatch quests (Guard Halric, npc_id = 4)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(4, 'Spider Infestation',
|
|
'Cave spiders have overrun the logging trails. Clear them out.',
|
|
'kill_count', 12, 'spider', NULL, 0.0, 5, 10, 80, 40, 1),
|
|
(4, 'Spider Fang Collection',
|
|
'We need spider fangs for antivenom. Collect them from slain spiders.',
|
|
'collect_item', 5, 'spider', NULL, 0.3, 5, 10, 100, 60, 1),
|
|
(4, 'Forest Patrol',
|
|
'Slay any 15 creatures along the forest road to keep it safe.',
|
|
'kill_count', 15, NULL, NULL, 0.0, 5, 12, 120, 70, 1);
|
|
|
|
-- Ashengard quests (Scholar Orin, npc_id = 6)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(6, 'Undead Purge',
|
|
'The ruins are crawling with undead. Destroy the zombies.',
|
|
'kill_count', 15, 'zombie', NULL, 0.0, 10, 16, 150, 80, 1),
|
|
(6, 'Ancient Relics',
|
|
'Search fallen enemies for fragments of the old kingdom.',
|
|
'collect_item', 8, NULL, NULL, 0.25, 10, 16, 200, 120, 2),
|
|
(6, 'Report to Redcliff',
|
|
'Warn Foreman Brak about the growing undead threat.',
|
|
'visit_town', 1, NULL, 4, 0.0, 10, 20, 120, 60, 0);
|
|
|
|
-- Redcliff quests (Foreman Brak, npc_id = 9)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(9, 'Orc Raider Cleanup',
|
|
'Orc warriors are raiding the mine carts. Stop them.',
|
|
'kill_count', 20, 'orc', NULL, 0.0, 16, 22, 250, 150, 2),
|
|
(9, 'Ore Samples',
|
|
'Collect glowing ore fragments from defeated enemies near the canyon.',
|
|
'collect_item', 6, NULL, NULL, 0.3, 16, 22, 200, 120, 1);
|
|
|
|
-- Boghollow quests (Witch Nessa, npc_id = 11)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(11, 'Swamp Creatures',
|
|
'The swamp beasts grow more aggressive by the day. Cull 25.',
|
|
'kill_count', 25, NULL, NULL, 0.0, 22, 28, 350, 200, 2),
|
|
(11, 'Venomous Harvest',
|
|
'Collect venom sacs from swamp creatures for my brews.',
|
|
'collect_item', 10, NULL, NULL, 0.25, 22, 28, 400, 250, 2),
|
|
(11, 'Message to Cinderkeep',
|
|
'The forgemaster needs to know about the corruption spreading here.',
|
|
'visit_town', 1, NULL, 6, 0.0, 22, 34, 200, 100, 1);
|
|
|
|
-- Cinderkeep quests (Forge-master Kael, npc_id = 14)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(14, 'Demon Slayer',
|
|
'Fire demons are emerging from the vents. Destroy them.',
|
|
'kill_count', 10, 'fire_demon', NULL, 0.0, 28, 34, 500, 300, 2),
|
|
(14, 'Infernal Cores',
|
|
'Retrieve smoldering cores from defeated fire demons.',
|
|
'collect_item', 5, 'fire_demon', NULL, 0.3, 28, 34, 600, 350, 3);
|
|
|
|
-- Starfall quests (Seer Aelith, npc_id = 16)
|
|
INSERT INTO quests (npc_id, title, description, type, target_count, target_enemy_type, target_town_id, drop_chance, min_level, max_level, reward_xp, reward_gold, reward_potions) VALUES
|
|
(16, 'Titan''s Challenge',
|
|
'The Lightning Titans must be stopped before they breach the gate.',
|
|
'kill_count', 8, 'lightning_titan', NULL, 0.0, 34, 40, 800, 500, 3),
|
|
(16, 'Void Fragments',
|
|
'Gather crystallized void energy from the astral enemies.',
|
|
'collect_item', 8, NULL, NULL, 0.2, 34, 40, 1000, 600, 3),
|
|
(16, 'Full Circle',
|
|
'Return to Willowdale and tell Elder Maren of your journey.',
|
|
'visit_town', 1, NULL, 1, 0.0, 34, 40, 500, 300, 2);
|