Creating squad and setting up its logic

From Mod Wiki

Jump to: navigation, search

It is common in quests to create squads of NPCs, which do something. Like walking around, talking, fighting or just resting. In order to do that we need to assign each NPC its logic.

To understand this tutorial. you need to know how to edit all.spawn file, what is smart terrain, squad, space restrictor.


1. Creating squad

First off we start by creating squad. To create squad you can use number of ways. There are 2 general ways to accomplish this:

  1. via space restrictor using some info potion
  2. via Lua scripts

The most used method is the first one, because using Lua it is bit more complicated and GSC also uses that one.

But now we will define squad first.

Defining squad and its NPCs

So, first we need to define NPCs. They're usually defined in file according to their location. As we want to create squad in Jupiter we edit file configs\gameplay\character_desc_jupiter.xml.

Usually when you will be creating specific characters you'd just copy last character in character_desc_*.xml file and adjust properties you need to change.

So we will create a unique NPC, which will be a duty stalker:

<specific_character id="jup_b212_duty_leader" team_default = "1">
    <map_icon x="1" y="0"></map_icon>
    <bio>Îďűňíűé ńňŕëęĺđ. Äĺňŕëüíŕ˙ číôîđěŕöč˙ îňńóňńňâóĺň.</bio>
    <money min="1000" max="3000" infinitive="0"/>
      [spawn] \n
      wpn_ak74 \n
      ammo_5.45x39_fmj = 1 \n
      wpn_pm = 1 \n
      ammo_9x18_fmj = 1 \n
      grenade_rgd5 = 1 \n
#include "gameplay\character_items.xml"
#include "gameplay\character_food.xml"
#include "gameplay\character_drugs_2.xml"
#include "gameplay\character_criticals_4.xml"
#include "gameplay\character_dialogs.xml"

So here is basic info of what is usually needed to create a character:

  • ID - character ids are usually consisted of name of smart terrain, in which they reside
  • Name – you can use generated name or you can define one in configs\text\*lang*\st_character.xml (lang is your game language – rus, eng, etc.)
  • Icon – which icon will NPC use in trade, upgrade and other windows. Generic and unique ones are defined in configs\ui\textures_descr\ui_actor.xml. Icon and Visual should match.
  • Class – this is important, because character class is what need in squad definition. We define it later on.
  • Community – important, defines in which community will our NPC spawn
  • Snd_config – there are 3 profiles, which you can use (human_01, human_02, human_03), dolg is for Duty stalkers
  • Visual – defines how will our NPC look, again to know which visuals can be used, you should take look in meshes\actors\stalker_*faction*\. Icon and Visual should match.
  • Supplies – define what will NPC carry with himself. Items, food and drugs are defined in those 3 XML files, so you don't have to write them down manually. NPC need only one box of ammo – that only defines, which type of ammo to use, because they have unlimited ammo

Of course there are other things you can change like money, rank, reputation or bio, but they're not important, unless you want your NPC to be wealthy. Usually you would also want to add dialogs here, but that's beyond scope of this article. You should read dedicated article.

For clarity sake, use same ID and same Classto avoid unnecessary crashes of game, because of unexisting NPC class or character ID.

Now we are going to create NPC profile. NPC profiles are defined in configs\gameplay\npc_profile.xml:

<character id="jup_b212_duty_leader">

Here just use same values as we used in charater_desc_jupiter.xml file.

After that we need to create spawn section, again in appropriate file. Spawn sections are located in configs\creatures\spawn_sections_*.ltx, again splitted by location. We are going to edit spawn_sections_jupiter.ltx:

$spawn                     = "respawn\jup_b212_duty_leader"
character_profile     =  jup_b212_duty_leader
story_id =  jup_b212_duty_leader

Here, almost everything is important:

  • spawn – this is the least important thing, just use our character ID here afer respawn\
  • character_profile – our character profile from character_desc_jupiter.xml
  • story_id – the most important thing. By this special ID, we will identify our NPC throughout our scripts – just set it to our usual ID (jup_b212_duty_leader)

In spawn section you can also define things like spec_rank or community, but that's not necessary.

Finally, we're about to define our squad. Squad definitions are in configs\misc\squad_descr_*.ltx – splitted by location. Open squad_descr_jupiter.ltx and add this to the beginning:

faction = dolg
npc = jup_b212_duty_leader, sim_default_duty_1, sim_default_duty_2
story_id = jup_b212_duty_squad
target_smart = jup_b212
  • faction – faction of our squad – use the same as in character_desc_jupiter.xml
  • NPC – defines which NPCs will our squad contain – notice our newly created unique NPC – jup_b212_duty_leader
  • story_id – important thing as in spawn_sections_jupiter.ltx – we will identify our squad with this ID
  • target_smart – defines which smart terrain is destination for our squad. You can use condition list here to define multiple target smart terrains.

You can (and also would like to) use spawn_point parameter – defines where squad will spawn. Again, you can use condition list in it.

(note: spawn_point is a waypoint defined in way_*.ltx files).

Also, there are other parameters: npc_in_squad and npc_random. Those are used for simulation squads – to generate random NPCs from given list and given number of them (npc_in_squad) and shouldn't be used in unique squads, because some problems could appear, e.g. if there's a leader in a squad, he doesn't have to be necessarily spawned.

Creating space restrictor

Creating space restrictor around place where task takes place is preferable, because you get a centralized control over the task.

In order to create space restrictor, you need to add it's definition into one of alife_*.ltx files of all.spawn. In our case it is alife_jupiter.ltx.

You need to assign it unique ID and preferably unique name, consisting of smart terrain name and your designed string.

We take for example jup_b212, which is Ventilation complex in south part of Jupiter location. Our space restrictor name will be jup_b212_sr_task (sr is shortcut for space restrictor).

So our new section in alife_jupiter.ltx would look like this:

; cse_abstract properties
section_name = space_restrictor
name = jup_b212_sr_task
position = -65.5894927978516,23.7972965240479,-322.665954589844
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 326
distance = 0
level_vertex_id = 609785
object_flags = 0xffffff3e
custom_data = <<END
cfg = scripts\jupiter\jup_b212_sr_task.ltx
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 40
; cse_alife_space_restrictor properties
restrictor_type = 3

Important parts are these:

  • Section name - defines that our object is space restrictor.
  • Name - defines our space restrictor name.
  • Position – position of our space restrictor. In our case I took position of jup_b212 smart terrain.
  • Game_vertex_id – defines vertex id in whole game (not important term here – vertex). Again I took it from jup_b212 smart terrain.
  • Level_vertex_id – defines vertex id in current level. From jup_b212.
  • Cfg – defines that configuration for our space restrictor is located somewhere else. It could be defined here, but we would always have to recompile all.spawn if we wanted to change something.
  • Radius – radius of space restrictor. In this case, it is a sphere. Don't make it too big, because obviously FPS will drop down.

Spawning squad

We will spawn our squad very simple – when actor enters Yanov station. Why don't we use our newly created space restrictor? Because that one is for the control over our task. You are free to create another somewhere else and use that one instead of weapon restrictor over Yanov.

So open up configs\scripts\jupiter\jup_a6_sr_noweap.ltx logic file and edit sr_no_weapon@wait section:

on_actor_inside = {=check_smart_alarm_status(jup_a6:normal) !actor_has_weapon} sr_no_weapon@wait
on_info = {=actor_in_zone(jup_a6_sr_light)} sr_no_weapon@wait
on_actor_outside = sr_idle@wait
on_info = {-jup_b212_duty_squad_created !squad_exist(jup_b212_duty_squad)} %+jup_b212_duty_squad_created =create_squad(jup_b212_duty_squad:jup_b212)%

Fast recap over logic above:

  • section activates when actor enter space restrictor around and in Yanov (that is in sr_idle@wait section)
  • on_info fires when:
    • infoportion jup_b212_duty_squad_created is not set and squad jup_b212_duty_squad doesn't exist
  • when on_info fires:
    • infoportion jup_b212_duty_squad_created is set
    • squad jup_b212_duty_squad is created

2. Setting up NPCs logic

First, we need to know something more about smart terrains. Smart terrains have different kind of jobs, which they assign to NPCs. Example is some stalkers patroling around smart terrain, sitting, eating, sleeping. Just everything they do in smart terrain.

Normal, simulation smart terrains have already predefined jobs (like patrol, guard, walk, sit, sleep etc.). But we need exclusive jobs for our NPCs. Exclusive jobs are usually defined in external configuration files (remember cfg = in custom_data?) of smart terrains. They're divided again by location. So we need config file for our smart terrain.

Open file configs\scripts\jupiter\smarts\jup_b212.ltx and add last line to it:

squad_id = 19
max_population = 1
;respawn_params = respawn@jup_b212   
spawn_squads = simulation_chimera
spawn_num = {+jup_b212_jupiter_chimera_hunt_done} 1,  0
night_hunter_chimera = jupiter\jup_b212_chimera_logic.ltx
jup_b212_duty_leader = jupiter\jup_b212_duty_leader.ltx

So here in config file of jup_b212, there are settings for respawn, but they're commented out by GSC. If you want to you can use it, but beware once you enable respawn params, save game with it and then try to remove them game will crash, because respawn params are saved to game save.

Max_population is self explanatory – maximum number of squads that can occupy given smart terrain.

What is more important is jup_b212_duty_leader and its set config file. It is not necessary to use same ID of NPC as its story id, but it is recommended. You'll understand it better from example:

suitable = {=check_npc_name(jup_b212_duty_leader)} true
prior = 200
active = walker@jup_b212_duty_leader
path_walk = leader_walk
path_look = leader_look
meet = meet
use = {=actor_enemy =actor_has_weapon} false, true
close_distance  = 10
close_victim    = actor
close_anim = {=actor_has_weapon} threat, guard
far_distance = 30
far_anim = guard
far_victim = nil

So we have a lot more to learn now.

Logic section:

  • smart terrain checks if that jobs is suitable for NPC, which smart terrain wants to assign job
    • check_npc_name function gets 1 parameter – story id of NPC
    • if name of NPC matches to NPC given in function param NPC gets this exclusive job
  • prior – priority of job, higher it is, less chance an NPC will get this job
  • active – defines which section will be active after the NPC gets this job (in our case a walker section)

Walker@jup_b212_duty_leader section:

  • path_walk – defines waypoint patrol which will NPC follow
  • path_look – defines waypoint patrol at which will NPC look
  • meet – section, which defines how will NPC behave on meet with actor

meet section:

  • use – has a condition list :
    • if actor is an enemy (to the NPC) and also if actor has weapon shown then player can't use the NPC – e.g. cannot activate dialog window
    • otherwise player can use the NPC – can activate dialog window
  • close_* parameters – define how will NPC behave when actor is within close_distance range
    • close_victimstory id of character at which will NPC look
    • close_animanimation which will NPC use – in our case, when actor has weapon shown we use threat animation, otherwise guard
  • far_* parameters – same as close_* parameters, except that actor is further than range defined in far_distance

Note: if you want to add jobs for other NPCs in squad, I strongly suggest to create their own character profile (e.g. in character_desc_*.xml, npc_profile.xml, spawn_sections_*.ltx). Otherwise any simulation (e.g. sim_default_duty_1 or even sim_default_bandit_1) can use the job and that might not what you want.

3. Conclusion

Most of logic and paths are explained in Logic article and you can learn a lot from GSC scripts. Those who are familiar with Lua can always check something in scripts, like checking/adding condition functions in xr_conditions.script or effect functions xr_effects.script.

Personal tools