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:
- Dialogi (
C_INFO) - rozmowy z NPC, które rozpoczynają i kończą zadania - Dziennik misji (Quest Log) - wpisy widoczne dla gracza
- Zmienne stanu - śledzenie postępu zadania
Klasa C_INFO - dialogi
Każda opcja dialogowa to instancja klasy C_INFO:
| Pole | Typ | Opis |
|---|---|---|
npc | int | NPC, z którym rozmawiamy |
nr | int | Kolejność wyświetlania (niższy = wyżej) |
condition | func | Funkcja warunku - kiedy opcja jest widoczna |
information | func | Funkcja wykonywana po wybraniu opcji |
permanent | int | TRUE = opcja nie znika po użyciu |
important | int | TRUE = NPC mówi pierwszy (bez wyboru gracza) |
description | string | Tekst 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";
};
| Pole | Wartość | Opis |
|---|---|---|
name | "Stary topór Konrada" | Nazwa wyświetlana w grze |
mainflag | ITEM_KAT_NONE | Kategoria "inne" (nie broń/zbroja/jedzenie) |
flags | ITEM_MISSION | Przedmiot misyjny (nie można sprzedać ani wyrzucić) |
value | 0 | Nie do sprzedaży |
visual | "ItMw_010_1h_misc_axe_01.3DS" | Plik modelu 3D |
material | MAT_WOOD | Drewno (wpływa na dźwięki) |
description | name | Nagłówek tooltipa = nazwa itemu |
TEXT[5] | "Przedmiot misyjny" | Linia informacyjna w tooltipie |
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łanie | Opis |
|---|---|
npc = BAU_900_Konrad | Dialog należy do Konrada |
nr = 999 | Zawsze na samym dole listy dialogowej |
condition | Funkcja warunku (tu zawsze TRUE) |
information | Funkcja wykonywana po wybraniu opcji |
permanent = TRUE | Opcja widoczna zawsze po użyciu |
description = DIALOG_ENDE | Wbudowana stała = "Koniec" |
return TRUE | Opcja 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;
};
| Pole | Wartość | Opis |
|---|---|---|
npc | BAU_900_Konrad | Dialog należy do Konrada |
nr | 1 | Wysoki priorytet (wyświetlany jako pierwszy) |
condition | DIA_Konrad_Hallo_Condition | Funkcja warunku |
information | DIA_Konrad_Hallo_Info | Funkcja wykonywana po wywołaniu |
permanent | FALSE | Dialog pojawia się tylko raz |
important | TRUE | NPC 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źć?
};
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.";
};
| Pole | Wartość | Opis |
|---|---|---|
npc | BAU_900_Konrad | Dialog należy do Konrada |
nr | 5 | Pozycja w kolejności wyświetlania |
condition | DIA_Konrad_Topor_Condition | Widoczny gdy quest nie rozpoczęty |
information | DIA_Konrad_Topor_Info | Rozpoczyna quest |
permanent | FALSE | Znika 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:
| Funkcja | Opis |
|---|---|
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.";
};
| Pole | Wartość | Opis |
|---|---|---|
npc | BAU_900_Konrad | Dialog należy do Konrada |
nr | 10 | Pozycja w kolejności wyświetlania |
condition | DIA_Konrad_Topor_Oddaj_Condition | Widoczny gdy quest aktywny I gracz ma topór |
information | DIA_Konrad_Topor_Oddaj_Info | Daje nagrodę i kończy quest |
permanent | FALSE | Znika 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łanie | Opis |
|---|---|
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_SUCCESS | Oznacza 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:
- Zmiennej stanu śledzącej postęp (0 →
LOG_RUNNING→LOG_SUCCESS) - Przedmiotu misyjnego z flagą
ITEM_MISSION - Dialogów z warunkami opartymi o stan questa i posiadane przedmioty
- Wpisów w dzienniku informujących gracza o postępie
- Nagrody (złoto, XP, przedmioty)
- Rejestracji wszystkich plików w
Gothic.srcw odpowiedniej kolejności