Это секция под номером 982
|
Сперва создадим троих NPC для нашего сквада;
В файле gamedata\configs\gameplay\character_desc_zaton.xml описываем наших персонажей.
<specific_character id="zat_a1_stalker_cop" team_default="1">
<name>st_zat_a1_stalker_cop_name</name>
<icon>ui_inGame2_Gluhar</icon>
<map_icon x="1" y="0">
</map_icon>
<bio>Опытный сталкер. Детальная информация отсутствует.</bio>
<class>zat_a1_stalker_cop</class>
<community>stalker</community>
<terrain_sect>stalker_terrain</terrain_sect>
<snd_config>characters_voice\human_02\stalker\</snd_config>
<rank>55</rank>
<reputation>0</reputation>
<money min="8000" max="8000" infinitive="0" />
<visual>actors\stalker_neutral\stalker_neutral_2_face_2</visual>
<supplies>
[spawn] \n
wpn_ak74u \n
ammo_5.45x39_fmj = 1 \n
wpn_pm \n
ammo_9x18_pmm = 1 \n
#include "gameplay\character_items_nd.xml"
#include "gameplay\character_food.xml"
#include "gameplay\character_drugs_2.xml"
</supplies>
#include "gameplay\character_criticals_4.xml"
<start_dialog>zat_b38_stalker_cop_start_dialog</start_dialog>
<actor_dialog>zat_a2_stalker_barmen_b7_actor_start</actor_dialog>
<actor_dialog>zat_b38_stalker_cop_task_dialog</actor_dialog>
<actor_dialog>zat_b38_cop_about_himself_dialog</actor_dialog>
<actor_dialog>zat_b38_stalker_cop_b52_about_nimble</actor_dialog>
<actor_dialog>zat_b38_stalker_cop_b52_about_snag</actor_dialog>
<actor_dialog>zat_b38_stalker_cop_about_sci_guards</actor_dialog>
<actor_dialog>zat_b38_stalker_cop_about_sci_helpers</actor_dialog>
<actor_dialog>actor_break_dialog</actor_dialog>
</specific_character>
<specific_character id="zat_a1_helper_1" team_default="1">
<name>zat_a1_helper_1_name</name>
<icon>ui_inGame2_neutral_2</icon>
<map_icon x="1" y="0">
</map_icon>
<bio>Опытный сталкер. Детальная информация отсутствует.</bio>
<class>zat_a1_helper_1</class>
<community>stalker</community>
<terrain_sect>stalker_terrain</terrain_sect>
<snd_config>characters_voice\human_03\stalker\</snd_config>
<rank>35</rank>
<reputation>0</reputation>
<visual>actors\stalker_neutral\stalker_neutral_2</visual>
<supplies>
[spawn] \n
wpn_binoc \n
detector_advanced = 1 \n
device_torch \n
wpn_mp5 \n
wpn_beretta = 1 \n
ammo_9x19_fmj = 1 \n
af_fireball = 1 \n
</supplies>
<start_dialog>zat_b53_artefact_hunter_1_gathering_artefacts</start_dialog>
#include "gameplay\character_criticals_4.xml"
#include "gameplay\character_dialogs_no_guide.xml"
</specific_character>
<specific_character id="zat_a1_helper_2" team_default="1">
<name>zat_a1_helper_2_name</name>
<icon>ui_inGame2_neutral_1</icon>
<map_icon x="1" y="0">
</map_icon>
<bio>Опытный сталкер. Детальная информация отсутствует.</bio>
<class>zat_a1_helper_2</class>
<community>stalker</community>
<terrain_sect>stalker_terrain</terrain_sect>
<snd_config>characters_voice\human_02\stalker\</snd_config>
<rank>20</rank>
<reputation>0</reputation>
<visual>actors\stalker_neutral\stalker_neutral_1</visual>
<supplies>
[spawn] \n
wpn_toz34 \n
ammo_12x70_buck = 1 \n
wpn_pm \n
ammo_9x19_fmj = 1 \n
medkit = 1 \n
#include "gameplay\character_items_nd.xml"
#include "gameplay\character_food.xml"
</supplies>
<start_dialog>zat_b53_artefact_hunter_2_gathering_artefacts</start_dialog>
#include "gameplay\character_criticals_4.xml"
#include "gameplay\character_dialogs.xml"
</specific_character>
|
Теперь в файле gamedata\configs\gameplay\npc_profile.xml зарегистрируем классы за определенными NPC
<character id="zat_a1_stalker_cop">
<class>zat_a1_stalker_cop</class>
</character>
<character id="zat_a1_helper_1">
<class>zat_a1_helper_1</class>
</character>
<character id="zat_a1_helper_2">
<class>zat_a1_helper_2</class>
</character>
|
Также в файле gamedata\configs\creatures\spawn_sections_zaton.ltx, пропишем новым персонажам секции для спавна
[zat_a1_stalker_cop]:stalker
$spawn = "respawn\zat_a1_stalker_cop"
character_profile = zat_a1_stalker_cop
spec_rank = regular
community = stalker
story_id = zat_a1_stalker_cop
[zat_a1_helper_1]:stalker
$spawn = "respawn\zat_a1_helper_1"
character_profile = zat_a1_helper_1
spec_rank = regular
community = stalker
story_id = zat_a1_helper_1
[zat_a1_helper_2]:stalker
$spawn = "respawn\zat_a1_helper_2"
character_profile = zat_a1_helper_2
spec_rank = regular
community = stalker
story_id = zat_a1_helper_2
|
Создаем сквад
Зарегистрируем наших NPC в новый сквад, в файле gamedata\configs\misc\squad_descr_zaton.ltx
[zat_a1_brigada_squad]:online_offline_group
faction = stalker
target_smart = zat_a1
spawn_point = zat_a1_walker_3_walk
npc = zat_a1_stalker_cop, zat_a1_helper_1, zat_a1_helper_2
|
Добавим наш сквад в симуляцию, через файл gamedata\configs\misc\simulation_objects_props.ltx
;--------- ZATON UNIQUE SQUADS --------
[zat_a1_brigada_squad]:default_squad
sim_avail = false
|
Внимание! Мы не будем прописывать наш сквад в стартовую позицию Затона т.к. спавнить будем функцией "create_squad" которую поместим в логику спейс-рестриктора.
Это будет альтернативой всеми нами любимого скрипта alife():create("...")
Создаем Space_Restricor в All.spawn
Добавим в файл gamedata\spawns\alife_zaton.ltx следующую секцию
[20000]
; cse_abstract properties
section_name = space_restrictor
name = zat_a1_spawner
position = 244.724090576172,18.1142883300781,530.155517578125
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 292
distance = 0
level_vertex_id = 1385170
object_flags = 0xffffff3e
custom_data = <<END
[logic]
cfg = scripts\zaton\zat_a1_spawner.ltx
END
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 1
; cse_alife_space_restrictor properties
restrictor_type = 3
|
Секцию можно воткнуть и в начало файла. Место расположения рестриктора чуть вперед от начальной точки спавна ГГ в начале игры, между
наклоненным сухим деревом и камнем, чтобы сработала логика, надо пройти между ними.
Создаем логику рестриктора в файле gamedata\configs\scripts\zaton\zat_a1_spawner.ltx
[logic]
active = sr_idle@spawn_stalker
[sr_idle@spawn_stalker]
on_info = {=actor_in_zone(zat_a1_spawner)} sr_idle@item_spawn %=create_squad(zat_a1_brigada_squad:zat_a1)%
[sr_idle@item_spawn]
on_game_timer = 150 | sr_idle@nil %=spawn_object(disel_generator:zat_a1_walker_4_walk)%
[sr_idle@nil]
|
В логику рестриктора добавил еще функцию "spawn_object" для спавна предметов (кому-то на голову свалится дизель-генератор через 15 секунд после спавна сквада)
Так-же обратите внимание на то, что в логике рестриктора можно указать или смарт-террейн для спавна (zat_a1_brigada_squad:zat_a1) или точку пути (disel_generator:zat_a1_walker_4_walk).
Пока все. Собираем - запускаем - наблюдаем.
Логику чувакам пока не подключал - делается так-же как и для одиночного эксклюзива.
Но пока стоит обратить внимание на то, что и без логики, если у командира сквада нормальные диалоги с инфопоршнями и прочим для выдачи квестов, то и дефолтная пойдет для простых сцен.
|
Через логику. Каждый боец (однотипная группа бойцов) имеет свою "кастом дату". Именно в ней прописывается логика действий. Собственно - последовательность реакций на условия, определяемые инфопоршнями или прекондишенами. А последовательность реакций - это вызовы функций, собранных в скриптах с префиксом xr_ . Вот простейшая логика перса, которую мы разбирали в школе в соседней теме:
[logic]
active = move@trader
[move@trader]
invulnerable = true
on_combat = combat
meet = meet_sgm
[combat]
combat_type = camper
[meet_sgm]
abuse = false
use = true
allow_break = false
meet_on_talking = false
Активная секция одна, может воевать как кемпер, говорить при юзе, бессмертен. Всё.
|
Распаковываем All.spawn и в alife_локация.ltx добавить:
[866] - уникальный ID
; cse_abstract properties
section_name = inventory_box - имя секции (не трогать)
name = level_prefix_inventory_box_0000 имя (можно не изменять)
position = -447.109985351563,-6.13000011444092,183.639999389648 (координаты тайника - x, y, z)
direction = -0.062830001115799,-2.99324011802673,-0.169295996427536 (куда направлен)
; cse_alife_object properties
game_vertex_id = 0 - game_vertex
distance = 0
level_vertex_id = 293223 - level_vertex
object_flags = 0xffffff3f
custom_data = <<END
[spawn] вещи в тайнике
wpn_pb
wpn_ak74
ammo_9x18_pmm
medkit_army
drug_antidot
END
; cse_visual properties
visual_name = dynamics\devices\dev_rukzak\dev_rukzak.ogf визуал тайника (рюкзак)
; cse_alife_inventory_box properties
tip = inventory_box_use
Синим выделено то, что можно\нужно изменить.
|
Распаковываем all.spawn и в файл alife_локация.ltx в конец добавляем:
[уникальный ID]
; cse_abstract properties
section_name = level_changer
name = имя перехода
position = x,y,z перехода
direction = 0,0,0
cse_abstract__unk1_h16 = 0x1
; cse_alife_object properties
game_vertex_id = game vertex перехода
distance = 0
level_vertex_id = level vertex перехода
object_flags = 0xffffff3e
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 0.50760293006897
; cse_alife_space_restrictor properties
restrictor_type = 3
; cse_alife_level_changer properties
dest_game_vertex_id = Game vertex места куда переместимся
dest_level_vertex_id = Level vertex локации куда переместимся
dest_position = x,y,z места куда переместимся
dest_direction = 0,0,0
dest_level_name = локация на которую переместимся
silent_mode = 1
; se_level_changer properties
|
1. | Создать объект. Визуал не важен |
3. | Создать рестриктор в All.spawn. Вот из мода: |
[5370]
; cse_abstract properties
section_name = space_restrictor
name = jup_freedom_radio_mod_00181 --имя рестриктора
position = -45.4620018005371,3.47900009155273,218.572998046875
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 339
distance = 0
level_vertex_id = 643188
object_flags = 0xffffff3e
custom_data = <<END
[logic]
cfg = scripts\SGM\jupiter\restrictors\jup_freedom_radio.ltx --ссылка на логику
END
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 10
; cse_alife_space_restrictor properties
restrictor_type = 3
4. | Прописать к рестриктору логику. Из мода это |
[logic]
active = sr_universal
[sr_universal]
scheme_type = sound_zone --буквально, зона звука. Предназначение, как я понимаю, рестриктора.
sound_zone_theme = radio_music\radio_music_5,radio_music\radio_music_10 --перечень фалов, играемых в зоне. Из той самой папки.
sound_zone_stop_info = zat_bandit_radio_stop --инфопоршень при наличии которого музыка не проигрывается.
Если хотите, чтобы он еще и включался выключался, то надо прописать диалог с выдачей инфопоршня или назначить его выдачу на клавишу.
|
в секцию [meet] логики NPC добавляем строчку
meet_on_talking = true
|
[logic]
active = remark
[remark]
combat_ignore = {=actor_enemy, !hit_npc_from_actor} combat_ignore
[combat_ignore]
|
На примере Кордона.
Создадим смарттеррейн для нашего сквада, в файле gamedata\spawns\alife_escape.ltx
[7076] -- Уникальный ID секции
section_name = smart_terrain
name = esc_smart_terrain_3_16 -- Имя смарта
position = -134.241699218,-30.13801574707,-377.1673889160 -- Позиция (X,Y,Z)
direction = 0,0.02057,0 -- Направление взгляда, оси (X,Y,Z)
version = 0x7c
script_version = 8
game_vertex_id = 934 -- Game Vertex ID
distance = 0
level_vertex_id = 25 -- Level Vertex ID
object_flags = 0xffffff3e
custom_data = <<END
[smart_terrain]
cfg = scripts\escape\smart\esc_smart_terrain_3_16.ltx -- Путь к логике смарта (относительно папки configs)
END
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 2
restrictor_type = 3
|
Теперь зарегистрируем точки путей для наших сталкеров в файле gamedata\spawns\way_escape.ltx
WayPoints
Напишем нашу логику для смарттеррейна в файле configs\scripts\escape\smart\esc_smart_terrain_3_16.ltx
[smart_terrain];esc_smart_terrain_3_16
squad_id = 2
max_population = 4
;здесь можно респавн еще прописать
|
Создаем сквад военных, для этого занесем эти секции в файл gamedata\configs\misc\squad_descr_escape.ltx
[esc_military_2_squad_0]:online_offline_group ; Имя секции с родителем
faction = stalker ; Группировка
npc = sim_default_military_0 ; NPC в скваде (указывать через запятую)
target_smart = esc_smart_terrain_3_16 ; Целевой смарт, на нем они и будут находиться
spawn_point = esc_smart_terrain_4_13_spawn_point ; Точка спавна (спавн идет через WayPoint)
story_id = esc_military_2_squad_0 ; StoryID сквада
[esc_military_2_squad_1]:online_offline_group
faction = stalker
npc = sim_default_military_2, sim_default_military_2, sim_default_military_2, sim_default_military_2, sim_default_military_2
target_smart = esc_smart_terrain_3_16
spawn_point = esc_smart_terrain_4_13_spawn_point
story_id = esc_military_2_squad_1
[esc_military_2_squad_2]:online_offline_group
faction = stalker
npc = sim_default_military_2, sim_default_military_2, sim_default_military_2, sim_default_military_2, sim_default_military_2
target_smart = esc_smart_terrain_3_16
spawn_point = esc_smart_terrain_4_13_spawn_point
story_id = esc_military_2_squad_2
|
Также добавляем сквады в симуляцию через файл gamedata\configs\misc\simulation_objects_props.ltx
--------------вояки---------------
[esc_military_2_squad_0]:default_squad
sim_avail = false
[esc_military_2_squad_1]:default_squad
sim_avail = false
[esc_military_2_squad_2]:default_squad
sim_avail = false
|
Спавнить сквад будем в симуляции, то есть он появится сразу после Новой игры.
Для этого откроем файл gamedata\configs\misc\simulation.ltx и добавим
[start_position_escape] ; Если не появятся - заккоментировать эту строку
esc_military_2_squad_0 = esc_smart_terrain_3_16
esc_military_2_squad_1 = esc_smart_terrain_3_16
esc_military_2_squad_2 = esc_smart_terrain_3_16
|
|
На примере Юпитера:
Заменяем все содержимое файла jup_crow_spawner.ltx на это
[logic]
active = sr_crow_spawner
[sr_crow_spawner]
max_crows_on_level = 2
spawn_path = jup_crow_spawn_1
Также можно поудалять все Spawn_path из way_локация.ltx
|
function spawn_zaton_anomalies(zaton_anomalies_sect)
for i=1,150 do
local anomalies = {"zone_mine_acidic_weak","zone_mine_acidic_average","zone_mine_acidic_strong",
"zone_mine_acidic_big","zone_mine_chemical_weak","zone_mine_chemical_average","zone_mine_chemical_strong",
"zone_buzz_weak","zone_buzz_average","zone_buzz_strong","zone_mine_electric_weak","zone_mine_electric_average",
"zone_mine_electric_strong","zone_witches_galantine_weak","zone_witches_galantine_average","zone_witches_galantine_strong",
"zone_mine_gravitational_average","zone_mine_gravitational_weak","zone_mine_gravitational_big","zone_gravi_zone",
"zone_mine_thermal_weak","zone_mine_thermal_average","zone_mine_thermal_strong","zone_mine_steam_weak",
"zone_mine_steam_average","zone_mine_steam_strong","zone_zharka_static_weak","zone_zharka_static_average",
"zone_zharka_static_strong"}
local zaton_anomalies_sect = anomalies[math.random(#anomalies)]
z_anom(zaton_anomalies_sect)
end
end
function z_anom(zaton_anomalies_sectt)
lv_new = math.random(1700000)
pos_new = level.vertex_position(lv_new)
create_anomalies(zaton_anomalies_sectt,3,pos_new.x,pos_new.y,pos_new.z,lv_new,0)
end
function create_anomalies(section,rad_anom,x,y,z,lv,gv,mode)
if gv==nil then gv=db.actor:game_vertex_id() end
if lv==nil then lv=db.actor:level_vertex_id() end
if pos==nil then pos=db.actor:position() end
local p_obj = alife():create(section,vector():set(x,y,z),lv,gv)
local packet = net_packet()
packet:w_begin(0)
p_obj:STATE_Write(packet)
packet:r_seek(2)
local game_vertex_id = packet:r_u16()
local cse_alife_object__unk1_f32 = packet:r_float()
local cse_alife_object__unk2_u32 = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local cse_alife_object__unk3_u32 = packet:r_s32()
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
local center = packet:r_vec3()
local radius = packet:r_float()
else
local box = packet:r_matrix()
end
end
local restrictor_type = packet:r_u8()
local cse_alife_custom_zone__unk1_f32 = packet:r_float()
local cse_alife_custom_zone__unk2_u32 = packet:r_s32()
local on_off_mode_enabled_time = packet:r_s32()
local on_off_mode_disabled_time = packet:r_s32()
local on_off_mode_shift_time = packet:r_s32()
local offline_interactive_radius = packet:r_float()
local artefact_spawn_places_count = packet:r_u16()
local cse_alife_anomalous_zone__unk1_u32 = packet:r_s32()
local last_spawn_time_present = packet:r_u8()
packet:w_u16(game_vertex_id)
packet:w_float(cse_alife_object__unk1_f32)
packet:w_s32(cse_alife_object__unk2_u32)
packet:w_s32(level_vertex_id)
packet:w_s32(object_flags)
if mode~=nil then custom_data = mode end
packet:w_stringZ(custom_data)
packet:w_s32(story_id)
packet:w_s32(cse_alife_object__unk3_u32)
packet:w_u8(1)
packet:w_u8(0)
local sphere_center = vector()
sphere_center:set(0, 0, 0)
packet:w_vec3(sphere_center)
radius = rad_anom
packet:w_float(radius)
packet:w_u8(restrictor_type)
packet:w_float(cse_alife_custom_zone__unk1_f32)
cse_alife_custom_zone__unk2_u32 = bit_not(0)
packet:w_s32(cse_alife_custom_zone__unk2_u32)
packet:w_s32(on_off_mode_enabled_time)
packet:w_s32(on_off_mode_disabled_time)
packet:w_s32(on_off_mode_shift_time)
packet:w_float(offline_interactive_radius)
packet:w_u16(artefact_spawn_places_count)
packet:w_s32(cse_alife_anomalous_zone__unk1_u32)
if mode == nil then
packet:w_u8(last_spawn_time_present)
end
p_obj:STATE_Read(packet, packet:w_tell()-packet:r_tell())
return p_obj
end
|
function create_anom(section,rad_anom,x,y,z,lv,gv,mode,time1,time2)
if gv==nil then gv=db.actor:game_vertex_id() end
if lv==nil then lv=db.actor:level_vertex_id() end
if pos==nil then pos=db.actor:position() end
local p_obj = alife():create(section,vector():set(x,y,z),lv,gv)
local packet = net_packet()
packet:w_begin(0)
p_obj:STATE_Write(packet)
packet:r_seek(2)
local game_vertex_id = packet:r_u16()
local cse_alife_object__unk1_f32 = packet:r_float()
local cse_alife_object__unk2_u32 = packet:r_s32()
local level_vertex_id = packet:r_s32()
local object_flags = packet:r_s32()
local custom_data = packet:r_stringZ()
local story_id = packet:r_s32()
local cse_alife_object__unk3_u32 = packet:r_s32()
local shape_count = packet:r_u8()
for i=1,shape_count do
local shape_type = packet:r_u8()
if shape_type == 0 then
local center = packet:r_vec3()
local radius = packet:r_float()
else
local box = packet:r_matrix()
end
end
local restrictor_type = packet:r_u8()
local cse_alife_custom_zone__unk1_f32 = packet:r_float()
local cse_alife_custom_zone__unk2_u32 = packet:r_s32()
local on_off_mode_enabled_time = packet:r_s32()
local on_off_mode_disabled_time = packet:r_s32()
local on_off_mode_shift_time = packet:r_s32()
local offline_interactive_radius = packet:r_float()
local artefact_spawn_places_count = packet:r_u16()
local cse_alife_anomalous_zone__unk1_u32 = packet:r_s32()
local last_spawn_time_present = packet:r_u8()
packet:w_u16(game_vertex_id)
packet:w_float(cse_alife_object__unk1_f32)
packet:w_s32(cse_alife_object__unk2_u32)
packet:w_s32(level_vertex_id)
packet:w_s32(object_flags)
if mode~=nil then custom_data = mode end
packet:w_stringZ(custom_data)
packet:w_s32(story_id)
packet:w_s32(cse_alife_object__unk3_u32)
packet:w_u8(1)
packet:w_u8(0)
local sphere_center = vector()
sphere_center:set(0, 0, 0)
packet:w_vec3(sphere_center)
radius = rad_anom
packet:w_float(radius)
packet:w_u8(restrictor_type)
packet:w_float(cse_alife_custom_zone__unk1_f32)
cse_alife_custom_zone__unk2_u32 = bit_not(0)
packet:w_s32(cse_alife_custom_zone__unk2_u32)
if time1 ~= nil then
packet:w_s32(time1)
else
packet:w_s32(on_off_mode_enabled_time)
end
if time2 ~= nil then
packet:w_s32(time2)
else
packet:w_s32(on_off_mode_disabled_time)
end
packet:w_s32(on_off_mode_shift_time)
packet:w_float(offline_interactive_radius)
packet:w_u16(artefact_spawn_places_count)
packet:w_s32(cse_alife_anomalous_zone__unk1_u32)
if mode==nil then
packet:w_u8(last_spawn_time_present)
else
end
p_obj:STATE_Read(packet, packet:w_tell()-packet:r_tell())
return p_obj
end
|
section - секция аномалии из конфигов
rad_anom - радиус аномалии (3 норма)
x - перваяя координата х
y - вторая координата у
z - третья координата z
lv - Level vertex
gv - Game vertex
mode - если используете поля, то нужно писать "filed", если обычные аномалии то nil
time1 - время работы в мс (1 с = 1000 мс)
time2 - время неработы в мс (1 с = 1000 мс)
если постоянно, то в обоих ставте nil
|
Добавим секцию спавна в файл spawns\alife_локация.ltx
[5672] ; Уникальный ID секции
section_name = stalker
name = gamer ; Имя секции
position = 243.661834716797,16.4937133789063,506.856964111328 ; Позиция по X,Y,Z
direction = 0,0,0
version = 0x7c
script_version = 8
money = 5000
character_profile = sim_default_stalker_4 ; ссылка на профиль для спавна (профиля берутся из character_desc_*.xml)
cse_alife_trader_abstract__unk1_u8 = 6
game_vertex_id = 52429 ; Game Vertex
distance = 1.15511835011223
direct_control = 416481280
level_vertex_id = 4290707477 ; Level Vertex
object_flags = 0x203bffff
custom_data = <<END
[smart_terrains]
none = true ; Будет ли использовать гулаги: true - нет, false - да (по умолчанию)
[spawn] ; вещи в инвентаре
bread
kolbasa
wpn_pb
ammo_9x18_fmj
hand_radio
medkit
vodka
wpn_vintorez
wpn_pkm
[logic]
cfg = scripts\zaton\stalker_gamer.ltx ; ссылка на логику, относительно папки configs
[task_manager]
reward = stalker
[spawner]
cond = true ; Условия спавна (Например: = {+my_info} true, false - NPC будет спавниться только при наличии инфопоршня "my_info")
END
visual_name = actors\stalker_neutral\stalker_neutral_1 ; Визуал, не имеет значения, так как читает из профиля
g_team = 0
g_squad = 0
g_group = 0
health = 1
dynamic_out_restrictions =
dynamic_in_restrictions =
upd:health = 1
upd:timestamp = 0
upd:creature_flags = 0
upd:position = 243.661834716797,16.4937133789063,506.856964111328 ; Позиция равная указанной выше
upd:o_model = 0
upd:o_torso = 0,0,0
upd:g_team = 0
upd:g_squad = 0
upd:g_group = 0
upd:next_game_vertex_id = 65535 ; Game Vertex ID
upd:prev_game_vertex_id = 65535 ; Game Vertex ID
upd:distance_from_point = 0
upd:distance_to_point = 0
predicate5 = 1,1,1,0,2
predicate4 = 0,1,0,1
upd:start_dialog =
|
Теперь расставим точки путей для нашего NPC, это сделаем в файле way_локация.ltx
[gamer_1_look]
points = p0,p1,p2
p0:name = name00|a=hide
p0:flags = 0x2
p0:position = 239.727722167969,14.4487590789795,499.2287769317627
p0:game_vertex_id = 6
p0:level_vertex_id = 1375126
p1:name = name01|a=hide
p1:flags = 0x1
p1:position = 235.727722167969,14.4487590789795,499.2287769317627
p1:game_vertex_id = 6
p1:level_vertex_id = 1375126
p2:name = name02|a=hide
p2:flags = 0x1
p2:position = 230.727722167969,14.4487590789795,499.2287769317627
p2:game_vertex_id = 6
p2:level_vertex_id = 1375126
[gamer_1_walk]
points = p0,p1,p2,p3,p4
p0:name = name00
p0:position = 239.727722167969,14.4487590789795,499.2287769317627
p0:game_vertex_id = 6
p0:level_vertex_id = 1375126
p0:links = p1(1)
p1:name = name01|a=sneak|t=300
p1:position = 230.727722167969,14.4487590789795,494.2287769317627
p1:game_vertex_id = 6
p1:level_vertex_id = 1359863
p1:links = p2(1)
p2:name = name02
p2:position = 223.727722167969,14.4487590789795,486.2287769317627
p2:game_vertex_id = 6
p2:level_vertex_id = 1346067
p2:links = p3(1)
p3:name = name03|a=raid
p3:position = 222.727722167969,14.4487590789795,479.2287769317627
p3:game_vertex_id = 6
p3:level_vertex_id = 1344790
p3:links = p4(1)
p4:name = name04
p4:position = 245.727722167969,14.4487590789795,493.2287769317627
p4:game_vertex_id = 6
p4:level_vertex_id = 1386371
p4:links = p0(1)
|
Напишем нашему персонажу логику, в файле configs\scripts\zaton\stalker_gamer.ltx
[logic]
active = camper
[camper]
path_walk = gamer_1_walk
path_look = gamer_1_look
radius = 5
sniper = true
|
|
Пропишем нужному нам смарт-терейну укрытие в файле gamedata\configs\misc\simulation_objects_props.ltx
[esc_sim_13]:default
surge = 1 ; прописали возможность укрытия
territory = 1
sim_avail = true
Зарегистрируем наше укрытие в файле gamedata\configs\misc\surge_manager.ltx
;escape
esc_surge_hide_sim_13
Зарегистрируем нашу локацию в скриптах:
Файл: gamedata\scripts\sim_board.script
--'******************************************************
--'* Реестр смарт-террейнов. Игровое поле симуляции.
--'******************************************************
--' В этом ltx хранятся дескрипторы сквадов.
squad_ltx = system_ini()
setting_ini = ini_file("misc\\simulation.ltx")
local group_id_by_levels = {zaton = 1,
pripyat = 2,
jupiter = 3,
labx8 = 4,
jupiter_underground = 5,
escape = 6}
Файл: gamedata\scripts\smart_terrain.script
строка 1196
function surge_stats()
local sim_obj_registry = simulation_objects.get_sim_obj_registry().objects
local sim_squads = {
["zaton"] = {},
["jupiter"] = {},
["pripyat"] = {},
["escape"] = {}
}
local sim_smarts = {
["zaton"] = {},
["jupiter"] = {},
["pripyat"] = {},
["escape"] = {}
}
строка 1241
print_smarts_and_squads_by_level("zaton")
print_smarts_and_squads_by_level("jupiter")
print_smarts_and_squads_by_level("pripyat")
print_smarts_and_squads_by_level("escape")
Файл: gamedata\scripts\surge_manager.script
строка 38
self.levels_respawn = {zaton = false, jupiter = false, pripyat = false, escape = false}
строка 194
xr_sound.set_sound_play(db.actor:id(), "zat_a2_stalker_barmen_after_surge")
elseif(level.name()=="jupiter") then
xr_sound.set_sound_play(db.actor:id(), "jup_a6_stalker_medik_after_surge")
elseif not has_alife_info("pri_b305_fifth_cam_end") then
xr_sound.set_sound_play(db.actor:id(), "pri_a17_kovalsky_after_surge")
elseif(level.name()=="escape") then
xr_sound.set_sound_play(db.actor:id(), "zat_a2_stalker_barmen_after_surge")
строка 249
if(level.name()=="zaton") then
xr_sound.set_sound_play(db.actor:id(), "zat_a2_stalker_barmen_surge_phase_2")
elseif(level.name()=="jupiter") then
xr_sound.set_sound_play(db.actor:id(), "jup_a6_stalker_medik_phase_2")
elseif not has_alife_info("pri_b305_fifth_cam_end") then
xr_sound.set_sound_play(db.actor:id(), "pri_a17_kovalsky_surge_phase_2")
elseif(level.name()=="escape") then
xr_sound.set_sound_play(db.actor:id(), "zat_a2_stalker_barmen_surge_phase_2")
строка 273
if(level.name()=="zaton") then
xr_sound.set_sound_play(db.actor:id(), "zat_a2_stalker_barmen_surge_phase_1")
elseif(level.name()=="jupiter") then
xr_sound.set_sound_play(db.actor:id(), "jup_a6_stalker_medik_phase_1")
elseif not has_alife_info("pri_b305_fifth_cam_end") then
xr_sound.set_sound_play(db.actor:id(), "pri_a17_kovalsky_surge_phase_1")
elseif(level.name()=="escape") then
xr_sound.set_sound_play(db.actor:id(), "zat_a2_stalker_barmen_surge_phase_1")
строка 329
self.levels_respawn = {zaton = true, jupiter = true, pripyat = true, escape = true}
строка 352
self.levels_respawn = {zaton = true, jupiter = true, pripyat = true, escape = true}
строка 638
packet:w_bool(self.levels_respawn.zaton)
packet:w_bool(self.levels_respawn.jupiter)
packet:w_bool(self.levels_respawn.pripyat)
packet:w_bool(self.levels_respawn.escape)
строка 665
self.levels_respawn.zaton = packet:r_bool()
self.levels_respawn.jupiter = packet:r_bool()
self.levels_respawn.pripyat = packet:r_bool()
self.levels_respawn.escape = packet:r_bool()
переходим к all.spawn - создаем секцию укрытия в файле alife_escape.ltx
[xxxx]
; cse_abstract properties
section_name = space_restrictor
name = esc_surge_hide_sim_13
position = -11.2279901504517,2.46390247344971,57.3380393981934
direction = 0,0,0
version = 0x7c
script_version = 8
; cse_alife_object properties
game_vertex_id = 934
distance = 0
level_vertex_id = 3366
object_flags = 0xffffff3e
; cse_shape properties
shapes = shape0
shape0:type = box
shape0:axis_x = 3.27519989013672,0,0
shape0:axis_y = 0,5.44060039520264,0
shape0:axis_z = 0,0,7.41159915924072
shape0:offset = 0,0,0
; cse_alife_space_restrictor properties
restrictor_type = 0
Создаем точки пути по количеству мест в укрытии, в файле way_escape.ltx
WayPoints
|
Спавним рестриктор в файле alife_zaton.ltx
[xxxx]
; cse_abstract properties
section_name = space_restrictor
name = zat_d1_logic
position = 209.414016723633,21.2857513427734,545.658752441406
direction = 0,0,0
version = 0x7c
script_version = 8
; cse_alife_object properties
game_vertex_id = 292
distance = 0
level_vertex_id = 1322116
object_flags = 0xffffff3e
custom_data = <<END
[logic]
cfg = scripts\zaton\zat_d1_logic.ltx
END
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 20
; cse_alife_space_restrictor properties
restrictor_type = 3
Ставим точки спавна в файле way_zaton.ltx
[zat_d1_item_1_spawn]
points = p0
p0:name = wp00
p0:flags = 0x1
p0:position = 209.414016723633,21.6857513427734,545.658752441406
p0:game_vertex_id = 292
p0:level_vertex_id = 1322115
[zat_d1_item_2_spawn]
points = p0
p0:name = wp00
p0:flags = 0x1
p0:position = 210.414016723633,21.6857513427734,545.658752441406
p0:game_vertex_id = 292
p0:level_vertex_id = 1322116
[zat_d1_item_3_spawn]
points = p0
p0:name = wp00
p0:flags = 0x1
p0:position = 210.414016723633,22.4857513427734,547.658752441406
p0:game_vertex_id = 292
p0:level_vertex_id = 1322117
[zat_d1_item_4_spawn]
points = p0
p0:name = wp00
p0:flags = 0x1
p0:position = 209.414016723633,21.3857513427734,543.658752441406
p0:game_vertex_id = 292
p0:level_vertex_id = 1322118
Пишем логику рестриктора в файле gamedata\configs\scripts\zaton\zat_d1_logic.ltx
[logic]
active = sr_idle@item_spawn
[sr_idle@item_spawn]
on_info = {=actor_in_zone(zat_d1_logic)} sr_idle@item_spawn_1 %=spawn_object(komp_block:zat_d1_item_1_spawn)%
[sr_idle@item_spawn_1]
on_game_timer = 150 | sr_idle@item_spawn_2 %=spawn_object(tv_1:zat_d1_item_2_spawn)%
[sr_idle@item_spawn_2]
on_game_timer = 150 | sr_idle@item_spawn_3 %=spawn_object(gaz_balon:zat_d1_item_3_spawn)%
[sr_idle@item_spawn_3]
on_game_timer = 150 | sr_idle@nil %=spawn_object(disel_generator:zat_d1_item_4_spawn)%
[sr_idle@nil]
В самом начале игры поворачиваем направо и идем параллельно склону, чуть левее сухой ёлочки, когда войдем в рестриктор - начнут спавниться предметы с интервалом 15 сек.
|
В файле alife_локация.ltx добавляем секцию:
[54] ; уникальный ID секции
section_name = zone_burning_fuzz_strong ;секция
name = zone_burning_fuzz_strong ;уникальное имя
position = 417.8486638,41.63044398,-106.0006849 --координаты спана
direction = 0,0,0 ;угол поворота
game_vertex_id = 73 ;гейм вертекс
distance = 18.1999988555908
level_vertex_id = 1650842 ;левел вертекс
object_flags = 0xffffff3e
shapes = shape0 ;шейпы (можно задавать несколько).
shape0:type = sphere ; тип шейпа (сферая. также есть box - коробка)
shape0:offset = 0,0,0
shape0:radius = 0.100000001490116 ;радиус шейпа
restrictor_type = 3
max_power = 0 ;максимальная сила(?)
offline_interactive_radius = 30
artefact_spawn_count = 32 ;максимальное число спавна артов
visual_name = dynamics\anomaly\topolinypuh_big ;визуал(партикл)
idle_animation = idle ;(скорее всего партикл)
attack_animation = idle ;(скорее всего партикл)
Данные о том,какие арты будут спавнится аномалией, записаны в configs\zones\zone_ХХХ.ltx
Для аномалий используются несколько партиклов:
1 - когда аномалия в состоянии спокойствия.
2 - когда аномалия реагирует на живность(NPC,ГГ,монстры)
3 - перед рождением арта проигрывается партикл.
|
Отредактировать секцию meet в логике:
[meet_guide]
close_snd_hello = rolan_hello_snd
close_snd_bye = rolan_hello_snd_bye
abuse = false
use = true
allow_break = false
meet_on_talking = false
В файле configs\misc\script_sound_xxx.ltx создать секции Rolan_hello_snd и
rolan_hello_snd_bye по аналогии с др.(разобраться легко)
|
Дописываем в нужном нам смарт-террейне респавн-параметры:
Например файл gamedata\configs\scripts\zaton\smart\zat_a1.ltx
[smart_terrain];zat_a1
squad_id = 54
max_population = 3
respawn_params = respawn@zat_sim_13
arrive_dist = 15
[respawn@zat_sim_13]
spawn_bandit@novice
spawn_stalker@advanced
spawn_monster@master
[spawn_bandit@novice]
spawn_squads = bandit_sim_squad_novice, bandit_sim_squad_advanced
spawn_num = {+zat_a1_game_start} 2, 0
[spawn_stalker@advanced]
spawn_squads = stalker_sim_squad_veteran
spawn_num = {+zat_a1_game_start} 2, 0
[spawn_monster@master]
spawn_squads = simulation_boar, simulation_flesh, simulation_snork
spawn_num = {+zat_a1_game_start} 2, 0
|
Если спавнил эксклюзива через смарт-террейн, то в логике точки пути надо писать сокращенно
Т.е. если в way_локация.ltx вейпоинт называется marsh_base_stalker_trader_walker_1_walk (look), а имя смарт-террейна marsh_base,
В логике надо писать path_walk = stalker_trader_walker_1_walk (без имени смарта).
Если-же спавнил через All.spawn - тогда полное имя пути нужно.
|
[logic]
active = walker
[walker]
path_walk = bar_bar_visitor_dolg_walk
path_look = bar_bar_visitor_dolg_look
def_state_standing = scaner_stand
on_game_timer = 150 | walker@1
meet = meet
danger = danger_ignore
on_info = {!is_day} walker@sleep_night ;условие -!(отрицание) если день - переход ко сну
[walker@sleep_night] ;спать
path_walk = bar_bar_visitor_dolg_walk
path_look = bar_bar_visitor_dolg_look
def_state_standing = sleep
on_info = {=is_day} walker ; =(соответствует) если день
meet = no_meet ;чтобы не будили
|
[ХХХХ] ; уникальный ID секции
; cse_abstract properties
section_name = physic_destroyable_object
name = mar_physic_destroyable_object_0016 ;имя должно быть уникальным
position = 114.354415893555,2.27533888816834,-151.578521728516
direction = -0.00769999995827675,-0.000303999986499548,-0.0395170003175735
; cse_alife_object properties
game_vertex_id = 0
distance = 0
level_vertex_id = 171487
object_flags = 0xffffff3a
custom_data = <<END
[logic]
active = nil
[drop_box]
items = medkit,1,bandage,2,ammo_12x70_buck,3,ammo_vog-25,5,wpn_fort,1
END
; cse_visual properties
visual_name = dynamics\box\box_metall_01
; cse_ph_skeleton properties
; cse_alife_object_physic properties
physic_type = 0x3
mass = 10
upd:num_items = 0
|
[active logic]
....
on_actor_dist_le_nvis = 5| remark@esc_lager_volk1
....
[remark@esc_lager_volk1]
anim = hello_wpn
snd = esc_wolf_thanks
target = story | actor
....
configs\misc\script_sound_xxx.ltx
[esc_wolf_thanks]
type = npc
path = scenario\escape\wolf_to_dialog
shuffle = seq
idle = 1,1,100
в snd пишешь путь к секции звука в script_sound
|
Создадим сквад из имеющегося уже специфик характера первого попавшегося NPC, к примеру долговца - sim_default_duty_4, определим его в ближайший от начала игры смарт-террейн - это zat_a1, а так-же определим точку его спавна из этого смарта - zat_a1_guard_1_walk (смотрим way_zaton.ltx) - точка двойная, будет ходить по ней и смотреть в точки zat_a1_guard_1_look
gamedata\configs\misc\squad_descr_zaton.ltx
; Здесь содержатся дескрипшены сквадов, которые потом можно создавать используя спец функции.
[zat_bolvan_1_squad]:online_offline_group
faction = stalker
npc = sim_default_duty_4
target_smart = zat_a1
spawn_point = zat_a1_guard_1_walk
story_id = zat_bolvan_1_squad
Теперь добавим этот сквад в стартовую позицию Затона через файл gamedata\configs\misc\simulation.ltx
;;;;;;;;;;;;;;;;;;;;;; FINAL ZATON ;;;;;;;;;;;;;;;;;;;;;;;;;
[start_position_zaton]
zat_bolvan_1_squad = zat_a1
и в уникальные сквады Затона через файл gamedata\configs\misc\simulation_objects_props.ltx
;--------- ZATON UNIQUE SQUADS --------
[zat_bolvan_1_squad]:default_squad
sim_avail = false
Все - сквад готов, команда на спавн получена, начинайте новую игру и встретите его у камней. У нас получился одиночный дефолтный сквад
Теперь пойдем дальше - создадим настоящего эксклюзива с индивидуальной логикой. Прежде всего создаем специфик характер:
<specific_character id="val_freedom_trader" team_default = "1">
<name>val_freedom_trader_name</name>
<icon>ui_npc_u_freedom_2_mask</icon>
<map_icon x="1" y="0"></map_icon>
<bio></bio>
<class>val_freedom_trader</class>
<community>freedom</community> <terrain_sect>stalker_terrain</terrain_sect>
<rank>450</rank>
<reputation>0</reputation>
<money min="10000" max="27500" infinitive="1"/>
<visual>actors\stalker_freedom\stalker_freedom_2_mask</visual>
<snd_config>characters_voice\human_01\freedom\</snd_config>
<supplies>
[spawn] \n
device_torch \n
wpn_lr300 \n
ammo_5.56x45_ss190 = 5 \n
wpn_hpsa \n
ammo_9x19_fmj = 5 \n
grenade_f1 = 10 \n
#include "gameplay\character_items.xml"
#include "gameplay\character_food.xml"
#include "gameplay\character_drugs.xml"
</supplies>
#include "gameplay\character_criticals_1.xml"
<start_dialog>zat_a2_stalker_barmen_start_dialog</start_dialog>
<actor_dialog>zat_a2_linker_b14_quest_init</actor_dialog>
<actor_dialog>zat_a2_linker_b14_quest_done</actor_dialog>
<actor_dialog>zat_a2_linker_b14_quest_strange_item</actor_dialog>
<actor_dialog>zat_a2_linker_b14_quest_sell_artefact</actor_dialog>
<actor_dialog>zat_a2_linker_b14_quest_wrong</actor_dialog>
<actor_dialog>zat_b57_barmen_about_bloodsucker_lair_dialog</actor_dialog>
<actor_dialog>zat_b57_barman_reward_dialog</actor_dialog>
<actor_dialog>zat_b22_barmen_about_vampire_actor1</actor_dialog>
<actor_dialog>zat_b22_barmen_about_vampire_actor2</actor_dialog>
<actor_dialog>zat_b22_barmen_about_vampire_actor3</actor_dialog>
<actor_dialog>zat_b22_barmen_about_vampire_actor4</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b7_actor_start</actor_dialog>
<actor_dialog>zat_b22_barmen_b5_daring_quest_stalkers</actor_dialog>
<actor_dialog>zat_b22_barmen_about_after_quest_b5_dealer_actor4</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_about_new_detector</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_about_compass</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_compass_give_dialog</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_compass_double_dialog</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_compass_revert_dialog</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_take_business_actor_dialog</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_army</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_about_sci_guards</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_about_sci_helpers</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_about_halfart_jup_b1</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_oasis_art_sell</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b52_about_snag</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b52_about_nimble</actor_dialog>
<actor_dialog>zat_a2_linker_b29_actor_info</actor_dialog>
<actor_dialog>zat_a2_linker_b29_actor_get_adv_task</actor_dialog>
<actor_dialog>zat_a2_linker_b29_actor_give_adv_task</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_b30_take_money_actor_dialog</actor_dialog>
<actor_dialog>zat_a2_stalker_barmen_actor_info</actor_dialog>
<actor_dialog>actor_break_dialog</actor_dialog>
</specific_character>
|
<character id="val_freedom_trader">
<class>val_freedom_trader</class>
</character>
|
;-------------------------наш свободовец------------------
[val_freedom_trader]:stalker
$spawn = "respawn\val_freedom_trader"
character_profile = val_freedom_trader
spec_rank = regular
community = freedom
story_id = val_freedom_trader
|
Создаем сквад
; Здесь содержатся дескрипшены сквадов, которые потом можно создавать используя спец функции.
[val_freedom_trader_squad]:online_offline_group ; наш свободовец
faction = freedom
npc = val_freedom_trader
target_smart = zat_a1
spawn_point = zat_a1_walker_1_walk
story_id = val_freedom_trader_squad
|
;;;;;;;;;;;;;;;;;;;;;; FINAL ZATON ;;;;;;;;;;;;;;;;;;;;;;;;;
[start_position_zaton]
val_freedom_trader_squad = zat_a1
|
;--------- ZATON UNIQUE SQUADS --------
[val_freedom_trader_squad]:default_squad
sim_avail = false
|
Пропишем в смарт-террейне путь к файлу логики NPC
[smart_terrain];zat_a1
squad_id = 54
max_population = 3
[exclusive] ; пропишем нашего свободовца в эксклюзивы
val_freedom_trader = zaton\val_freedom_trader.ltx ; где лежит файл логики
|
[logic@val_freedom_trader]
active = walker@freedom ; активируем первую схему - патруль между двумя точками
suitable = {=check_npc_name(val_freedom_trader)} ; проверяем - наш ли этот чувак
prior = 100
on_hit = hit
on_death = death
[walker@freedom]
path_look = guard_1_look ;вейпоинты в way_zaton.ltx - куда смотрит
path_walk = guard_1_walk ;вейпоинты в way_zaton.ltx - где ходит
def_state_standing = guard_na ;какую анимацию использует
on_actor_dist_le_nvis = 10 | walker@freedom_1 ;дистанция до игрока <= 10 без проверки на видимость | переход на др схему
;on_info = {=actor_has_item(detector_advanced)} %=teleport_npc(esc_a1_freedom_guard_1_walk)%
meet = no_meet
[walker@freedom_1]:walker@freedom ; производная от первой схемы с изменениями
path_walk = guard_2_walk
path_look = guard_2_look
on_actor_dist_ge_nvis = 10 | walker@freedom ;если дистанция до игрока > 8 без проверки на видимость | возврат в первую схему
meet = meet
[meet]
close_snd_hello = zat_a2_stalker_barmen_greeting ; озвучка - приветствие, без звука - nil
close_snd_bye = zat_a2_stalker_barmen_farewell ; озвучка - прощание, без звука - nil
close_anim = guard_na
close_victim = actor
far_anim = nil
far_victim = nil
close_distance = 2
far_distance = 0
close_snd_distance = 3
abuse = false
;use = {=actor_has_item(detector_advanced)} true, false ;условие диалога -есть детектор"медведь" -говорит
use = true
allow_break = false
meet_on_talking = false
[wounded]
hp_state = 0|wounded_heavy@help_heavy
hp_state_see = 0|wounded_heavy@help_heavy
hp_victim = 0|nil
hp_fight = 0|false
hp_cover = 0|false
[danger]
ignore_distance = 0
ignore_distance_grenade = 0
ignore_distance_corpse = 0
ignore_distance_hit = 0
ignore_distance_sound = 0
[hit]
[death]
|
Обратите внимание на написание точек путей в логике при таком спавне - имя смарт-террейна не пишется zat_a1_guard_1_look
Сами понимаете, что если сразу двоих сделаете - передерутся и долговец скорее всего победит - надо кому-нибудь группировку сменить
|
Добавить в активную логику строку
invulnerable = true
|
Применяются в основном в двух случаях:
1. | Вместо точек путей в логике эксклюзивов. |
2. | Для кампов - посиделки у костра. |
Начнем с посиделок.Добавим в all.spawn в зону нужного нам смарт-террейна несколько смарт-каверов и камп-зону
[20001]
; cse_abstract properties
section_name = camp_zone
name = zat_a1_camp
position = 241.788421630859,14.009066619873,467.594360351563
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 6
distance = 0
level_vertex_id = 1382565
object_flags = 0xffffff3e
custom_data = <<END
[camp]
cfg = scripts\camp.ltx
END
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 5.84479999542236
; cse_alife_space_restrictor properties
restrictor_type = 3
[20002]
; cse_abstract properties
section_name = smart_cover
name = zat_a1_animpoint_1
position = 241.788421630859,14.009066619873,466.594360351563
direction = 0,3.13,0
; cse_alife_object properties
game_vertex_id = 6
distance = 0
level_vertex_id = 1382565
object_flags = 0xffffffbf
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 2
; cse_smart_cover properties
cse_smart_cover__unk1_sz = animpoint_sit_low
cse_smart_cover__unk2_f32 = 0
enter_min_enemy_distance = 15
exit_min_enemy_distance = 10
; se_smart_cover properties
last_description = animpoint_sit_low
loopholes = animpoint_sit_low,1
[20003]
; cse_abstract properties
section_name = smart_cover
name = zat_a1_animpoint_2
position = 240.788421630859,14.009066619873,468.594360351563
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 6
distance = 0
level_vertex_id = 1382565
object_flags = 0xffffffbf
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 2
; cse_smart_cover properties
cse_smart_cover__unk1_sz = animpoint_sit_low
cse_smart_cover__unk2_f32 = 0
enter_min_enemy_distance = 15
exit_min_enemy_distance = 10
; se_smart_cover properties
last_description = animpoint_sit_low
loopholes = animpoint_sit_low,1
[20004]
; cse_abstract properties
section_name = smart_cover
name = zat_a1_animpoint_3
position = 242.788421630859,14.009066619873,468.594360351563
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 6
distance = 0
level_vertex_id = 1382565
object_flags = 0xffffffbf
; cse_shape properties
shapes = shape0
shape0:type = sphere
shape0:offset = 0,0,0
shape0:radius = 2
; cse_smart_cover properties
cse_smart_cover__unk1_sz = animpoint_sit_low
cse_smart_cover__unk2_f32 = 0
enter_min_enemy_distance = 15
exit_min_enemy_distance = 10
; se_smart_cover properties
last_description = animpoint_sit_low
loopholes = animpoint_sit_low,1
|
Все - лагерь для посиделок готов, собираем все с предыдущими наработками.
Важный момент - шейп камп-зоны должен покрывать смарт-каверы, иначе получатся слишком скучные посиделки - не будут травить анекдоты и прочее.
За направление взгляда отвечает дирекшн смарт-кавера.
|
В All.spawn спавним как физический объект (physic_object)
В конце секции добавляем: fixed_bones = wpn_body
(Если не поможет: fixed_bones = wpn_body, priklad)
|
[3718]
; cse_abstract properties
section_name = stalker
name = esc_stalker_kurer
position = 374.063720703125,15.0854034423828,-45.3065032958984
direction = -0.00443700002506375,0.000190000006114133,-0.0433019995689392
; cse_alife_trader_abstract properties
money = 5000
character_profile = esc_stalker_kurer
; cse_alife_object properties
game_vertex_id = 1187
distance = 4.90000009536743
level_vertex_id = 623948
object_flags = 0xffffffbf
custom_data = <<END
[game_info]
END
; cse_visual properties
visual_name = actors\stalker_neutral\stalker_neutral_2
; cse_alife_creature_abstract properties
g_team = 0
g_squad = 0
g_group = 0
health = 0
dynamic_out_restrictions =
dynamic_in_restrictions =
upd:health = 0 ; жизни
upd:timestamp = 0
upd:creature_flags = 0
upd:position = 374.063720703125,15.0854034423828,-45.3065032958984
upd:o_model = 0
upd:o_torso = 0.000190000006114133,-0.00443700002506375,0
upd:g_team = 0
upd:g_squad = 0
upd:g_group = 0
; cse_alife_monster_abstract properties
upd:next_game_vertex_id = 65535
upd:prev_game_vertex_id = 65535
upd:distance_from_point = 0
upd:distance_to_point = 0
; cse_alife_human_abstract properties
predicate5 = 1,2,0,1,0
predicate4 = 1,1,1,1
; cse_ph_skeleton properties
upd:start_dialog =
; se_stalker properties
|
В логику NPC дописываем:
anim = 1_из_анимок
Вот анимки разнообразных ранений:
wounded, wounded_heavy, wounded_heavy_2, wounded_heavy_3, wounded_zombie (только при подключенной анимации stalkers_zombied), psy_pain_anim, psy_armed_anim
|
в all.spawn в секции нужного NPC после custom_data = <<END добавляем
[game_info]
stories = "story_01, legend_01"
|
[10129]
; cse_abstract properties
section_name = m_poltergeist_normal_tele
name = generators_m_poltergeist_normal_tele
position = 40.2556800842285,13.0783748626709,-523.860778808594
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 951
distance = 340.199981689453
level_vertex_id = 374575
object_flags = 0xffffffbf
; cse_visual properties
visual_name = monsters\poltergeist\poltergeist
; cse_alife_creature_abstract properties
g_team = 0
g_squad = 0
g_group = 0
health = 1
dynamic_out_restrictions =
dynamic_in_restrictions =
upd:health = 1
upd:timestamp = 0
upd:creature_flags = 0
upd:position = 40.2556800842285,13.0783748626709,-523.860778808594
upd:o_model = 0
upd:o_torso = 0,0,0
upd:g_team = 0
upd:g_squad = 0
upd:g_group = 0
; cse_alife_monster_abstract properties
upd:next_game_vertex_id = 940
upd:prev_game_vertex_id = 940
upd:distance_from_point = 0
upd:distance_to_point = 0
; cse_ph_skeleton properties
; cse_alife_monster_base properties
; se_monster properties
old_lvid = nil
active_section =
|
[logic]
active = sr_idle
[sr_idle]
on_actor_inside = %+название_инфопоршня%
|
function scenario_autosave (xr_effects.script)
Для примера логика рестриктора в начале игры: zat_a1_logic.ltx
Тексты для названий автосейвов лежат в файле ui_st_other.xml
Если не пашет на новой локации посмотрите зарегистрирована ли ваша локация в скриптах sim_board и smart_terrain (хотя и без этого должно сохраняться)
Пример: сохраняемся и заодно повреждаем вещи:
[logic]
active = sr_idle@game_start
[sr_idle@game_start]
on_info = {=actor_on_level(escape)} sr_idle@nil %=damage_actor_items_on_start +esc_a1_game_start =scenario_autosave(st_save_start_escape)%
[sr_idle@nil]
|
Разместим секцию спейс-рестриктора в all.spawn (привязка имени к определенному смарт-террейну (esc_b1) не обязательна, но желательна для ясности)
alife_escape.ltx
[15001]
; cse_abstract properties
section_name = space_restrictor
name = bar_dolg_bunker_sr_sleep
position = 219.5344470977783,-5.39998846054077,123.680816650391
direction = 0,0,0
version = 0x7c
script_version = 8
; cse_alife_object properties
game_vertex_id = 2746
distance = 0
level_vertex_id = 54650
object_flags = 0xffffff3e
custom_data = <<END
[story_object]
story_id = bar_dolg_bunker_sr_sleep_id
[logic]
cfg = scripts\sr_sleep.ltx
END
; cse_shape properties
shapes = shape0
shape0:type = box
shape0:axis_x = 5.02119588851929,0,0
shape0:axis_y = 0,5.0482006072998,0
shape0:axis_z = 0,0,2.23479747772217
shape0:offset = 0,0,0
; cse_alife_space_restrictor properties
restrictor_type = 3
Регистрируем наше койкоместо в скриптах:
pda.script
;стр.-288
local sleep_zones_tbl =
{
{target = "zat_a2_sr_sleep_id", hint = "st_ui_pda_sleep_place"},
{target = "jup_a6_sr_sleep_id", hint = "st_ui_pda_sleep_place"},
{target = "pri_a16_sr_sleep_id", hint = "st_ui_pda_sleep_place"},
{target = "esc_b1_sr_sleep_id", hint = "st_ui_pda_sleep_place"}
}
function fill_primary_objects()
xr_effects.script
;стр.-2846
function sleep(actor, npc)
local sleep_zones = {
"zat_a2_sr_sleep",
"jup_a6_sr_sleep",
"pri_a16_sr_sleep",
"actor_surge_hide_2",
"esc_b1_sr_sleep"
}
for k,v in pairs(sleep_zones) do
|
Через логику:
Функции: function_teleport_actor, function_teleport_npc
Пример: (configs/scripts/zaton/zat_a1_logic.ltx)
[logic]
active = sr_idle@game_start
[sr_idle@game_start]
on_info = {=actor_on_level(zaton)} sr_idle@game_start_2 %=damage_actor_items_on_start =teleport_actor(zat_b104_zombied_walker_5_walk)%
[sr_idle@game_start_2]
on_info = sr_idle@timer %+zat_a1_game_start%
[sr_idle@timer]
on_game_timer = 3000 | sr_idle@free %+zat_a1_simulation_start%
on_info = {+about_skadovsk_dialog_done -zat_a2_reach_base} %+zat_a2_reach_base =give_task(zat_a2_reach_base)%
on_info2 = {-zat_a2_reach_base =actor_in_zone(zat_a2_sr_noweap)} %+about_skadovsk_dialog_done +zat_a2_reach_base%
on_info3 = {-zat_a2_reached_skadovsk =actor_in_zone(zat_a2_sr_noweap)} %+zat_a2_reached_skadovsk =scenario_autosave(st_save_zat_a2_reached_skadovsk)%
[sr_idle@free]
on_info = {+about_skadovsk_dialog_done -zat_a2_reach_base} sr_idle@time %+zat_a2_reach_base =give_task(zat_a2_reach_base)%
on_info2 = {+zat_a2_reach_base} sr_idle@time
on_info3 = {-zat_a2_reach_base =actor_in_zone(zat_a2_sr_noweap)} %+about_skadovsk_dialog_done +zat_a2_reach_base%
[sr_idle@time]
on_game_timer = 43200 | sr_idle@nil %+zat_a1_trade_level_2%
on_info = {-zat_a2_reached_skadovsk =actor_in_zone(zat_a2_sr_noweap)} %+about_skadovsk_dialog_done +zat_a2_reach_base +zat_a2_reached_skadovsk =scenario_autosave(st_save_zat_a2_reached_skadovsk)%
[sr_idle@nil]
В самом начале игры переместимся в точку пути zat_b104_zombied_walker_5_walk
|
за выдачу заданий на поиск вертолетов отвечает space_restrictor с именем zat_b101_logic. Когда ГГ появляется в нем, то срабатывает логика из файла configs\scripts\zaton\zat_b101_logic.ltx. В пятой строчке идет выдача заданий
|
Для этих целей можно создать спейсрестриктор с нужными условиями спавна сквада.
Для этого надо создать сквад из нужных персонажей, но не прописывать его в start_position в файле simulation.ltx
Посмотрите для примера логику рестриктора zat_b14_spawner.ltx - это спавнер рекетиров на земснаряде, когда гг берет артефакт - спавнится сквад сталкеров в секции [sr_idle@spawn_stalker], команда на спавн =create_sguad
Еще можно в самом смарт-террейне, если нужно дефолтных персонажей (читать как: дефолтный симуляционный сквад), респавн сквада с условием, условие в строке spawn_num = {условие} количество, к примеру файл zat_b28.ltx - нашел вертолет, респавнятся снорки.
|
target_smart = {=is_dark_night} nil, {~50} zat_sim_5, {~50} zat_sim_3, {~50} zat_sim_1, {~50} zat_sim_18, {~50} zat_sim_10, {~50} zat_sim_7, zat_sim_26
Условия:
{=is_dark_night} -- Если ночь
{~50} --- Вероятность, что пойдет на эту точку
|
[logic@zat_a2_stalker_barmen]
suitable = {=check_npc_name(zat_a2_stalker_barmen)} true ;проверка на совместимость логики с конкретным НПСом, или группировкой. Это значит, что эта логика только для конкретного НПСа, в данном случае для Бороды.
trade = misc\trade\trade_zat_a2_barmen.ltx ;путь к файлу торговли.
prior = 200 ;приоритет. На что влияет никто точно не знает.
active = animpoint@bar ;активная схема поведения
can_select_weapon = false ;может ли пользоваться оружием
level_spot = trader ;иконка на карте
[animpoint@bar]
cover_name = zat_a2_sc_barmen ;имя секции smart_cover из all.spawn.
avail_animations = animpoint_stay_table_no_rnd ;анимация поведения.
use_camp = false ;может ли использовать кэмп-зону.
meet = meet ;ссылка на логику разговоров (meet - дефолтная, описывать ее не обязательно; no_meet - NPC будет молчать как партизан на допросе)
combat_ignore_cond = true ;игнорирование боя.
combat_ignore_keep_when_attacked = true ;игнорирование боя, даже если НПС атакован.
invulnerable = true ;бессмертие.
gather_items_enabled = false ;разрешение на сбор предметов.
help_wounded_enabled = false ;разрешение на помощь раненым.
corpse_detection_enabled = false ;разрешение на обыск трупов.
[meet]
close_snd_hello = {-zat_b30_barmen_under_sultan} zat_a2_stalker_barmen_greeting, zat_a2_stalker_barmen_greeting_angry
close_snd_bye = {-zat_b30_barmen_under_sultan} zat_a2_stalker_barmen_farewell, zat_a2_stalker_barmen_farewell_angry
close_anim = nil
close_victim = nil
far_anim = nil
far_victim = nil
close_distance = 0
far_distance = 0
close_snd_distance = 3
abuse = false
use = {=actor_enemy} false, true
allow_break = false
meet_on_talking = false
meet_on_talking = false
|
[logic]
active = sr_idle@1
[sr_idle@1]
on_npc_in_zone = название_этого_рестриктора | sr_idle@2 %=kill_npc%
[sr_idle@2]
on_npc_in_zone = название_этого_рестриктора | sr_idle@1 %=kill_npc%
|
Стоит чуть-чуть подправить логику, например:
[logic@bazmar_kamp1]
active = animpoint@bazmar_kamp1
[animpoint@bazmar_kamp1]
cover_name = kamp1
on_info = {=surge_started} walker@bazmar_kamp1_surge ;если выброс начался, то идем в укрытие, на точку [walker@bazmar_kamp1_surge].
use_camp = true
meet = meet@bazmar
[walker@bazmar_kamp1_surge]
path_walk = bazmar_surge1_walk
path_look = bazmar_surge1_look
meet = meet@bazmar
def_state_moving = run
use_camp = true
def_state_standing = sit_knee
on_info = {=surge_complete} animpoint@bazmar_kamp1 ;если выброс закончился, то идем обратно в анимпоинт.
[meet@bazmar]
close_anim = nil
close_victim = nil
far_anim = nil
far_victim = nil
close_distance = 0
far_distance = 0
use = {=actor_enemy} false, {=dist_to_actor_le(3)} true, false
snd_on_use = {!dist_to_actor_le(3)} nil
meet_on_talking = false
|
Для работы нужен: ACDC COP with split
Конвертируем наш all.spawn батником:
perl acdccop.pl -d all.spawn -split_spawns -graph
pause
Далее, конвертируем получившийся level.spawn батником:
perl acdccop.pl -d level.spawn -w -l -ls
pause
И у нас выведуться все графпоинты. Пример:
[1]
section_name = graph_point
name = start_actor_01
position = -384.276184082031,1.29132080078125,91.8708267211914
direction = 0,0,0
[2]
section_name = graph_point
name = l09_deadcity_graph_point_1
position = -333.990936279297,-1.19963073730469,159.972640991211
direction = 0,0,0
[3]
section_name = graph_point
name = l09_deadcity_graph_point_2
position = -326.427185058594,-4.72068786621094,-4.02680969238281
direction = 0,0,0
[4]
section_name = graph_point
name = l09_deadcity_graph_point_3
position = -321.962768554688,7.70576477050781,67.442985534668
direction = 0,0,0
[5]
section_name = graph_point
name = l09_deadcity_graph_point_4
position = -300.007446289063,-7.8902587890625,222.426391601563
direction = 0,0,0
|
Прежде всего нужно поставить сигнал на последнюю точку пути:
p12:name = wp012|sig=end_way
p12:position = -156.36016845703,7.499502658844,-206.67156982422
p12:game_vertex_id = 1263
p12:level_vertex_id = 39802
Затем в логике проверять наличие сигнала при получении которого будет произведен переход:
[walker@stalker]
...
on_signal = end_way | remark@stalker
[remark@stalker]
|
Для того чтобы найти индивидуальную логику НПС нужно:
1. По имени НПС определить его идентификатор. Например для Бороды (подробнее урок 002 в КМБ) zat_a2_stalker_barmen
2. Найти его файл логики, он должен содержать строку типа suitable = {=check_npc_name(zat_a2_stalker_barmen), то есть проверку на то, что НПС и есть тот самый Борода.
3. Находим файл zat_a2_stalker_barmen.ltx в папке configs\scripts\zaton
Файлов логики может быть несколько, по числу смартов на которых данный НПС может находиться.
|
Например двери на Cкадовск configs\scripts\zaton\zat_a2_ph_ship_door.ltx
в секциях заменить locked = true на locked = false
|
[meet]
use={Условие}self, true
|
[2584]
; cse_abstract properties
section_name = lights_hanging_lamp
name = lights_white_12m_glass
position = -349.036407470703,6.66451787948608,393.330322265625
direction = 0,0,-1.57079601287842
; cse_alife_object properties
game_vertex_id = 317
distance = 0
level_vertex_id = 1231404
object_flags = 0xffffff3a
custom_data = <<END
[collide]
ignore_static
END
; cse_visual properties
visual_name = dynamics\light\light_white_glass
; cse_ph_skeleton properties
; cse_alife_object_hanging_lamp properties
main_color = 0xffffe3b5
main_brightness = 0.800000011920929
main_range = 12
light_flags = 0xa
lamp_fixed_bones = link
health = 100
main_virtual_size = 0.100000001490116
ambient_radius = 2.5
ambient_power = 0.600000023841858
main_bone = bone_lamp
main_cone_angle = 2.09439492225647
glow_radius = 0.699999988079071
ambient_bone = bone_omni
cse_alife_object_hanging_lamp__unk1_f32 = 1
cse_alife_object_hanging_lamp__unk2_f32 = 1
cse_alife_object_hanging_lamp__unk3_f32 = 1
|
[logic@sergant_kolobkov]
active = walker@sergant_kolobkov
suitable = {=check_npc_name(agroprom_sergant_kolobkov)}
prior = 100
[walker@sergant_kolobkov]
path_walk = sergant_kolobkov_walk
path_look = sergant_kolobkov_look
def_state_moving = walk_noweap
meet = meet@wounded
wounded = wounded@sergant_kolobkov
on_info = {+agr_kolobkov_help} walker@sergant_kolobkov_2
[wounded@sergant_kolobkov]
hp_state = 101|wounded_heavy@help_heavy
hp_state_see = 101|wounded_heavy@help_heavy
hp_victim = 101|nil ;actor
hp_cover = 101|false
hp_fight = 101|false
autoheal = false
not_for_help = true
enable_talk = true
[meet@wounded]
use = true
meet_dialog = agroprom_sergant_kolobkov_wounded
abuse = false
allow_break = false
trade_enable = false
close_anim = nil
close_victim = nil
close_distance = 0
far_distance = 0
[walker@sergant_kolobkov_2]
path_walk = sergant_kolobkov_2_walk
path_look = sergant_kolobkov_2_look
meet = meet
commander = true
on_combat = combat
В начальной секции walker@sergant_kolobkov НПС ранен с настройками поведения раненного из секции wounded@sergant_kolobkov, при этом может взаимодействовать с ГГ вести только один диалог описанный в секции meet@wounded, после лечения переходит в секцию walker@sergant_kolobkov_2 в которой здоров и также взаимодействует с ГГ посредством секции meet (опущена в данном фрагменте)
|
Нужно указать параметр direction в секции:
direction = a,b,c
Нужно устанавливать значение B - угол в радианах между направлением взгляда и направлением оси координат. Использовать db.actor:direction() - для снятия направления взгляда не корректно, нужно использовать направление камеры: device().cam_dir
Все значения могут находиться в интервале от -3.14 до +3.14
|
toolkit_1, toolkit_2, toolkit_3
|
Надо вписать сквад в файл simulation.ltx в секции соответствующей локации спавна таким образом:
<Сквад> = <Смарт>
|
[logic@krovos_stan]
suitable = {=check_npc_name(stan_bloodsucker)} true
active = mob_home@krovos_stan
monster_job = true
prior = 150
[mob_home@krovos_stan]
path_home = krovos_stan_walk
aggressive = true
home_min_radius = 15
home_max_radius = 35
|
on_actor_in_zone = restrictor_name | схема
on_actor_not_in_zone = restrictor_name | схема
on_npc_in_zone = npc_story_id | restrictor_name | схема
on_npc_not_in_zone = npc_story_id | restrictor_name | схема
out_restr = npc_story_id | restrictor_name -- NPC не будет выходить из этого рестриктора
in_restr = npc_story_id | restrictor_name -- Наоборот
|
Создать рестриктор с такой логикой:
[logic]
active = sr_silence
[sr_silence]
|
[1204]
; cse_abstract properties
section_name = physic_object
name = marsh_helicopter
position = -260.848236083984,1.69732201099396,87.5911636352539
direction = 0,0,0
; cse_alife_object properties
game_vertex_id = 3592
distance = 0.300000011920929
level_vertex_id = 82716
object_flags = 0xffffff3a
custom_data = <<END
[collide]
ignore_static
END
; cse_visual properties
visual_name = dynamics\vehicles\mi24\veh_mi24_u_02
; cse_ph_skeleton properties
skeleton_name =
skeleton_flags = 1
; cse_alife_object_physic properties
physic_type = 0x3
mass = 1000
fixed_bones = korpus1
|
|