SoC. Смартеррейны и гулаги
Материал из S.T.A.L.K.E.R. Inside Wiki
В последнее время люди постоянно меня спрашивали как создать скрипт гулага для смартеррейнов. Чтобы постоянно не отвечать на каждое отдельное письмо, я решил написать небольшой тутор. Прежде чем начать, хотелось бы предупредить, что не являюсь экспертом в подобного рода вещах и некоторые моменты мне всё еще не ясны до конца, так что вероятно я не смогу объяснить всё правильно. Также я буду использовать ST как абревиатуру смартеррейна. Этот тутор посвящен НПС в ST, но он также сгодится и для мутантов. Предполагаю что вы знакомы с:
- луа программированием
- редактированием all.spawn
- работа с вейпоинтами(патрульными путями)
- утилитами аи
В первую очередить подумайте о своём ST, где бы его заспавнить, сколько нпс/мутантов будут в нем выполнять определенную "работу", когда ST должен активироваться/отключаться, сколько и какие состояния будет у вашего ST и тд. Думаю, наиболее эффективный способ объяснить вам как это работает на примере. Давайте предположим.. мы хотим поставить ST(smart terrain) на Кордоне для 3х бандитов.
1. Спавн 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 = <<END [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
Эта наиболее важная часть:
type = esc_bandits_smart_terrain cond = {-infoportion} capacity = 3 squad = 1 groups = 5 respawn = esc_respawn_inventory_box_0002</source>
type название вашего нового ST(обязательно)
cond описывает условия, которые необходимы для выполнения(по желанию)
capacity количество мутантов/нпс, которое может вместить смарттеррейн(обязательно)
squad, groups - номер сквада и количество групп(по желанию)
respawn название тайника(синяя коробка) куда будут спавниться предметы, когда мы вызовем респавн в ST.(по желанию)
name of the stash (blue box) where items will be spawn when ST respawn will be called (optional)
2. Спавн нпс/мутантов и назначение(биндинг) их к нашему ST: для этого мы должны добавить каждому мутанту/нпс определенную логику:
custom_data = <<END [smart_terrains] esc_bandits_smart_terrain = true END
... переведу потом, loxotron
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
Author
Ссылки
Используйте нашу утилиту для дебаггинга смартеррейнов и экспорта вейпоинтов:
Скачать: http://sdk.stalker-game.com/ru/images/d/d7/Smartterrain_and_Waypoint_Tools_by_dez0wave.zip
Зеркало: http://ifolder.ru/7179080