Przejdź do głównej zawartości

Moje pierwsze zadanie

W tym poradniku nauczysz się tworzyć kompletne zadanie (quest) - od rozmowy z NPC, przez dziennik misji, po nagrodę za wykonanie.

Jak działają questy w Gothic?

System questów w Gothic opiera się na trzech elementach:

  1. Dialogi (C_INFO) - rozmowy z NPC, które rozpoczynają i kończą zadania
  2. Dziennik misji (Quest Log) - wpisy widoczne dla gracza
  3. Zmienne stanu - śledzenie postępu zadania

Klasa C_INFO - dialogi

Każda opcja dialogowa to instancja klasy C_INFO:

PoleTypOpis
npcintNPC, z którym rozmawiamy
nrintKolejność wyświetlania (niższy = wyżej)
conditionfuncFunkcja warunku - kiedy opcja jest widoczna
informationfuncFunkcja wykonywana po wybraniu opcji
permanentintTRUE = opcja nie znika po użyciu
importantintTRUE = NPC mówi pierwszy (bez wyboru gracza)
descriptionstringTekst opcji dialogowej

Krok 1: Zmienna stanu misji

Najpierw zdefiniuj zmienną śledzącą postęp questa. Dodaj ją do pliku ze stałymi misji (np. Log_Constants.d):

// Stany misji:
// 0 = nie rozpoczęta
// LOG_RUNNING = w trakcie
// LOG_SUCCESS = zakończona sukcesem
// LOG_FAILED = zakończona porażką

var int MIS_Konrad_ZnajdzTopor;

// Nazwa tematu w dzienniku
const string TOPIC_Konrad_ZnajdzTopor = "Topór Konrada";

Krok 2: Przedmiot misyjny

Stwórz przedmiot, który gracz musi znaleźć (w Items/MissionItems.d):

instance ItMi_Topor_Konrada (C_Item)
{
name = "Stary topór Konrada";
mainflag = ITEM_KAT_NONE;
flags = ITEM_MISSION;
value = 0;
visual = "ItMw_010_1h_misc_axe_01.3DS";
material = MAT_WOOD;

description = name;
TEXT[5] = "Przedmiot misyjny";
};
PoleWartośćOpis
name"Stary topór Konrada"Nazwa wyświetlana w grze
mainflagITEM_KAT_NONEKategoria "inne" (nie broń/zbroja/jedzenie)
flagsITEM_MISSIONPrzedmiot misyjny (nie można sprzedać ani wyrzucić)
value0Nie do sprzedaży
visual"ItMw_010_1h_misc_axe_01.3DS"Plik modelu 3D
materialMAT_WOODDrewno (wpływa na dźwięki)
descriptionnameNagłówek tooltipa = nazwa itemu
TEXT[5]"Przedmiot misyjny"Linia informacyjna w tooltipie
informacja

Flaga ITEM_MISSION sprawia, że przedmiot nie może być sprzedany ani wyrzucony.

Krok 3: Dialog - wyjście z rozmowy

Każdy NPC musi mieć opcję zakończenia rozmowy. To standardowy element:

instance DIA_Konrad_EXIT (C_INFO)
{
npc = BAU_900_Konrad;
nr = 999;
condition = DIA_Konrad_EXIT_Condition;
information = DIA_Konrad_EXIT_Info;
permanent = TRUE;
description = DIALOG_ENDE;
};

func int DIA_Konrad_EXIT_Condition ()
{
return TRUE;
};

func void DIA_Konrad_EXIT_Info ()
{
AI_StopProcessInfos (self);
};
Pole / WywołanieOpis
npc = BAU_900_KonradDialog należy do Konrada
nr = 999Zawsze na samym dole listy dialogowej
conditionFunkcja warunku (tu zawsze TRUE)
informationFunkcja wykonywana po wybraniu opcji
permanent = TRUEOpcja widoczna zawsze po użyciu
description = DIALOG_ENDEWbudowana stała = "Koniec"
return TRUEOpcja zawsze widoczna
AI_StopProcessInfos(self)Zamyka okno dialogu

Krok 4: Dialog - powitanie (NPC mówi pierwszy)

Gdy gracz podejdzie do Konrada po raz pierwszy:

instance DIA_Konrad_Hallo (C_INFO)
{
npc = BAU_900_Konrad;
nr = 1;
condition = DIA_Konrad_Hallo_Condition;
information = DIA_Konrad_Hallo_Info;
permanent = FALSE;
important = TRUE;
};
PoleWartośćOpis
npcBAU_900_KonradDialog należy do Konrada
nr1Wysoki priorytet (wyświetlany jako pierwszy)
conditionDIA_Konrad_Hallo_ConditionFunkcja warunku
informationDIA_Konrad_Hallo_InfoFunkcja wykonywana po wywołaniu
permanentFALSEDialog pojawia się tylko raz
importantTRUENPC sam podchodzi do gracza i mówi pierwszy
func int DIA_Konrad_Hallo_Condition ()
{
// Pokaż tylko jeśli quest nie został jeszcze rozpoczęty
if (MIS_Konrad_ZnajdzTopor == 0)
{
return TRUE;
};
};

func void DIA_Konrad_Hallo_Info ()
{
// self = NPC (Konrad), other = gracz
AI_Output (self, other, "DIA_Konrad_Hallo_01_01"); //Hej, ty tam! Masz chwilę?
AI_Output (other, self, "DIA_Konrad_Hallo_15_01"); //Czego chcesz?
AI_Output (self, other, "DIA_Konrad_Hallo_01_02"); //Zgubiłem swój topór gdzieś w lesie. Pomożesz mi go znaleźć?
};
wskazówka

Konwencja nazewnictwa audio: DIA_Konrad_Hallo_01_01 - 01 = numer głosu NPC, 01 = numer linii. 15 w linii gracza oznacza głos bohatera. Komentarz // po AI_Output musi być w tej samej linii - parser Daedalusa traktuje go jako tekst napisów dialogowych.

Krok 5: Dialog - przyjęcie zadania

instance DIA_Konrad_Topor (C_INFO)
{
npc = BAU_900_Konrad;
nr = 5;
condition = DIA_Konrad_Topor_Condition;
information = DIA_Konrad_Topor_Info;
permanent = FALSE;
description = "Pomogę ci znaleźć topór.";
};
PoleWartośćOpis
npcBAU_900_KonradDialog należy do Konrada
nr5Pozycja w kolejności wyświetlania
conditionDIA_Konrad_Topor_ConditionWidoczny gdy quest nie rozpoczęty
informationDIA_Konrad_Topor_InfoRozpoczyna quest
permanentFALSEZnika po wybraniu
description"Pomogę ci znaleźć topór."Tekst opcji dialogowej gracza
func int DIA_Konrad_Topor_Condition ()
{
if (MIS_Konrad_ZnajdzTopor == 0)
{
return TRUE;
};
};

func void DIA_Konrad_Topor_Info ()
{
AI_Output (other, self, "DIA_Konrad_Topor_15_01"); //Dobra, poszukam twojego topora.
AI_Output (self, other, "DIA_Konrad_Topor_01_01"); //Dzięki! Ostatni raz widziałem go koło starej jaskini na północy.

// === ROZPOCZNIJ QUEST ===
MIS_Konrad_ZnajdzTopor = LOG_RUNNING;

// Utwórz temat w dzienniku
Log_CreateTopic (TOPIC_Konrad_ZnajdzTopor, LOG_MISSION);
Log_SetTopicStatus (TOPIC_Konrad_ZnajdzTopor, LOG_RUNNING);
B_LogEntry (TOPIC_Konrad_ZnajdzTopor,
"Konrad zgubił swój topór w lesie koło starej jaskini na północy. Powinienem go poszukać."
);

AI_StopProcessInfos (self);
};

Kluczowe funkcje dziennika:

FunkcjaOpis
Log_CreateTopic(topic, LOG_MISSION)Tworzy wpis w dzienniku
Log_SetTopicStatus(topic, status)Ustawia status: LOG_RUNNING / LOG_SUCCESS / LOG_FAILED
B_LogEntry(topic, tekst)Dodaje notatkę do istniejącego wpisu

Krok 6: Dialog - oddanie przedmiotu i nagroda

instance DIA_Konrad_Topor_Oddaj (C_INFO)
{
npc = BAU_900_Konrad;
nr = 10;
condition = DIA_Konrad_Topor_Oddaj_Condition;
information = DIA_Konrad_Topor_Oddaj_Info;
permanent = FALSE;
description = "Mam twój topór.";
};
PoleWartośćOpis
npcBAU_900_KonradDialog należy do Konrada
nr10Pozycja w kolejności wyświetlania
conditionDIA_Konrad_Topor_Oddaj_ConditionWidoczny gdy quest aktywny I gracz ma topór
informationDIA_Konrad_Topor_Oddaj_InfoDaje nagrodę i kończy quest
permanentFALSEZnika po wybraniu
description"Mam twój topór."Tekst opcji dialogowej gracza
func int DIA_Konrad_Topor_Oddaj_Condition ()
{
// Pokaż tylko gdy quest jest aktywny I gracz ma topór
if (MIS_Konrad_ZnajdzTopor == LOG_RUNNING)
&& (Npc_HasItems (other, ItMi_Topor_Konrada) >= 1)
{
return TRUE;
};
};

func void DIA_Konrad_Topor_Oddaj_Info ()
{
AI_Output (other, self, "DIA_Konrad_Topor_Oddaj_15_01"); //Mam twój topór. Znalazłem go koło jaskini.

// Gracz oddaje topór
B_GiveInvItems (other, self, ItMi_Topor_Konrada, 1);

AI_Output (self, other, "DIA_Konrad_Topor_Oddaj_01_01"); //Świetnie! Weź to złoto jako podziękowanie.

// === NAGRODA ===
CreateInvItems (self, ItMi_Gold, 150);
B_GiveInvItems (self, other, ItMi_Gold, 150);
B_GivePlayerXP (100);

// === ZAKOŃCZ QUEST ===
MIS_Konrad_ZnajdzTopor = LOG_SUCCESS;
B_LogEntry (TOPIC_Konrad_ZnajdzTopor,
"Odnalazłem topór Konrada i oddałem mu go. W zamian dostałem 150 sztuk złota."
);

AI_StopProcessInfos (self);
};
WywołanieOpis
Npc_HasItems(other, ItMi_Topor_Konrada)Sprawdza czy gracz ma topór
B_GiveInvItems(other, self, ItMi_Topor_Konrada, 1)Gracz oddaje topór Konradowi
CreateInvItems(self, ItMi_Gold, 150)Tworzy 150 złota w ekwipunku Konrada
B_GiveInvItems(self, other, ItMi_Gold, 150)Konrad daje 150 złota graczowi
B_GivePlayerXP(100)Gracz otrzymuje 100 XP
MIS_Konrad_ZnajdzTopor = LOG_SUCCESSOznacza quest jako ukończony
AI_StopProcessInfos(self)Zamyka okno dialogu

Krok 7: Umieszczenie przedmiotu w świecie

W pliku Startup.d (funkcja startowa świata) umieść topór w lokacji:

func void Startup_NewWorld ()
{
// ... inne elementy ...

// Umieść topór Konrada przy waypoincie jaskini
Wld_InsertItem (ItMi_Topor_Konrada, "NW_CAVE_NORTH_01");
};

Pełna struktura plików

Kompletny quest wymaga tych plików:

Scripts/Content/
├── _intern/Constants.d ← zmienna MIS_Konrad_ZnajdzTopor
├── Story/Log_Entries/
│ └── LOG_Constants.d ← stała TOPIC_Konrad_ZnajdzTopor
├── Items/
│ └── MissionItems.d ← ItMi_Topor_Konrada
├── Story/NPC/
│ └── BAU_900_Konrad.d ← definicja NPC
├── Story/Dialoge/
│ └── DIA_BAU_900_Konrad.d ← wszystkie dialogi
└── Story/Startup.d ← Wld_InsertNpc + Wld_InsertItem

Podsumowanie

Kompletny quest w Gothic wymaga:

  1. Zmiennej stanu śledzącej postęp (0 → LOG_RUNNINGLOG_SUCCESS)
  2. Przedmiotu misyjnego z flagą ITEM_MISSION
  3. Dialogów z warunkami opartymi o stan questa i posiadane przedmioty
  4. Wpisów w dzienniku informujących gracza o postępie
  5. Nagrody (złoto, XP, przedmioty)
  6. Rejestracji wszystkich plików w Gothic.src w odpowiedniej kolejności