stepstead-backend/db/seed_quests.py
jts ea049b8ccd İlk commit: Stepstead backend (FastAPI)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:30:24 +03:00

617 lines
39 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Stepstead — Yan görev içeriği (2026-07-08).
WoW / Witcher tarzı ~90 yan görev + görev veren NPC'ler + yeni düşmanlar + görev itemleri.
Yapar (idempotent — tekrar çalıştırılabilir):
1. Görev veren NPC'ler (friendly/neutral) → şehir/kasaba/tapınak/maden map_tag'lerine.
2. Yeni düşmanlar (hostile NPC) → maden/tapınak/çorak/orman/çayır bölgelerine.
3. Görev itemleri → items tablosu. Toplanabilenler location_resources'a (oyun lokasyonu).
Düşmandan düşenler item olarak eklenir (drop düşman açıklamasında yazılı).
4. ~90 yan görev (quests) + adım adım hedefler (quest_objectives).
Seed işareti: quests.author='Görev Tohumu', npcs (giver) description sonuna [seed:quest].
Çalıştırma: cd /opt/stepstead && ./venv/bin/python3 db/seed_quests.py
"""
import asyncio
import sys
sys.path.insert(0, "/opt/stepstead")
import asyncpg # noqa: E402
from config import settings # noqa: E402
SEED_TAG = "Görev Tohumu"
GIVER_MARK = "[seed:quest-giver]"
def edesc(hp, dmg, atk, dc, weak, drops, danger, lore):
return (f"{lore}\n\n⚔ Saldırı türü: {atk}\n❤ Can (HP): {hp}\n🗡 Hasar: {dmg}\n"
f"🎯 Savaş zorluğu (combat DC): {dc}\n💀 Tehlike: {danger}\n"
f"🩹 Zayıflık: {weak}\n🎁 Düşürdükleri: {drops}")
# ─────────────────────────── GÖREV VERENLER ───────────────────────────
# (key, ad, rol, yer_adı[map_tags.name], açıklama)
GIVERS = [
("doran", "Kaptan Doran", "Kale Muhafızı", "Aethelguard Citadel",
"Aethelguard Kalesi'nin sert ama adil muhafız kaptanı. Bölgedeki tehditleri maceracılara havale eder."),
("lysa", "Rahibe Lysa", "Şifacı Rahibe", "Aethelguard Citadel",
"Kale mabedinin şefkatli rahibesi. Hastalara şifalı ot ve kutsal su lazım olur."),
("aldwin", "Tüccar Aldwin", "Tüccar", "Aethelguard Citadel",
"Zengin ama korkak bir tüccar. Kervanları eşkıyalardan çekmediği için sürekli yardım arar."),
("verena", "Simyacı Verena", "Simyacı", "Aethelguard Citadel",
"Meraklı bir simyacı; deneyleri için nadir salgı, zehir ve mantar ister."),
("orin", "Kütüphaneci Orin", "Bilgin", "Aethelguard Citadel",
"Kadim metinlerin peşindeki yaşlı bilgin. Harabelerdeki tabletleri ve tomarları toplatır."),
("bramble", "Hancı Bramble", "Hancı", "Riftwood Crossing",
"Riftwood Geçidi hanının gürültücü sahibi. Müşterileri için et, balık ve dedikodu toplar."),
("kael", "Avcı Ustası Kael", "Avcı Ustası", "Riftwood Crossing",
"Bölgenin en iyi izcisi. Çırak yetiştirir; canavar avı ve deri siparişleri verir."),
("sefa", "Kervan Lideri Sefa", "Kervancı", "Riftwood Crossing",
"Kıtalar arası mal taşıyan cesur kervancı. Yol güvenliği ve teslimat işleri dağıtır."),
("grungni", "Ustabaşı Grungni", "Maden Ustabaşı", "Rivenhaven",
"Rivenhaven madeninin huysuz ustabaşı. Madeni istila eden yaratıklardan ve göçüklerden bıkmış."),
("nadia", "Kâhin Nadia", "Kâhin", "T-1",
"Terk edilmiş tapınağın son kâhini. Huzursuz ölüleri ve bozulan mühürleri dert eder."),
("thariel", "Baş Rahip Thariel", "Baş Rahip", "T-2",
"ık tarikatının baş rahibi. Lanetli sunakları arındıracak ve kutsal emanetleri bulacak eller arar."),
("bram", "Orman Bekçisi Bram", "Korucu", "Whisperwood",
"Whisperwood'un yalnız koruyucusu. Ormanın dengesini bozan her şeyi izler."),
("elindra", "Elf İzci Elindra", "İzci", "Luminara Grove",
"Luminara'nın zarif elf izcisi. Kutsal ağaçları ve nadir çiçekleri korur."),
("morvath", "Münzevi Morvath", "Münzevi Büyücü", "Xylos Prime",
"Ormanın derininde yaşayan tuhaf büyücü. Reagent'ları karşılığında sırlar fısıldar."),
("thessa", "Thessa Mor", "Görev Veren", "Rivenhaven",
"Gizemli görev dağıtıcısı; kimin için çalıştığı belirsiz, ama altını gerçek."),
("garrick", "Nalbant Garrick", "Nalbant", "Riftwood Crossing",
"Kervan atlarına bakan güçlü kuvvetli nalbant. Demir ve kömür sıkıntısı çeker."),
("wystan", "Yaşlı Wystan", "Emekli Şövalye", "Aethelguard Citadel",
"Bir zamanlar ünlü bir şövalye; artık dizleri tutmuyor, işlerini gençlere yaptırıyor."),
("seline", "Balıı Seline", "Balıı Reisi", "Riftwood Crossing",
"Kıyı balıılarının sözü geçen reisi. Fırtına, korsan ve dev balık derdi hiç bitmez."),
]
# ─────────────────────────── YENİ DÜŞMANLAR ───────────────────────────
# (ad, rol, bölge_adı[map_tags.name], desc)
ENEMIES = [
# Maden
("Kobold Madenci", "Kobold", "Rivenhaven",
edesc(20, "5-9 (kazma)", "Yakın dövüş — sürü", 13, "Ateş, dar geçitte kıstırma",
"Kobold kulağı ×1-2, ham bakır, mum", "Orta",
"Madenin karanlık dehlizlerini istila eden küçük, aç gözlü kobold. Parlak her şeyi çalar.")),
("Taş Golemi", "Golem", "Rivenhaven",
edesc(70, "14-20 (yumruk)", "Yakın dövüş — ağır", 17, "Kazma (mining), keskin köşeler",
"Golem çekirdeği ×1, kristal parçası ×2-3", "Yüksek",
"Maden derinliklerinde biriken mananın canlandırdığı taş yığını. Yavaş ama ezici.")),
("Kör Mağara Trolü", "Trol", "M-1",
edesc(90, "16-24 (sopa)", "Yakın dövüş — öfke", 18, "Ateş, ışık (kör eder)",
"Trol derisi ×1-2, kemik sopa, iri diş", "Çok Yüksek",
"Gözleri körelmiş dev bir mağara trolü. Sesi ve kokuyu takip eder; ateşten deliye döner.")),
("Derin Örümcek", "Dev Örümcek", "M-2",
edesc(28, "7-12 (zehir)", "Yakın dövüş — zehirli", 14, "Ateş, geniş alan",
"Örümcek zehir kesesi ×1-2, ipek", "Orta-Yüksek",
"Mağaranın dibinde ağ ören, at büyüklüğünde solgun örümcek. Zehri felç eder.")),
# Tapınak / undead
("Huzursuz İskelet", "Hortlak", "T-1",
edesc(24, "6-10 (paslı kılıç)", "Yakın dövüş", 13, "Kutsal su, kör (blunt) silah",
"İskelet kemiği ×1-2, paslı madeni para", "Orta",
"Mühür bozulunca uyanan eski muhafız iskeletleri. Kutsal su karşısında dağılır.")),
("Lanetli Rahip Hayaleti", "Hayalet (Elit)", "T-2",
edesc(60, "12-18 (mana lanet)", "Büyü — lanet + korku", 17, "Kutsal emanet, ışık büyüsü",
"Hayalet ektoplazması ×1-2, lanetli tomar", "Yüksek",
"Tapınağı ihanetle lekeleyen rahibin huzursuz ruhu. Sunak arındırılmadan yok edilemez.")),
("Taş Bekçi Heykeli", "Muhafız Golem", "T-2",
edesc(80, "15-22 (balyoz kol)", "Yakın dövüş — ağır", 18, "Kazma, çekirdeğini kırmak",
"Kutsal taş ×2, golem çekirdeği ×1", "Yüksek",
"Tapınağı bekleyen kadim heykel. Yabancıyı kutsal alanda görünce canlanır.")),
# Çorak (B-1 wasteland)
("Çorak Hortlağı", "Zombi", "B-1",
edesc(30, "7-11 (pençe)", "Yakın dövüş — hastalık", 14, "Ateş, kafa darbesi",
"Çürük et, kayıp madalyon (nadir)", "Orta",
"Çorak toprakta sürünen, hastalık saçan cesetler. Yavaş ama kalabalık gelir.")),
("Kum Solucanı", "Dev Solucan", "B-1",
edesc(75, "14-20 (yutma)", "Pusu — yer altından", 17, "Titreşimden kaçınmak, ateş",
"Kum solucanı dişi ×1-2, kristalize tuz", "Çok Yüksek",
"Çorak kumun altında bekleyen kör dev solucan. Ayak sesini duyunca patlarcasına fırlar.")),
("Leş Akbabası", "Uçan Yırtıcı", "B-1",
edesc(22, "6-9 (gaga)", "Havadan dalış", 13, "Ok/yay, yüksek zemin",
"Akbaba gagası, tüy demeti", "Orta",
"Çorakta leş kokusunu kilometrelerce öteden alan iri akbaba. Zayıfı seçer.")),
("Gölge İblisi", "İblis (Elit)", "B-1",
edesc(95, "18-26 (kara alev)", "Büyü — kara alev + korku", 19, "Kutsal emanet, ışık",
"İblis boynuzu ×1, kükürt, kara kristal", "Ölümcül",
"Yarıktan sızan alt-düzey iblis. Gölgeden gölgeye atlar, dokunduğunu yakar.")),
# Çayır / genel
("Yaban Domuzu Reisi", "Canavar (Elit)", "Solstice Mire",
edesc(50, "11-16 (azı dişi)", "Hücum — boynuzlama", 15, "Tuzak, mızrak",
"Domuz dişi ×1-2, kalın deri, yaban eti", "Orta-Yüksek",
"Sürünün yaşlı, yaralı ama azgın reisi. Hücumu ağaç deviren güçtedir.")),
("Dağ Ayısı", "Canavar (Elit)", "Emberfall",
edesc(65, "13-19 (pençe)", "Yakın dövüş — pençe+ısırık", 16, "Ateş, mesafe",
"Ayı pençesi ×1-2, kalın post, bal", "Yüksek",
"İninden erken uyanmış huysuz bir bozayı. Toprağını savunurken acımasızdır.")),
("Bataklık Harpisi", "Harpi", "Solstice Mire",
edesc(34, "8-13 (pençe dalış)", "Havadan taciz + çığlık", 15, "Ok/yay, ağ",
"Harpi tüyü ×1-2, çalınmış mücevher", "Orta-Yüksek",
"Bataklık üstünde çığlıklarla uçan yarı kuş yaratık. Parlak eşya için saldırır.")),
("Vahşi Şaman Goblin", "Goblin Büyücü", "Rivenwood",
edesc(40, "9-14 (şok totemi)", "Büyü — totem + şimşek", 15, "Totemini kırmak, hızlı baskın",
"Goblin kulağı ×2, totem parçası, garip iksir", "Orta-Yüksek",
"Goblin çetesini totemleriyle güçlendiren sinsi şaman. Önce totemi düşmeli.")),
("Gulyabani", "Yamyam Yaratık", "Xylos Prime",
edesc(45, "10-15 (tırnak)", "Pusu — karanlıktan", 16, "Ateş meşalesi, ışık",
"Solgun et, mezar tozu, kayıp yüzük", "Yüksek",
"Karanlık ormanda mezarları eşen soluk benizli yamyam. Işıktan tiksinir.")),
("Orman Şeytanı (Leshy)", "Bitki Ruhu (Elit)", "Ironbark Reach",
edesc(85, "15-22 (kök kırbaç)", "Yakın dövüş + köklerle bağlama", 18, "Ateş, gümüş balta",
"Kadim meşe özü ×2, canlı kök, uğur boncuğu", "Çok Yüksek",
"Ormanın öfkeli koruyucu ruhu. Witcher masalındaki gibi kurbanlarını köklerle sarar.")),
("Su Cini (Vodyanoy)", "Su Canavarı", "Aetherbloom",
edesc(48, "10-15 (pençe)", "Sudan pusu", 16, "Kuru zemine çekmek, ateş",
"Pullu deri, inci, sülük salgısı", "Orta-Yüksek",
"Gölet ve derelerde pusuya yatan pullu su cini. Balııları suya çeker.")),
]
# ─────────────────────────── GÖREV İTEMLERİ ───────────────────────────
# type: material (çoğu). gather_loc: oyun lokasyonu code'u (varsa location_resources'a eklenir), None=sadece drop.
# (code, ad, rarity, gather_loc, skill, step, xp, açıklama)
QITEMS = [
# Toplanabilir reagent'lar
("herb_healroot", "Şifalı Kök", "common", "fisilti_ormani", "foraging", 5, 9, "Rahibe Lysa'nın merhemleri için kök."),
("herb_moonflower", "Ay Çiçeği", "uncommon", "cayirlar", "foraging", 6, 12, "Sadece dolunayda açan soluk mavi çiçek."),
("herb_bluecap", "Mavi Mantar", "common", "kadim_orman", "foraging", 5, 9, "Nemli kütüklerde biten mavi şapkalı mantar."),
("mat_wildhoney", "Yaban Balı", "uncommon", "akca_koru", "foraging", 7, 13, "Vahşi arı kovanından çıkarılan koyu bal."),
("mat_crystal", "Kristal Parçası", "uncommon", "derin_maden", "mining", 7, 13, "Maden derinliğinde parıldayan ham kristal."),
("mat_ironslag", "Demir Cürufu", "common", "tas_ocagi", "mining", 5, 9, "Eritme artığı; nalbantın işine yarar."),
("mat_pearlshell", "İnci Kabuğu", "uncommon", "aynali_gol", "fishing", 6, 12, "İçinde bazen inci taşıyan sedefli kabuk."),
("mat_holywater", "Kutsal Su", "rare", "firtina_kiyisi", "fishing", 8, 16, "Kutsanmış kaynaktan alınan berrak su."),
("mat_ancientoak", "Kadim Meşe Özü", "rare", "kadim_orman", "woodcutting", 8, 16, "Yüzyıllık meşenin sızan özü; büyüde güçlüdür."),
("mat_salt", "Kristalize Tuz", "common", "firtina_kiyisi", "foraging", 5, 9, "Kıyı kayalarında biriken tuz kristali."),
# Sadece drop / bulunacak eşyalar
("q_wolf_fang", "Kurt Dişi", "common", None, None, 0, 0, "Kurt sürülerinden toplanan sivri diş."),
("q_spider_venom", "Örümcek Zehir Kesesi", "uncommon", None, None, 0, 0, "Dev örümceklerden alınan zehir kesesi."),
("q_kobold_ear", "Kobold Kulağı", "common", None, None, 0, 0, "Kobold avının kanıtı."),
("q_skeleton_bone", "İskelet Kemiği", "common", None, None, 0, 0, "Huzursuz ölülerden kalan kemik."),
("q_golem_core", "Golem Çekirdeği", "rare", None, None, 0, 0, "Golemi çalıştıran manalı taş çekirdek."),
("q_ectoplasm", "Hayalet Ektoplazması", "rare", None, None, 0, 0, "Hayaletten sızan titreşen madde."),
("q_harpy_feather", "Harpi Tüyü", "uncommon", None, None, 0, 0, "Bataklık harpisinin keskin tüyü."),
("q_bear_claw", "Ayı Pençesi", "uncommon", None, None, 0, 0, "Dağ ayısının kavisli pençesi."),
("q_goblin_ear", "Goblin Kulağı", "common", None, None, 0, 0, "Goblin çetesi avının kanıtı."),
("q_troll_hide", "Trol Derisi", "rare", None, None, 0, 0, "Kalın, ok geçirmez trol derisi."),
("q_demon_horn", "İblis Boynuzu", "epic", None, None, 0, 0, "Gölge iblisinden koparılan kara boynuz."),
("q_worm_tooth", "Kum Solucanı Dişi", "rare", None, None, 0, 0, "Kum solucanının testere gibi dişi."),
("q_boar_tusk", "Domuz Dişi", "common", None, None, 0, 0, "Yaban domuzu reisinin azı dişi."),
("q_leech_slime", "Sülük Salgısı", "common", None, None, 0, 0, "Bataklık sülüğünden alınan yapışkan salgı."),
("q_medallion", "Kayıp Madalyon", "rare", None, None, 0, 0, "Bir soylunun kayıp aile madalyonu."),
("q_ancient_tablet","Kadim Tablet", "rare", None, None, 0, 0, "Eski bir dille yazılı taş tablet."),
("q_cursed_scroll", "Lanetli Tomar", "rare", None, None, 0, 0, "Karanlık büyü içeren mühürlü tomar."),
("q_holy_relic", "Kutsal Emanet", "epic", None, None, 0, 0, "ık tarikatının kayıp kutsal emaneti."),
("q_lost_ring", "Kayıp Yüzük", "uncommon", None, None, 0, 0, "Bir maceracının mezardan çıkan yüzüğü."),
("q_totem_shard", "Totem Parçası", "common", None, None, 0, 0, "Goblin şamanın kırık totemi."),
]
# ─────────────────────────── YAN GÖREVLER ───────────────────────────
# (başlık, giver_key, bölge_adı[map_tags.name] veya None, özet, [hedef notları])
QUESTS = [
# ── Kaptan Doran — bounty / güvenlik ──
("Kurt Belası", "doran", "Veridian Glade",
"Aç kurtlar kale yollarına inmeye başladı. Doran onları seyrekleştirmeni istiyor.",
["Veridian Glade'de 6 Aç Kurt öldür.", "Kanıt olarak 4 Kurt Dişi topla.", "Kaptan Doran'a dön."]),
("Örümcek Yuvası", "doran", "Luminara Grove",
"Zehirli örümcekler bir tüccarı zehirledi. Yuvayı temizle.",
["Luminara Grove'da 5 Zehirli Orman Örümceği öldür.", "3 Örümcek Zehir Kesesi getir."]),
("Haydut Tehdidi", "doran", "Solstice Mire",
"Orman haydutları kervan yolunu kesiyor. Reisleri bir ders almalı.",
["Solstice Mire'da 5 Orman Haydutu öldür.", "Çaldıkları keseyi geri al.", "Doran'a bildir."]),
("Gölge Kurdu Avı", "doran", "Emberfall",
"Bir alfa kurt sürüsü kontrolden çıkardı. Elit hedefi indir.",
["Emberfall'da Gölge Kurdu (Alfa)'yı öldür.", "Postunu kanıt getir."]),
("Kanatlı Bela", "doran", "Xylos Prime",
"Kanlı yarasalar geceleri nöbetçilere saldırıyor.",
["Xylos Prime'da 8 Kanlı Yarasa öldür.", "5 Yarasa Kanadı topla."]),
("Karga Laneti", "doran", "Veridian Glade",
"Lanetli bir karga sürüsü tarlaları talan ediyor; uğursuzluk saçıyorlar.",
["Lanetli Karga Sürüsü'nü dağıt.", "Lanetli boncuğu Rahibe Lysa'ya götür."]),
# ── Rahibe Lysa — şifa / topla ──
("Merhem İçin Kök", "lysa", "Fısıltı Ormanı",
"Revirdeki yaralılar için şifalı kök tükendi.",
["Fısıltı Ormanı'nda 8 Şifalı Kök topla.", "Rahibe Lysa'ya teslim et."]),
("Dolunay Çiçeği", "lysa", None,
"Ateşi düşmeyen bir çocuk için nadir ay çiçeği gerek.",
["Uçsuz Çayırlar'da 6 Ay Çiçeği topla.", "Lysa'ya getir."]),
("Kutsal Su Seferi", "lysa", None,
"Vaftiz ayini için kutsanmış kaynak suyu lazım.",
["Fırtına Kıyısı'ndan 4 Kutsal Su al.", "Mabede götür."]),
("Salgın Durdurulmalı", "lysa", "B-1",
"Çorak topraktan gelen hortlaklar hastalık yayıyor; kaynağı azalt.",
["Çorak Hortlağı'ndan 6 öldür.", "5 Mavi Mantar topla (panzehir için).", "Lysa'ya dön."]),
("Arı Kovanı Riski", "lysa", None,
"Yaralı yanıkları için yaban balı gerekiyor ama kovanlar tehlikeli.",
["Akça Koru'dan 5 Yaban Balı topla.", "Lysa'ya teslim et."]),
# ── Tüccar Aldwin — teslimat / eskort ──
("Kervan Koruması", "aldwin", "Solstice Mire",
"Aldwin'in kervanı bataklıktan geçerken haydut korkusu içinde.",
["Kervan yolundaki 4 Orman Haydutu'nu temizle.", "Aldwin'e güvenli yolu bildir."]),
("Kayıp Sevkiyat", "aldwin", "Rivenwood",
"Bir yük arabası devrildi, mallar ormana saçıldı.",
["Rivenwood'da 5 kayıp sandığı bul (araştır).", "Goblinlerin çaldığını Aldwin'e söyle."]),
("Değerli Teslimat", "aldwin", "Riftwood Crossing",
"Kırılgan bir sipariş Riftwood'a ulaştırılmalı.",
["Paketi Hancı Bramble'a götür.", "İmzalı makbuzu Aldwin'e geri getir."]),
("Borçlu Kaçtı", "aldwin", "Karaağaç Karanlığı",
"Aldwin'e borçlu bir adam karanlık ormana kaçmış.",
["Karaağaç Karanlığı'nda borçluyu bul.", "Ya altını ya sözünü Aldwin'e getir."]),
("Rakip Casusu", "aldwin", "Aethelguard Citadel",
"Aldwin rakip bir tüccarın kendisini gözetlediğinden şüpheleniyor.",
["Kalede casusu takip et (araştır).", "Bulguları Aldwin'e ilet."]),
# ── Simyacı Verena — reagent ──
("Zehir Deneyi", "verena", "Luminara Grove",
"Verena panzehir formülü için taze örümcek zehri istiyor.",
["4 Örümcek Zehir Kesesi topla.", "Verena'ya getir."]),
("Mantar Koleksiyonu", "verena", "Kadim Orman",
"Nadir mavi mantarlar bir iksirin anahtarı.",
["Kadim Orman'da 10 Mavi Mantar topla.", "Verena'nın laboratuvarına bırak."]),
("Kristalin Sırrı", "verena", "Rivenhaven",
"Verena maden kristalinin manasını incelemek istiyor.",
["Derin Maden'den 6 Kristal Parçası çıkar.", "Verena'ya teslim et."]),
("Ektoplazma Örneği", "verena", "T-2",
"Hayalet maddesi Verena'nın en riskli deneyi için gerekli.",
["Lanetli Rahip Hayaleti'nden 2 Hayalet Ektoplazması al.", "Kırılmadan Verena'ya götür."]),
("Sülük Salgısı", "verena", "Slyvandor",
"Yapışkan sülük salgısı yeni bir yara bandı denemesi için.",
["Bataklık Sülüğü'nden 5 Sülük Salgısı topla.", "Verena'ya ver."]),
("İblis Kükürdü", "verena", "B-1",
"Verena tehlikeli bir simya için iblis boynuzu tozu istiyor — delilik mi cesaret mi?",
["Gölge İblisi'nden 1 İblis Boynuzu al.", "Verena'ya teslim et (dikkatli!)."]),
# ── Kütüphaneci Orin — araştır / kadim ──
("Kayıp Tabletler", "orin", "M-1",
"Orin mağara duvarlarındaki kadim yazıtları istiyor.",
["M-1 mağarasında 3 Kadim Tablet bul.", "Orin'e getir."]),
("Yasak Tomar", "orin", "T-1",
"Tapınak arşivinde lanetli bir tomar saklı; Orin onu güvenle incelemek istiyor.",
["Huzursuz İskeletleri geçip 1 Lanetli Tomar al.", "Orin'e teslim et."]),
("Harabelerin Sırrı", "orin", "Rivenhaven",
"Madende eski bir uygarlığın izleri var.",
["Rivenhaven'da 4 oyma taş incele (araştır).", "Çizimleri Orin'e ver."]),
("Kadim Meşenin Bilgeliği", "orin", "Kadim Orman",
"Orin kadim meşe özünün büyülü kaydını çözmek istiyor.",
["3 Kadim Meşe Özü topla.", "Orin'in masasına bırak."]),
("Kayıp Günlük", "orin", "Whisperwood",
"Kaybolan bir kaşifin günlüğü ormanda bir yerlerde.",
["Whisperwood'da kaşifin kampını bul (araştır).", "Günlüğü Orin'e getir."]),
# ── Hancı Bramble — yemek / dedikodu ──
("Han Mutfağı: Et", "bramble", "Av Toprakları",
"Han için taze yaban eti lazım.",
["Av Toprakları'nda avlan, 8 yaban eti getir.", "Bramble'a teslim et."]),
("Han Mutfağı: Balık", "bramble", None,
"Cuma ziyafeti için taze balık gerek.",
["Aynalı Göl'de 10 balık tut.", "Bramble'a getir."]),
("Bal Likörü", "bramble", "Akça Koru",
"Bramble'ın meşhur bal likörü için yaban balı bitti.",
["6 Yaban Balı topla.", "Bramble'a ver."]),
("Fıçı Baskını", "bramble", "Rivenwood",
"Goblinler han fıçılarını çaldı!",
["Rivenwood'da 4 Orman Haydutu/Goblin öldür.", "Çalınan fıçıyı geri getir."]),
("Dedikodu Toplayıcı", "bramble", "Riftwood Crossing",
"Bramble kasabadaki söylentileri merak ediyor.",
["3 kasabalıyla konuş (araştır).", "Duyduklarını Bramble'a anlat."]),
# ── Avcı Ustası Kael — av / deri ──
("Çırak Sınavı: Tavşan", "kael", "Av Toprakları",
"Kael'in çırağı olmak için önce mütevazı bir avla başla.",
["Av Toprakları'nda 6 tavşan avla.", "6 tavşan derisi getir."]),
("Reis Domuz", "kael", "Solstice Mire",
"Yaban domuzu reisi bir avcıyı yaraladı; onu indir.",
["Yaban Domuzu Reisi'ni öldür.", "2 Domuz Dişi getir."]),
("Ayı Sorunu", "kael", "Emberfall",
"Erken uyanan bir dağ ayısı avlanma alanını basıyor.",
["Dağ Ayısı'nı öldür.", "Ayı Pençesi ve postu Kael'e getir."]),
("Kaliteli Deri Siparişi", "kael", "Av Toprakları",
"Bir zırhçı için kalın deri gerekiyor.",
["Geyik avla, 8 geyik derisi topla.", "Kael'e teslim et."]),
("Harpi Tehdidi", "kael", "Solstice Mire",
"Bataklık harpileri avcıların tuzaklarını yağmalıyor.",
["3 Bataklık Harpisi öldür.", "4 Harpi Tüyü getir."]),
("Kaçak Yavru", "kael", "Whisperwood",
"Nadir bir geyik yavrusu sürüden ayrı düşmüş; kurtlardan önce bul.",
["Whisperwood'da yavruyu bul (araştır).", "Güvenle Kael'e getir."]),
# ── Kervan Lideri Sefa — yol / teslimat ──
("Yol Temizliği", "sefa", "Ironbark Reach",
"Sefa'nın rotasını sarmaşık cinleri kapatmış.",
["Ironbark Reach'te 4 Sarmaşık Cini öldür.", "Yolu Sefa'ya rapor et."]),
("Kıtalar Arası Paket", "sefa", "Riftwood Crossing",
"Meridia'ya gidecek hassas bir paket koruma istiyor.",
["Paketi limana kadar koru (eskort).", "Sefa'ya teslim onayını getir."]),
("Kayıp Kervancı", "sefa", "Karaağaç Karanlığı",
"Sefa'nın bir adamı karanlık ormanda kayıp.",
["Karaağaç Karanlığı'nda kervancıyı ara (araştır).", "Gulyabani tehdidini temizle.", "Adamı geri getir."]),
("Nal Sevkiyatı", "sefa", "Riftwood Crossing",
"Nalbant Garrick'e demir cürufu ulaştırılmalı.",
["Taş Ocağı'ndan 8 Demir Cürufu topla.", "Garrick'e teslim et."]),
("Korsan Uyarısı", "sefa", None,
"Kıyıda korsan görüldü; Sefa deniz rotasını merak ediyor.",
["Fırtına Kıyısı'nı gözle (araştır).", "Seline ile konuş.", "Sefa'ya bildir."]),
# ── Ustabaşı Grungni — maden ──
("Kobold İstilası", "grungni", "Rivenhaven",
"Kobold sürüsü madenin alt katını ele geçirdi.",
["Rivenhaven'da 8 Kobold Madenci öldür.", "6 Kobold Kulağı getir."]),
("Taştan Bela", "grungni", "Rivenhaven",
"Bir taş golemi maden geçidini tıkadı.",
["Taş Golemi'ni parçala.", "Golem Çekirdeği'ni Grungni'ye getir."]),
("Göçük Kurtarması", "grungni", "Rivenhaven",
"Göçük altında kalan madenciler var.",
["3 madenciyi kazıp çıkar (araştır).", "Güvenli çıkışı Grungni'ye bildir."]),
("Kristal Kotası", "grungni", "Derin Maden",
"Kalenin siparişi için kristal çıkarılmalı.",
["Derin Maden'den 10 Kristal Parçası çıkar.", "Grungni'ye teslim et."]),
("Derindeki Örümcek", "grungni", "M-2",
"En alt galeride dev bir örümcek yuva kurmuş.",
["Derin Örümcek'i öldür.", "Yuvayı yak.", "Grungni'ye haber ver."]),
("Kör Trol", "grungni", "M-1",
"Kör bir mağara trolü madencileri dehşete düşürüyor.",
["Kör Mağara Trolü'nü indir.", "Trol Derisi'ni kanıt getir."]),
# ── Kâhin Nadia — tapınak/undead ──
("Huzursuz Ölüler", "nadia", "T-1",
"Tapınak mührü zayıfladı, iskeletler uyandı.",
["T-1'de 8 Huzursuz İskelet dağıt.", "6 İskelet Kemiği topla."]),
("Mührü Onar", "nadia", "T-1",
"Kırık mühür yeniden çizilmeli.",
["3 Kutsal Su getir.", "Sunakta ritüeli tamamla.", "Nadia'ya bildir."]),
("Kayıp Kâhin", "nadia", "M-1",
"Nadia'nın çırağı kehanet ararken mağarada kaybolmuş.",
["M-1'de çırağı bul (araştır).", "Sağ salim Nadia'ya getir."]),
("Kehanet Tableti", "nadia", "M-2",
"Bir kehanet kadim bir tablete kazınmış.",
["M-2'de 2 Kadim Tablet bul.", "Nadia'ya oku."]),
# ── Baş Rahip Thariel — kutsal ──
("Lanetli Sunak", "thariel", "T-2",
"İhanetle lekelenen sunak arındırılmalı.",
["Lanetli Rahip Hayaleti'ni yok et.", "Sunağı kutsal su ile arındır.", "Thariel'e dön."]),
("Kutsal Emanet", "thariel", "T-2",
"Tarikatın kutsal emaneti yağmalanmış, izini sür.",
["Taş Bekçi Heykeli'ni geç.", "1 Kutsal Emanet'i geri al.", "Thariel'e teslim et."]),
("Karanlığı Kov", "thariel", "B-1",
"Çorak topraktan yayılan karanlık tapınağı tehdit ediyor.",
["B-1'de 1 Gölge İblisi'ni kov.", "İblis Boynuzu'nu mühürle.", "Thariel'e getir."]),
("Kutsal Su Kuyusu", "thariel", None,
"Mabet kuyusu kurudu; kutsanacak temiz su gerek.",
["Fırtına Kıyısı'ndan 6 Kutsal Su getir.", "Thariel kutsayacak."]),
("Hac Yolu Güvenliği", "thariel", "T-1",
"Hacılar huzursuz ölülerden korkuyor.",
["T-1 yolundaki 6 Huzursuz İskelet'i temizle.", "Thariel'e güvenli yolu bildir."]),
# ── Orman Bekçisi Bram — orman dengesi ──
("Ormanın Dengesi", "bram", "Whisperwood",
"Yaşlı Ağaç Adam öfkelenip yolcuları eziyor; sakinleştir ya da indir.",
["Whisperwood'da Yaşlı Ağaç Adam'ı yatıştır ya da öldür.", "Bram'a bildir."]),
("Spor Salgını", "bram", "Rivenwood",
"Mantar spor yaratıkları ormanı zehirliyor.",
["Rivenwood'da 6 Mantar Spor Yaratığı öldür.", "Zehirli sporları yak."]),
("Kaçak Ateş", "bram", "Emberfall",
"Emberfall'da kontrolsüz bir yangın çıkabilir; kaynağı bul.",
["Emberfall'da yangın izini araştır.", "Bram'a raporla."]),
("Leshy Uyanışı", "bram", "Ironbark Reach",
"Bir orman şeytanı (Leshy) uyanmış; Witcher misali onu alt et.",
["Ironbark Reach'te Orman Şeytanı (Leshy)'yi öldür.", "Kadim Meşe Özü'nü Bram'a getir."]),
("Fare İstilası", "bram", "Aetherbloom",
"Dev orman fareleri ağaç köklerini kemiriyor.",
["Aetherbloom'da 8 Dev Orman Faresi öldür.", "Bram'a bildir."]),
# ── Elf İzci Elindra — nadir doğa ──
("Ay Çiçeği Kutsaması", "elindra", None,
"Elindra'nın ritüeli için el değmemiş ay çiçekleri gerek.",
["Uçsuz Çayırlar'da 8 Ay Çiçeği topla.", "Elindra'ya getir."]),
("Kutsal Ağaç Bekçisi", "elindra", "Luminara Grove",
"Örümcekler kutsal ağaca ağ örüyor.",
["Luminara Grove'da 6 Zehirli Orman Örümceği öldür.", "Ağacı temizle."]),
("İnci Gözyaşı", "elindra", None,
"Elindra'nın kolyesi için berrak bir göl incisi gerek.",
["Aynalı Göl'de 5 İnci Kabuğu topla.", "Elindra'ya ver."]),
("Su Cini Tehdidi", "elindra", "Aetherbloom",
"Bir su cini derenin balıklarını ve balııları yutuyor.",
["Aetherbloom'da Su Cini (Vodyanoy)'u öldür.", "Elindra'ya haber ver."]),
# ── Münzevi Morvath — gizemli reagent ──
("Reagent Toplayıcı", "morvath", "Xylos Prime",
"Morvath büyüsü için üç farklı reagent istiyor.",
["4 Kadim Meşe Özü, 4 Mavi Mantar, 4 Kristal Parçası getir.", "Morvath'a ver."]),
("Kara Tomarın Peşinde", "morvath", "T-1",
"Morvath yasak bilgi için lanetli bir tomar istiyor.",
["T-1'den 1 Lanetli Tomar al.", "Morvath'a gizlice getir."]),
("Gölge Özü", "morvath", "B-1",
"Morvath karanlık bir deney için iblis maddesi arıyor.",
["Gölge İblisi'nden 1 İblis Boynuzu al.", "Morvath'a teslim et."]),
("Totem Kırıcı", "morvath", "Rivenwood",
"Vahşi şaman goblin Morvath'ın çizdiği sınırı bozuyor.",
["Vahşi Şaman Goblin'i öldür.", "2 Totem Parçası getir."]),
# ── Thessa Mor — gizemli / karışık ──
("Kayıp Madalyon", "thessa", "B-1",
"Thessa bir soylunun kayıp madalyonunu istiyor; nedenini söylemiyor.",
["Çorak Hortlağı'ndan 1 Kayıp Madalyon düşür.", "Thessa'ya getir."]),
("Mezar Yüzüğü", "thessa", "Karaağaç Karanlığı",
"Bir maceracının yüzüğü gulyabaninin ininde.",
["Gulyabani'yi öldür.", "1 Kayıp Yüzük al.", "Thessa'ya teslim et."]),
("İsimsiz İş", "thessa", "M-2",
"Thessa mağaranın dibinden bir şey getirmeni istiyor — soru sorma.",
["M-2'de gizli sandığı bul (araştır).", "Açmadan Thessa'ya getir."]),
("Sessiz Tanık", "thessa", "Rivenhaven",
"Bir olaya tanık olan madenci ortadan kaybolmuş.",
["Rivenhaven'da tanığı ara (araştır).", "Bulguları Thessa'ya fısılda."]),
("Kum Altındaki Sır", "thessa", "B-1",
"Çorakta bir şey gömülü; kum solucanı üstünde bekliyor.",
["Kum Solucanı'nı öldür.", "1 Kum Solucanı Dişi ve gömülü kutuyu getir."]),
# ── Nalbant Garrick — demir/kömür ──
("Demir Cürufu Lazım", "garrick", "Taş Ocağı",
"Garrick'in nal ocağı için cüruf tükendi.",
["Taş Ocağı'ndan 10 Demir Cürufu topla.", "Garrick'e getir."]),
("At Nalı Siparişi", "garrick", "Riftwood Crossing",
"Kervan atları için toplu nal gerek; malzeme topla.",
["6 Demir Cürufu ve 3 bakır külçe getir.", "Garrick'e teslim et."]),
("Kayıp Örs", "garrick", "Rivenwood",
"Garrick'in kıymetli örsü çalınmış — goblin işi.",
["Rivenwood'da goblin kampını bul (araştır).", "Örsü geri getir."]),
# ── Yaşlı Wystan — nostalji / bounty ──
("Eski Kılıcım", "wystan", "M-1",
"Wystan gençliğinin kılıcını bir mağarada bırakmış.",
["M-1'de eski kılıcı bul (araştır).", "Wystan'a getir."]),
("Son Bir Av", "wystan", "Emberfall",
"Wystan bir kez daha büyük bir av görmek istiyor; onun adına indir.",
["Dağ Ayısı'nı öldür.", "Postu Wystan'a göster."]),
("Şövalyenin Onuru", "wystan", "B-1",
"Wystan'ı yenen iblis hâlâ çorakta; intikamını al.",
["Gölge İblisi'ni öldür.", "İblis Boynuzu'nu Wystan'a getir."]),
("Zırhımı Onar", "wystan", "Taş Ocağı",
"Wystan'ın eski zırhı için metal gerek.",
["Taş Ocağı'ndan 8 Demir Cürufu topla.", "Bir demirciye onartıp Wystan'a getir."]),
# ── Balıı Seline — deniz/göl ──
("Fırtına Avı", "seline", None,
"Fırtına öncesi balık sürüsü kıyıya yaklaştı.",
["Fırtına Kıyısı'nda 12 balık tut.", "Seline'ye getir."]),
("İnci Dalışı", "seline", None,
"Seline'nin borcu için değerli inci gerek.",
["Aynalı Göl'de 8 İnci Kabuğu topla.", "Seline'ye ver."]),
("Dev Balık Efsanesi", "seline", None,
"Gölde efsanevi bir balık görülmüş; kanıt getir.",
["Aynalı Göl'ü araştır.", "Efsane balığı yakala.", "Seline'ye göster."]),
("Korsan Kampı", "seline", "B-1",
"Kıyı korsanları balıı ağlarını yağmalıyor.",
["Kıyıdaki 4 haydudu/korsanı temizle.", "Seline'ye bildir."]),
("Sülük Bela", "seline", "Slyvandor",
"Bataklık sülükleri balık ağlarına doluşuyor.",
["Slyvandor'da 6 Bataklık Sülüğü öldür.", "5 Sülük Salgısı Verena için topla."]),
# ── Ek karışık (dünya doldurma) ──
("Tuz Toplayıcı", "bramble", None,
"Han'ın eti kürlemek için tuza ihtiyacı var.",
["Fırtına Kıyısı'ndan 8 Kristalize Tuz topla.", "Bramble'a getir."]),
("Akbaba Sürüsü", "doran", "B-1",
"Leş akbabaları çorak yolcularına saldırıyor.",
["B-1'de 6 Leş Akbabası öldür.", "Doran'a bildir."]),
("Kutsal Taş", "thariel", "T-2",
"Sunak onarımı için bekçi heykelinden kutsal taş gerek.",
["Taş Bekçi Heykeli'ni yık.", "2 Kutsal Taş getir."]),
("Bal ve Mum", "grungni", "Akça Koru",
"Madenciler karanlıkta çalışmak için mum, ustabaşı da tatlı istiyor.",
["Akça Koru'dan 5 Yaban Balı topla.", "Grungni'ye getir."]),
("Goblin Reisi", "kael", "Rivenwood",
"Goblin çetesinin şamanı bölgeyi terörize ediyor.",
["Vahşi Şaman Goblin'i öldür.", "4 Goblin Kulağı getir."]),
("Kristalize Tuz Siparişi", "verena", None,
"Verena koruyucu tuz çemberi için saf tuz istiyor.",
["Fırtına Kıyısı'ndan 10 Kristalize Tuz topla.", "Verena'ya ver."]),
("Yolcu Kurtarma", "sefa", "Solstice Mire",
"Bataklıkta mahsur kalan bir yolcu yardım bekliyor.",
["Solstice Mire'da yolcuyu bul (araştır).", "Harpilerden koru.", "Sefa'ya getir."]),
("Kadim Kapı", "orin", "M-2",
"Orin mağaranın dibindeki mühürlü kapıyı çözmek istiyor.",
["M-2'de kapının 3 sembolünü incele (araştır).", "Çizimi Orin'e getir."]),
("Şifalı Çorba", "lysa", "Av Toprakları",
"Hasta çocuklar için besleyici et suyu gerek.",
["Av Toprakları'nda 6 yaban eti getir.", "Lysa'ya teslim et."]),
("Kayıp Çoban", "bram", "Uçsuz Çayırlar mı?",
"Çayırlarda bir çoban ve sürüsü kaybolmuş.",
["Uçsuz Çayırlar'ı araştır.", "Çobanı bul.", "Bram'a bildir."]),
("Örümcek İpeği", "verena", "M-2",
"Verena dayanıklı örümcek ipeği ile deney yapacak.",
["Derin Örümcek'ten 4 ipek topla.", "Verena'ya getir."]),
("Kayıp Madenci Ailesi", "grungni", "Rivenhaven",
"Bir madencinin ailesi haber bekliyor; adamı bul.",
["Rivenhaven'da kayıp madenciyi ara (araştır).", "Haberi Grungni'ye ilet."]),
("Tapınak Çanı", "nadia", "T-2",
"Tapınak çanı düşmüş; ruhları uzak tutan sesi geri getir.",
["T-2'de düşen çanı bul (araştır).", "Bekçiyi geçip çanı as.", "Nadia'ya bildir."]),
]
async def resolve_map_tag(c, name):
if not name or name.endswith("mı?"):
return None
return await c.fetchval("SELECT id FROM map_tags WHERE name=$1", name)
async def main():
dsn = settings.DATABASE_URL.replace("+asyncpg", "")
c = await asyncpg.connect(dsn)
# 1) Görev verenler (upsert by name)
giver_ids = {}
for key, name, role, place, about in GIVERS:
tag = await c.fetchval("SELECT id FROM map_tags WHERE name=$1", place)
desc = f"{about}\n\n{GIVER_MARK}"
gid = await c.fetchval("SELECT id FROM npcs WHERE name=$1", name)
if gid:
await c.execute("UPDATE npcs SET role=$2,stance='friendly',description=$3,"
"map_tag_id=$4,updated_at=now() WHERE id=$1", gid, role, desc, tag)
else:
gid = await c.fetchval("INSERT INTO npcs(name,role,stance,description,map_tag_id) "
"VALUES($1,$2,'friendly',$3,$4) RETURNING id", name, role, desc, tag)
giver_ids[key] = gid
# 2) Düşmanlar (upsert by name)
for name, role, region, desc in ENEMIES:
tag = await c.fetchval("SELECT id FROM map_tags WHERE name=$1", region)
eid = await c.fetchval("SELECT id FROM npcs WHERE name=$1", name)
if eid:
await c.execute("UPDATE npcs SET role=$2,stance='hostile',description=$3,"
"map_tag_id=$4,updated_at=now() WHERE id=$1", eid, role, desc, tag)
else:
await c.execute("INSERT INTO npcs(name,role,stance,description,map_tag_id) "
"VALUES($1,$2,'hostile',$3,$4)", name, role, desc, tag)
# 3) Görev itemleri (upsert by code) + toplanabilir olanları location_resources'a
for code, name, rarity, loc, skill, step, xp, about in QITEMS:
iid = await c.fetchval("""
INSERT INTO items(code,name,type,rarity,base_value,description)
VALUES($1,$2,'material',$3,$4,$5)
ON CONFLICT(code) DO UPDATE SET name=EXCLUDED.name,rarity=EXCLUDED.rarity,
description=EXCLUDED.description RETURNING id
""", code, name, rarity, {"common":8,"uncommon":20,"rare":60,"epic":180}.get(rarity,8), about)
if loc:
lid = await c.fetchval("SELECT id FROM locations WHERE code=$1", loc)
if lid:
await c.execute("""
INSERT INTO location_resources(location_id,item_code,skill,step_cost,xp,cooldown_s)
VALUES($1,$2,$3,$4,$5,300)
ON CONFLICT(location_id,item_code) DO NOTHING
""", lid, code, skill, step, xp)
# 4) Quest'ler — önce eski seed'i temizle, sonra ekle
await c.execute("DELETE FROM quests WHERE author=$1", SEED_TAG)
qn = 0
for i, (title, gkey, region, summary, objs) in enumerate(QUESTS):
gid = giver_ids.get(gkey)
rtag = await resolve_map_tag(c, region)
qid = await c.fetchval("""
INSERT INTO quests(title,quest_type,summary,giver_npc_id,region_tag_id,author,sort_order)
VALUES($1,'side',$2,$3,$4,$5,$6) RETURNING id
""", title, summary, gid, rtag, SEED_TAG, i)
for j, note in enumerate(objs):
await c.execute("INSERT INTO quest_objectives(quest_id,note,ordering,map_tag_id) "
"VALUES($1,$2,$3,$4)", qid, note, j, rtag)
qn += 1
tot_q = await c.fetchval("SELECT count(*) FROM quests")
tot_npc = await c.fetchval("SELECT count(*) FROM npcs")
tot_hostile = await c.fetchval("SELECT count(*) FROM npcs WHERE stance='hostile'")
tot_items = await c.fetchval("SELECT count(*) FROM items")
await c.close()
print(f"Görev veren: {len(GIVERS)}, yeni düşman: {len(ENEMIES)}, görev itemi: {len(QITEMS)}")
print(f"Yan görev eklendi: {qn}. DB toplam quest: {tot_q}, NPC: {tot_npc} "
f"(hostile {tot_hostile}), item: {tot_items}")
asyncio.run(main())