Mój pierwszy NPC
W tym poradniku nauczysz się tworzyć prostą postać niezależną (NPC) w języku Daedalus. Stworzymy farmera, który stoi na rynku i ma swój dzienny plan zajęć.
Wymagania wstępne
Przed rozpoczęciem upewnij się, że:
- Masz zainstalowane skrypty Gothic (folder
Scripts/Content/) - Rozumiesz strukturę skryptów
- Wiesz, czym jest instancja i prototyp w Daedalusie
Klasa C_NPC - co definiuje postać?
Każdy NPC w Gothic jest instancją klasy C_NPC. Najważniejsze pola tej klasy to:
| Pole | Typ | Opis |
|---|---|---|
name | string[5] | Imię NPC (wyświetlane w grze) |
guild | int | Gildia (np. GIL_MIL - milicja, GIL_OUT - bezgildyjny) |
id | int | Unikalny identyfikator NPC |
voice | int | Numer głosu (powiązany z plikami audio) |
level | int | Poziom postaci |
attribute[] | int[] | Atrybuty: HP, mana, siła, zręczność |
protection[] | int[] | Ochrona przed typami obrażeń |
fight_tactic | int | Taktyka walki (np. FAI_HUMAN_COWARD) |
daily_routine | func | Funkcja z dziennym planem NPC |
npctype | int | Typ NPC (główny, przyjaciel, wróg) |
flags | int | Flagi (np. NPC_FLAG_IMMORTAL) |
Prototyp Npc_Default
Zanim stworzymy własną postać, musimy rozumieć prototyp Npc_Default. Jest to szablon, z którego dziedziczą prawie wszystkie postacie w grze:
prototype Npc_Default (C_NPC)
{
// Podstawowe atrybuty
attribute[ATR_STRENGTH] = 10;
attribute[ATR_DEXTERITY] = 10;
attribute[ATR_MANA_MAX] = 10;
attribute[ATR_MANA] = 10;
attribute[ATR_HITPOINTS_MAX] = 40;
attribute[ATR_HITPOINTS] = 40;
// Szanse trafienia (0% - nie umie walczyć daną bronią)
HitChance[NPC_TALENT_1H] = 0;
HitChance[NPC_TALENT_2H] = 0;
HitChance[NPC_TALENT_BOW] = 0;
HitChance[NPC_TALENT_CROSSBOW] = 0;
// Ochrona (0 - brak ochrony)
protection[PROT_EDGE] = 0;
protection[PROT_BLUNT] = 0;
protection[PROT_POINT] = 0;
protection[PROT_FIRE] = 0;
protection[PROT_MAGIC] = 0;
// Domyślne ustawienia
damagetype = DAM_BLUNT;
senses = SENSE_HEAR | SENSE_SEE;
senses_range = PERC_DIST_ACTIVE_MAX;
};
| Pole | Domyślnie | Opis |
|---|---|---|
attribute[ATR_STRENGTH] | 10 | Bazowa siła |
attribute[ATR_DEXTERITY] | 10 | Bazowa zręczność |
attribute[ATR_MANA_MAX] | 10 | Maksymalna mana |
attribute[ATR_MANA] | 10 | Startowa mana |
attribute[ATR_HITPOINTS_MAX] | 40 | Maksymalne zdrowie |
attribute[ATR_HITPOINTS] | 40 | Startowe zdrowie |
HitChance[NPC_TALENT_*] | 0 | Szansa trafienia per typ broni - 0% = nie umie walczyć tą bronią |
protection[PROT_*] | 0 | Ochrona przed typami obrażeń - 0 = brak ochrony |
damagetype | DAM_BLUNT | Domyślny typ zadawanych obrażeń |
senses | SENSE_HEAR | SENSE_SEE | NPC słyszy i widzi |
senses_range | PERC_DIST_ACTIVE_MAX | Maksymalny zasięg percepcji |
Prototyp ustawia domyślne wartości. Każda instancja NPC może nadpisać dowolne z nich.
Tworzenie instancji NPC
Stwórzmy farmera o imieniu Konrad. Utwórz plik BAU_900_Konrad.d w folderze Story/NPC/:
instance BAU_900_Konrad (Npc_Default)
{
// --- Podstawowe informacje ---
name = "Konrad";
guild = GIL_OUT;
id = 900;
voice = 90;
flags = 0;
npctype = NPCTYPE_MAIN;
// --- Atrybuty ---
attribute[ATR_STRENGTH] = 30;
attribute[ATR_DEXTERITY] = 15;
attribute[ATR_HITPOINTS_MAX] = 80;
attribute[ATR_HITPOINTS] = 80;
level = 5;
// --- Walka ---
fight_tactic = FAI_HUMAN_COWARD;
// --- Ekwipunek ---
EquipItem (self, ItMw_1h_Bau_Axe);
CreateInvItems (self, ItMi_Gold, 25);
CreateInvItems (self, ItFo_Apple, 3);
// --- Wygląd ---
B_SetNpcVisual (self, MALE, "Hum_Head_Bald", Face_N_NormalBart_Senyan, BodyTex_N, ITAR_Bau_L);
Mdl_SetModelFatness (self, 1);
Mdl_ApplyOverlayMds (self, "Humans_Relaxed.mds");
// --- Umiejętności ---
B_GiveNpcTalents (self);
B_SetFightSkills (self, 15);
// --- Plan dnia ---
daily_routine = Rtn_Start_900;
};
| Pole / Wywołanie | Opis |
|---|---|
name = "Konrad" | Imię NPC wyświetlane w grze |
guild = GIL_OUT | Bezgildyjny (rolnik) |
id = 900 | Unikalny numer identyfikacyjny |
voice = 90 | Numer głosu (powiązany z plikami audio) |
flags = 0 | 0 = normalny, NPC_FLAG_IMMORTAL = nieśmiertelny |
npctype = NPCTYPE_MAIN | Ważna postać (związana z questami) |
attribute[ATR_STRENGTH] = 30 | Siła (nadpisuje 10 z prototypu) |
attribute[ATR_DEXTERITY] = 15 | Zręczność (nadpisuje 10 z prototypu) |
attribute[ATR_HITPOINTS_MAX] = 80 | Maksymalne zdrowie (nadpisuje 40 z prototypu) |
attribute[ATR_HITPOINTS] = 80 | Startowe zdrowie |
level = 5 | Poziom postaci |
fight_tactic = FAI_HUMAN_COWARD | Ucieka przed walką |
EquipItem(self, ItMw_1h_Bau_Axe) | Zakłada topór farmera |
CreateInvItems(self, ItMi_Gold, 25) | 25 sztuk złota w ekwipunku |
CreateInvItems(self, ItFo_Apple, 3) | 3 jabłka w ekwipunku |
B_SetNpcVisual(self, ...) | Ustawia mesh ciała, głowę, twarz, teksturę i zbroję |
Mdl_SetModelFatness(self, 1) | Tusza postaci (0 = chudy, 1 = normalny, 2 = gruby) |
Mdl_ApplyOverlayMds(self, "Humans_Relaxed.mds") | Zrelaksowana nakładka animacji |
B_GiveNpcTalents(self) | Przypisuje domyślne talenty |
B_SetFightSkills(self, 15) | 15% szans trafienia dla wszystkich typów broni |
daily_routine = Rtn_Start_900 | Funkcja planu dnia (zobacz niżej) |
Konwencja nazewnictwa: BAU (Bauer = farmer), 900 (unikalne ID), Konrad (imię). W oryginalnych skryptach Gothic każda gildia ma swój prefix.
Plan dnia (Daily Routine)
Każdy NPC potrzebuje planu dnia - funkcji określającej, co robi o danej godzinie:
func void Rtn_Start_900 ()
{
// Od 7:00 do 12:00 - stoi przy studni
TA_Stand_ArmsCrossed (07, 00, 12, 00, "NW_CITY_WELL_01");
// Od 12:00 do 13:00 - je posiłek
TA_Sit_Bench (12, 00, 13, 00, "NW_CITY_BENCH_01");
// Od 13:00 do 20:00 - pracuje na farmie
TA_Smalltalk (13, 00, 20, 00, "NW_FARM1_PATH_01");
// Od 20:00 do 7:00 - śpi
TA_Sleep (20, 00, 07, 00, "NW_FARM1_BED_01");
};
Waypointy (np. "NW_CITY_WELL_01") muszą istnieć w świecie gry (pliku .zen). Jeśli użyjesz nieistniejącego waypointa, NPC pojawi się w punkcie (0, 0, 0).
Dostępne funkcje planu dnia:
| Funkcja | Opis |
|---|---|
TA_Stand_ArmsCrossed | Stoi ze skrzyżowanymi rękoma |
TA_Stand_Guarding | Stoi na straży |
TA_Sit_Bench | Siedzi na ławce |
TA_Sleep | Śpi |
TA_Smalltalk | Rozmawia z pobliskimi NPC |
TA_Smith | Kowalstwo |
TA_Eat | Je |
TA_Practice | Ćwiczy |
Rejestracja w Gothic.src
Aby gra załadowała nowego NPC, musisz dodać plik do Gothic.src:
Story\NPC\BAU_900_Konrad.d
Kolejność plików w Gothic.src ma znaczenie! NPC musi być zadeklarowany po prototypie Npc_Default, ale przed dialogami.
Osadzenie NPC w świecie
Aby NPC pojawił się w świecie gry, musisz go wstawić (spawn) w funkcji startowej odpowiedniego świata. W pliku Startup.d (lub odpowiednim pliku świata) dodaj:
func void Startup_NewWorld ()
{
// ... inne NPC ...
Wld_InsertNpc (BAU_900_Konrad, "NW_CITY_WELL_01");
};
Wld_InsertNpc wstawia postać do świata w podanym waypoinecie. Od tego momentu NPC zacznie wykonywać swój plan dnia.
Podsumowanie
Utworzenie NPC wymaga:
- Instancji dziedziczącej po
Npc_Default - Ustawienia atrybutów (siła, HP, poziom)
- Konfiguracji wyglądu (model, tekstura, zbroja)
- Zdefiniowania planu dnia
- Rejestracji w
Gothic.src - Wstawienia do świata w
Startup.d