Skip to main content

My First NPC

In this tutorial you will learn how to create a simple non-player character (NPC) in Daedalus. We will create a farmer who stands in the market and has his own daily routine.

Prerequisites

Before starting, make sure that:

  • You have the Gothic scripts installed (Scripts/Content/ folder)
  • You understand the script structure
  • You know what an instance and prototype are in Daedalus

The C_NPC Class - What Defines a Character?

Every NPC in Gothic is an instance of the C_NPC class. The most important fields are:

FieldTypeDescription
namestring[5]NPC name (displayed in game)
guildintGuild (e.g., GIL_MIL - militia, GIL_OUT - guildless)
idintUnique NPC identifier
voiceintVoice number (linked to audio files)
levelintCharacter level
attribute[]int[]Attributes: HP, mana, strength, dexterity
protection[]int[]Protection against damage types
fight_tacticintCombat tactic (e.g., FAI_HUMAN_COWARD)
daily_routinefuncNPC daily routine function
npctypeintNPC type (main, friend, enemy)
flagsintFlags (e.g., NPC_FLAG_IMMORTAL)

The Npc_Default Prototype

Before creating our own character, we need to understand the prototype Npc_Default. This is a template that almost all characters in the game inherit from:

prototype Npc_Default (C_NPC)
{
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;

HitChance[NPC_TALENT_1H] = 0;
HitChance[NPC_TALENT_2H] = 0;
HitChance[NPC_TALENT_BOW] = 0;
HitChance[NPC_TALENT_CROSSBOW] = 0;

protection[PROT_EDGE] = 0;
protection[PROT_BLUNT] = 0;
protection[PROT_POINT] = 0;
protection[PROT_FIRE] = 0;
protection[PROT_MAGIC] = 0;

damagetype = DAM_BLUNT;
senses = SENSE_HEAR | SENSE_SEE;
senses_range = PERC_DIST_ACTIVE_MAX;
};
FieldDefaultDescription
attribute[ATR_STRENGTH]10Base strength
attribute[ATR_DEXTERITY]10Base dexterity
attribute[ATR_MANA_MAX]10Maximum mana
attribute[ATR_MANA]10Starting mana
attribute[ATR_HITPOINTS_MAX]40Maximum health
attribute[ATR_HITPOINTS]40Starting health
HitChance[NPC_TALENT_*]0Hit chance per weapon type - 0% means NPC cannot fight with it
protection[PROT_*]0Protection against each damage type - 0 means no protection
damagetypeDAM_BLUNTDefault damage type dealt by the NPC
sensesSENSE_HEAR | SENSE_SEENPC can hear and see
senses_rangePERC_DIST_ACTIVE_MAXMaximum perception range
info

The prototype sets default values. Each NPC instance can override any of them.

Creating an NPC Instance

Let's create a farmer named Konrad. Create a file BAU_900_Konrad.d in the Story/NPC/ folder:

instance BAU_900_Konrad (Npc_Default)
{
name = "Konrad";
guild = GIL_OUT;
id = 900;
voice = 90;
flags = 0;
npctype = NPCTYPE_MAIN;

attribute[ATR_STRENGTH] = 30;
attribute[ATR_DEXTERITY] = 15;
attribute[ATR_HITPOINTS_MAX] = 80;
attribute[ATR_HITPOINTS] = 80;
level = 5;

fight_tactic = FAI_HUMAN_COWARD;

EquipItem (self, ItMw_1h_Bau_Axe);
CreateInvItems (self, ItMi_Gold, 25);
CreateInvItems (self, ItFo_Apple, 3);

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");

B_GiveNpcTalents (self);
B_SetFightSkills (self, 15);

daily_routine = Rtn_Start_900;
};
Field / CallDescription
name = "Konrad"NPC name displayed in game
guild = GIL_OUTGuildless (farmer)
id = 900Unique NPC identifier
voice = 90Voice number (linked to audio files)
flags = 00 = normal, NPC_FLAG_IMMORTAL = immortal
npctype = NPCTYPE_MAINImportant character (quest-relevant)
attribute[ATR_STRENGTH] = 30Strength (overrides prototype's 10)
attribute[ATR_DEXTERITY] = 15Dexterity (overrides prototype's 10)
attribute[ATR_HITPOINTS_MAX] = 80Maximum health (overrides prototype's 40)
attribute[ATR_HITPOINTS] = 80Starting health
level = 5Character level
fight_tactic = FAI_HUMAN_COWARDFlees from combat
EquipItem(self, ItMw_1h_Bau_Axe)Equips a farmer's axe
CreateInvItems(self, ItMi_Gold, 25)25 gold coins in inventory
CreateInvItems(self, ItFo_Apple, 3)3 apples in inventory
B_SetNpcVisual(self, ...)Sets body mesh, head, face, body texture, armor
Mdl_SetModelFatness(self, 1)Body fatness (0 = thin, 1 = normal, 2 = fat)
Mdl_ApplyOverlayMds(self, "Humans_Relaxed.mds")Relaxed animation overlay
B_GiveNpcTalents(self)Assigns default talent values
B_SetFightSkills(self, 15)15% hit chance for all weapon types
daily_routine = Rtn_Start_900Daily routine function (see below)
tip

Naming convention: BAU (Bauer = farmer), 900 (unique ID), Konrad (name). In the original Gothic scripts, each guild has its own prefix.

Daily Routine

Every NPC needs a daily routine - a function that defines what they do at each hour:

func void Rtn_Start_900 ()
{
TA_Stand_ArmsCrossed (07, 00, 12, 00, "NW_CITY_WELL_01");
TA_Sit_Bench (12, 00, 13, 00, "NW_CITY_BENCH_01");
TA_Smalltalk (13, 00, 20, 00, "NW_FARM1_PATH_01");
TA_Sleep (20, 00, 07, 00, "NW_FARM1_BED_01");
};
TimeFunctionWaypointActivity
07:00–12:00TA_Stand_ArmsCrossedNW_CITY_WELL_01Stands by the well
12:00–13:00TA_Sit_BenchNW_CITY_BENCH_01Eats a meal
13:00–20:00TA_SmalltalkNW_FARM1_PATH_01Works at the farm
20:00–07:00TA_SleepNW_FARM1_BED_01Sleeps
warning

Waypoints (e.g., "NW_CITY_WELL_01") must exist in the game world (.zen file). If you use a non-existent waypoint, the NPC will appear at the (0, 0, 0) point.

Available daily routine functions:

FunctionDescription
TA_Stand_ArmsCrossedStands with arms crossed
TA_Stand_GuardingStands on guard
TA_Sit_BenchSits on a bench
TA_SleepSleeps
TA_SmalltalkTalks with nearby NPCs
TA_SmithSmithing
TA_EatEats
TA_PracticePractices

Registration in Gothic.src

For the game to load the new NPC, you need to add the file to Gothic.src:

Story\NPC\BAU_900_Konrad.d
danger

File order in Gothic.src matters! The NPC must be declared after the Npc_Default prototype, but before dialogs.

Placing the NPC in the World

To make the NPC appear in the game world, you need to insert (spawn) them in the startup function of the corresponding world. In the Startup.d file (or the appropriate world file) add:

func void Startup_NewWorld ()
{
// ... other NPCs ...
Wld_InsertNpc (BAU_900_Konrad, "NW_CITY_WELL_01");
};

Wld_InsertNpc inserts the character into the world at the given waypoint. From this moment, the NPC will start following their daily routine.

Summary

Creating an NPC requires:

  1. An instance inheriting from Npc_Default
  2. Setting attributes (strength, HP, level)
  3. Configuring appearance (model, texture, armor)
  4. Defining a daily routine
  5. Registration in Gothic.src
  6. Inserting into the world in Startup.d