Lost Alpha is a new episode of the S.T.A.L.K.E.R. series made by dezowave group for free!

Report article RSS Feed Smart Terrains

A short tutorial about smart terrains, how they work, what they do, and mostly how to set them up. Have a good scripting! :)

Posted by dezodor on Dec 5th, 2010
Intermediate Client Side Coding.

Lately some people asked us how to create and script smart terrains. To avoid responding for each single email we decided to create this little tutorial. We will use ST as Smart Terrain abbreviation. This tutorial treats about npc's ST-s but for mutants it's almost the same.

We assume you are familiar with:

- lua programming
- all.spawn editing (with acdc)
- waypoints (patrols)
- ai schemes

First you have to think about your ST, where to spawn it, how many npcs/mutants will "work" for your ST, when ST should be activated/terminated, how many states your ST will have and so on. We guess the best way would be to show you how to get it working by an example. So let's say we want to spawn ST in Cordon for 3 bandits.

1. Spawning ST:


[2515]
; cse_abstract properties
section_name = smart_terrain
name         = esc_bandits_smart_terrain
position     = 131.02030944824,0.065616846084595,-248.9094543457
direction    = 0,0,0

; cse_alife_object properties
game_vertex_id  = 635
distance        = 9.09999942779541
level_vertex_id = 363757
object_flags    = 0x==3e
custom_data     = < [smart_terrain]
type     = esc_bandits_smart_terrain
cond     = {-infoportion}
capacity = 3
squad    = 1
groups   = 5
respawn  = esc_respawn_inventory_box_0002
END

; cse_shape properties
shapes        = shape0
shape0:type   = sphere
shape0:offset = 0,0,0
shape0:radius = 20.55957102775574

; cse_alife_space_restrictor properties
restrictor_type = 3

; se_smart_terrain properties

this is actually the most important stuff:


type     = esc_bandits_smart_terrain
cond     = {-infoportion}
capacity = 3
squad    = 1
groups   = 5
respawn  = esc_respawn_inventory_box_0002

'''type''' is a name of our new ST (required)
'''cond''' describes conditions which have to be met (optional)
'''capacity''' ST npcs/mutants quantity i.e. how many npcs/mutants our ST can handle (required)
'''squad, groups''' no idea what they are used for, maybe they are not used at all but i might be wrong (both are optional)
'''respawn''' name of the stash (blue box) where items will be spawn when ST respawn will be called (optional)

2. Spawning npcs/mutants and assigning (binding) them to our ST: in this case for each mutant/npc we have to add to its logic:


custom_data = < [smart_terrains]
esc_bandits_smart_terrain = true
END

3. Adding job (logic) for each npc/mutant from our ST (for each state). Let's say our ST have two states: state 0 (describes what npcs/mutants are doing during day) and state 1 (during night). We have 3 bandits, so say:

- bandit1: walker (state 0) and kamp (state 1)
- bandit2: guard (state 0) and sleeper (state 1)
- bandit3: walker (state 0 and 1 <= he's doing the same at day and night)

There are at least 3 ways to add logic (job) for each npc/mutant, we will use the most common one, i.e. we will add logic to config\misc\gulag_escape.ltx file. It may looks like this:


;-- bandit1 (walker -> state 0, i.e. during day)
[logic@esc_bandits_smart_terrain_bandit1_walker]
active = walker@esc_bandits_smart_terrain_bandit1

[walker@esc_bandits_smart_terrain_bandit1]
path_walk         = bandit1_walk
danger            = danger_condition@esc_bandits_smart_terrain
def_state_moving1 = patrol
def_state_moving2 = patrol
def_state_moving3 = patrol
meet              = no_meet

;-- bandit1 (kamp -> state 1, i.e. during night)
[logic@esc_bandits_smart_terrain_bandit1_kamp]
active = kamp@esc_bandits_smart_terrain_bandit1

[kamp@esc_bandits_smart_terrain_bandit1]
center_point = bandit_kamp
path_walk    = bandit_kamp_task

;-- bandit2 (guard -> state 0, i.e. during day)
[logic@esc_bandits_smart_terrain_bandit2_walker]
active = walker@esc_bandits_smart_terrain_bandit2

[walker@esc_bandits_smart_terrain_bandit2]
path_walk = bandit2_walk
path_look = bandit2_look
danger    = danger_condition@esc_bandits_smart_terrain

;-- bandit2 (sleeper -> state 1, i.e. during night)
[logic@esc_bandits_smart_terrain_bandit2_sleeper]
active = sleeper@esc_bandits_smart_terrain_bandit2

[sleeper@esc_bandits_smart_terrain_bandit2]
path_main = bandit2_sleep
wakeable  = false

;-- bandit3 (guard -> state 0 and 1, i.e. during day/night)
[logic@esc_bandits_smart_terrain_bandit3_walker]
active = walker@esc_bandits_smart_terrain_bandit3

[walker@esc_bandits_smart_terrain_bandit3]
path_walk = bandit3_walk
path_look = bandit3_look

[danger_condition@esc_bandits_smart_terrain]
ignore_distance_corpse = 0
ignore_distance        = 0

4. Now we have to script our ST. In this case we will add our code to scripts\gulag_escape.script file. There are several things we need to do here (each of this steps is required):

- load logic (jobs) for each npc/mutant, for each state -> function load_job(...)


if type == "esc_bandits_smart_terrain" then
    t = {}
    ;-- section is a "link" to logic defined in ltx file
    t.section = "logic@esc_bandits_smart_terrain_bandit1_walker"
    ;-- no idea, probably describes after what time
    ;-- npc will use this job again (?)
    t.idle = 0
    ;-- no idea but i guess it's optional
    t.timeout = 0
    ;-- priority
    t.prior = 100
    ;-- npc will use this logic if ST switched to this state
    ;-- in this case - state 0 (day)
    t.state = {0}
    ;-- no idea about squad and group
    t.squad = squad
    t.group = groups[1]
    ;-- no idea what means position_threshold
    t.position_threshold = 100
    ;-- describes whether npc in this state is online or offline
    ;-- online = true by default
    t.online = true
    ;-- describes restrictors (where npc can/can't go)
    t.in_rest = ""
    t.out_rest = ""
    ;-- because of the way how jobs are assigning by
    ;-- smart_terrain.script you never know which job
    ;-- will be used by which npc; if you want to ensure
    ;-- that certain job is used by certain npc then
    ;-- you have to use predicate function; in this case
    ;-- we want this job to be used by expert (master) bandit
    t.predicate = function(obj_info) return obj_info.rank >= 900 end
    table.insert(sj, t)

    t = {section = "logic@esc_bandits_smart_terrain_bandit1_kamp",
    idle = 0, timeout = 0, prior = 100, state = {1},squad = squad,
    group = groups[1], position_threshold = 100, online = true, in_rest = "",
    out_rest = "", predicate = function(obj_info) return obj_info.rank >= 900 end}
    table.insert(sj, t)

    ;-- bandit2 -> state 0 (day)
    t = {section = "logic@esc_bandits_smart_terrain_bandit2_walker",
    idle = 0, prior = 5, state = {0}, squad = squad, group = groups[1],
    in_rest = "", out_rest = ""}
    table.insert(sj, t)

    ;-- bandit2 -> state 1 (night)
    t = {section = "logic@esc_bandits_smart_terrain_bandit2_sleeper",
    idle = 0, prior = 5, state = {1}, squad = squad, group = groups[1],
    in_rest = "", out_rest = ""}
    table.insert(sj, t)

    ;-- bandit3 -> state 0 (day) and state 1 (night)
    t = {section = "logic@esc_bandits_smart_terrain_bandit3_walker",
    idle = 0, prior = 5, state = {0, 1}, squad = squad, group = groups[1],
    in_rest = "", out_rest = ""}
    table.insert(sj, t)
end

One more thing about ST states, it's up to you how many states your ST have. The important thing is to add logic for each state. For instance your ST can have those states:

0 - npcs are offline
1 - npcs are online (day)
2 - npcs are online (night)
3 - npcs are online, they decided to assault other ST
4 - npcs are online and actor attacks them

And another thing, i'm sick when i have to fill so many tables, so i usually use this function:


function fill_tbl(section, idle, prior, states, squad, group, in_rest, out_rest, online, gulag_name)
    local tbl = {}

    tbl.section = "logic@" .. gulag_name .. "_" .. section
    tbl.idle = idle
    tbl.prior = prior   
    tbl.state = {}

    for index = 1, #states do
        table.insert(tbl.state, states[index])
    end

    tbl.squad = squad
    tbl.group = group
    tbl.in_rest = in_rest
    tbl.out_rest = out_rest
    tbl.online = online
    return tbl
end

So using above function, we can load logic like this:


if type == "esc_bandits_smart_terrain" then
    local t = table.insert(sj, fill_tbl("bandit1_walker", 0, 100, {0}, squad, groups[1], "", "", true, type))
    t.timeout = 0
    t.position_threshold = 100
    t.predicate = function(obj_info) return obj_info.rank >= 900 end
    table.insert(sj, t)

    t = table.insert(sj, fill_tbl("bandit1_kamp", 0, 100, {1}, squad, groups[1], "", "", true, type))
    t.timeout = 0
    t.position_threshold = 100
    t.predicate = function(obj_info) return obj_info.rank >= 900 end
    table.insert(sj, t)

    table.insert(sj, fill_tbl("bandit2_walker", 0, 5, {0}, squad, groups[1], "", "", true, type))
    table.insert(sj, fill_tbl("bandit2_sleeper", 0, 5, {1}, squad, groups[1], "", "", true, type))
    table.insert(sj, fill_tbl("bandit3_walker", 0, 5, {0, 1}, squad, groups[1], "", "", true, type))
end

- automatically change job for each npc/mutant -> function load_states(...)


if type == "esc_bandits_smart_terrain" then
    return function(gulag)
        if not db.actor then
            return gulag.state
        end
        if level.get_time_hours() >= 5 and level.get_time_hours() <= 22 then
            return 0  -- switch all mutants/npc to daily job
        else
            return 1  -- switch all mutants/npc to nightly job
        end
    end
end

- ensure that our ST will be used only by bandits -> function checkStalker(...)


if gulag_type == "esc_bandits_smart_terrain" then
    return npc_community == "bandit"
end


==Links==
Discussion:
Gsc-game.com

Check our tool for smart terrain debugging and waypoint exporting:


Download:
Sdk.stalker-game.com

Mirror: Ifolder.ru

Post comment Comments
Chezzlor
Chezzlor Dec 6 2010, 12:14am says:

I'm no scripter nor modder. So to say the least, all that seems intimidating just to get a few active NPCs walking around smart terrain.

+2 votes     reply to comment
Hendar23
Hendar23 Dec 6 2010, 6:19pm replied:

I don't know why, but every time someone finds out just how hard making games is, it warms my heart. :)

+3 votes     reply to comment
xxx.xxx.xxx
xxx.xxx.xxx Dec 6 2010, 3:07am says:

position = 131.02030944824,0.065616846084595,-248.9094543457

this makes a lot of sense to me, is this perhaps yantar near the big oak tree :) NO I DON'T UNDERSTAND A WORD YOUR SAYING THERE BUT LIKE TO :)))

+6 votes     reply to comment
MacBradley
MacBradley Dec 6 2010, 5:08am says:

I've read this in the past on the STALKER wiki, and it was very helpful, so thank you for taking the time to write it!

Since I've been doing a lot of spawning on empty maps for RCOM, I was thinking about updating the wiki eventually and making an article more relevant to Call of Pripyat, since there aren't many articles on it and I spent a lot of time figuring figuring out the particulars of it. I know how much time can be saved having the process explained in a tutorial versus figuring it out, and the tutorials you guys have wrote have saved me much time in the past so I hope to do the same soon!

+2 votes     reply to comment
dezodor
dezodor Dec 6 2010, 6:27am replied:

well if you update it, pls make an other entry, and mb rename the old as smart terrain tutorial (soc) and call yours as smart terrain tutorial (cop) :) this way wiki will have more articles, and also ppl wont get confused.

+3 votes     reply to comment
MacBradley
MacBradley Dec 6 2010, 8:04am replied:

Oh yea, I would name it appropriately, of course! :)

Don't know if you've looked at CoP's scripts much yet, but if walkers and guards have their way points named appropriately, a basic default logic is applied and one doesn't need to be manually defined. I don't know if ShoC has this (I never knew if so), but it sure is convenient for quickly creating non-exclusive alife jobs for simulation smart terrains.

+1 vote     reply to comment
dezodor
dezodor Dec 6 2010, 6:25am says:

yep, it was on stk wiki since 2years, we just saw its possible to drop here tutorials too, so we will slowly port all our tuts from wiki to this site.

+4 votes     reply to comment
Shadowracer
Shadowracer Dec 6 2010, 8:54am replied:

Thank you, Dez0wave, for doing this. I think this will be very helpful for lots of people (including me) on their way to create nice mods and improve stalker mods quality. :)

+2 votes     reply to comment
este
este Dec 8 2010, 10:19am says:

Whaaat a tutorial?! nice!

+1 vote     reply to comment
Vodkin
Vodkin Jan 1 2011, 7:17am says:

Nice of you, it's really useful!

+2 votes     reply to comment
Post a Comment
click to sign in

You are not logged in, your comment will be anonymous unless you join the community today (totally free - or sign in with your social account on the right) which we encourage all contributors to do.

2000 characters limit; HTML formatting and smileys are not supported - text only

Icon
S.T.A.L.K.E.R. Shadow of Chernobyl Icon
Platform
Windows
Developer
dez0wave
Contact
Send Message
Official Page
Dezowave.com
Release Date
Coming Apr 25, 2014
Mod Watch
Track this mod
Tutorial
Browse
Tutorials
Report Abuse
Report article
Related Mods
Related Games
S.T.A.L.K.E.R. Shadow of Chernobyl
S.T.A.L.K.E.R. Shadow of Chernobyl Single & Multiplayer First Person Shooter
Related Groups
dez0wave
dez0wave Developer & Publisher with 26 members