Предлагаю в этой теме выкладывать свои или чьи то уроки по созданию модов , которые могут пригодиться для начинающих или для тех кто просто или не знал или забыл ,также если кто в уроке увидел ошибку просим сообщить об этом , а не исправлять самим
Сразу расположу ответы на часто задаваемые вопросы по редактированию файлов
Как увеличить максимальный переносимый вес?
откройте файл gamedata\configs\creatures\actor.ltx, найдите там строку max_walk_weight =60, это максимальный вес(60кг), в файле gamedata\configs\system.ltx найдите
строку max_weight = 50 (если несёте больше этого веса, то быстро расходуется сила), поменяйте эти значения на желаемые.
Как сделать главного героя бессмертным, бесконечно выносливым?
Параметры, отвечающие за потерю НР находятся в файле gamedata\configs\creatures\actor.ltx, эти строки:
.... satiety_critical = 0.0 ;критическое значения сытости (в процентах от 0..1) когда здоровье начианает уменьшаться radiation_health_v = 0.004 ;уменьшение здоровья при воздействии радиации health_hit_part = 1.0 ;процент хита, уходящий на отнимание здоровья power_hit_part = 0.1 ;процент хита, уходящий на отнимание силы bleeding_v = 0.002 ;0.0005 ;потеря крови при номинальной ране в секунду ... сделайте их равными 0.0 и вы бессмертны ... wound_incarnation_v = 0.0001 ;0.003 ;скорость заживления раны min_wound_size = 0.0256 ;минимальный размер раны, после которого она считается зажившей psy_health_v = 0.001 ;скорость восстановления psy-здоровья ... увеличьте эти параметры в несколько раз для бесконечной выносливости обнулите эти параметры: walk_power = 0.00001 ;умешьшение силы за секнду во время ходьбы без учета веса ноши walk_weight_power = 0.00005; ;умешьшение силы за секнду во время ходьбы с учетом веса ноши, для максимального допустимого веса для увеличения высоты прыжка, измените этот параметр: jump_speed = 6
Параметры стволов заданы в конфигурационных файлах по адресу gamedata\configs\weapons
Возьмем, для примера, конфиг w_g36.ltx. Он делится на разделы:
Первый раздел Здесь хранится общая информация о оружии - его класс, тип, ссылки на спавн и т.д. Нас интересуют следующие строки:
description = enc_weapons1_wpn-g36 - ссылка на string_id, из которого игра подгружает описание этого оружия. ef_main_weapon_type = 2 - основной тип, к которому принадлежит оружие ef_weapon_type = 6 - подтип, к которому принадлежит оружие
Второй раздел Содержит модификаторы, которые даются к углу зрения/дальности обзора NPC, держащего это оружие в руках: holder_range_modifier = 1.85 - во сколько раз увеличивается eye_range holder_fov_modifier = 0.3 - во сколько раз увеличивается eye_fov
Третий раздел Содержит данные о самом оружии, его некоторых характеристиках:
cost = 18000 - базовая цена (торговцы умножают её на некоторый коэффициент) weapon_class = assault_rifle - класс оружия (здесь - штурмовая винтовка) ammo_mag_size = 30 - размер магазина ammo_class = ammo_5.56x45_ss190, ammo_5.56x45_ap - типы используемых патронов grenade_class = ammo_m209 - тип используемых гранат fire_modes = 1, -1 - режимы ведения огня hand_dependence = 1 - засивимость о рук (?) - возможно, речь идет о качании ствола single_handed = 0 - держится ли только в одной руке slot = 2 - слот в инвентаре animation_slot = 2 - вид анимации (для пистолета/для винтовки) inv_name = wpn-g36 - ссылка на имя, отображаемое в инвентаре, тоже берется из string table, как и описание inv_name_short = wpn-g36 - короткое имя; в данном случае используется то же самое inv_weight = 3.6 - вес inv_grid_width = 5 - координаты первого угла иконки по x inv_grid_height = 2 - координаты первого угла иконки по y inv_grid_x = 0 - координаты второго угла иконки по x inv_grid_y = 10 - координаты второго угла иконки по y
Четвертый раздел В четвертом разделе хранится информация о износе/отдаче оружия. Практически все параметры там снабжены комментариями, поэтому приведу лишь самые интересные:
cam_relax_speed = 5.7 - скорость возврата в исходное положение cam_dispersion = 0.2 - увеличения угла (в градусах) с каждым выстрелом fire_dispersion_condition_factor = 5 - увеличение дисперсии в процентах при максимальном износе misfire_probability = 0.003 - вероятность осечки при максимальном износе misfire_condition_k = 0.05 - порог (в данном случае - 5%), после которого оружие может заклинивать condition_shot_dec = 0.0002 - увеличение износа при каждом выстреле
Пятый раздел Здесь хранится множество параметров, из которых наиболее интересны эти: PDM_disp_base = 3.0 - множитель, на который умножается базовая дисперсия оружия, когда ГГ (Главный Герой) стоит на месте в полный рост; PDM_disp_vel_factor = 1.3 - множитель, на который умножается базовая дисперсия оружия, когда ГГ крутит оружием или бежит; PDM_disp_accel_factor = 1.3 - множитель, на который умножается базовая дисперсия оружия, когда ГГ бежит в спринте; PDM_crouch = 1.0 - множитель, на который умножается базовая дисперсия оружия, когда ГГ идет пригнувшись; PDM_crouch_no_acc = 1.0 - множитель, на который умножается базовая дисперсия оружия, когда ГГ стоит на месте, пригнувшись; hit_power = 0.50, 0.54, 0.57, 0.60 - сила выстрела hit_impulse = 105 - импульс пули (сила, которую летящая пуля передает жертве, влияет на поведение ragdoll-тела) hit_type = fire_wound - тип причиняемых повреждений, в данном случае - пулевые ранения (параметр в синглплеере ни на что не влияет) fire_distance = 600 - максимальная дистанция для выстрела bullet_speed = 925 - начальная скорость пули hud = wpn_g36_hud - внешний вид оружия
Шестой раздел position = -0.026, -0.132, 0.0 - позиция по отношению к игроку (?) orientation = 0, 0, 0 - направление, в которое смотрит ствол (?)
Седьмой раздел Содержит описания визуальной стороны оружия и некоторые другие параметры:
startup_ammo = 90 - как нетрудно догадаться, стартовое количество патронов (в синглплеере ни на что не влияет) visual = weapons\g36\wpn_g36.ogf - модель оружия, используемая NPC, а также игроком при виде от третьего лица ph_mass = 4 - физическая масса, используемая при расчетах scope_status = 1 - ситуация со съемным прицелом silencer_status = 0 - ситуация со съемным глушителем grenade_launcher_status = 0 - ситуация с подствольным гранатометом Параметры: 0 - нет, новый прикрепить нельзя 1 - уже есть, несъемный 2 - нет, но можно установить новый zoom_enabled = true - есть ли зум (прицеливание) scope_zoom_factor = 33.3 - какой зум дает прицеливание (здесь - 1.8х) scope_texture = wpn\wpn_crosshair_g36 - текстура прицельной сетки shell_point = 0.15, 0.0, -0.05 - точка вылета гильз shell_dir = 0.0, 1.0, 0.0 fire_point = -0.000000,0.062000,0.134000 - точка выстрела fire_point2 = 0.30, 0.00, 0.05 - точка выстрела (2) fire_bone = wpn_body orientation = 0, 0, 0 - направление position = 0, 0, 0 - позиция visual = weapons\g36\wpn_g36_hud.ogf - модель, отображаемая у нас в руках
Изменение описаний Описания оружия хранятся в файле: ...\S.T.A.L.K.E.R\gamedata\config\text\rus\string_table_enc_weapons.xml
В нем хранятся строки с названиями и описаниями, на которые ссылаются конфиги оружия. Например, тот же G36 ссылается сюда:
[...]
<string id="enc_weapons1_wpn-g36"> <text>Штурмовая винтовка немецкого производства, представляющая собой первоклассный образец современного оружия - лёгкого, надёжного и эргономичного.\n Боеприпасы:\n обычный 5,56x45 мм SS109,\n бронебойный 5,56x45 мм АР.</text> [...] <string id="wpn-g36"> <text>ГП37</text> [...]Меняя их содержимое, мы меняем описания/названия данного оружия.
Как изменить параметры конкретного боеприпаса?
Параметры амуниции заданы в файле по адресу gamedata\configs\weapons\weapons.ltx например: visual = weapons\ammo\ammo_556x45_ss190.ogf - модель коробки с патронами description = enc_weapons1_ammo_ammo-5.56x45-ss190 - ссылка на string_id, из которого игра подгружает описание этого типа патронов cost = 320 - стоимость одной коробки box_size = 30 - количество патронов в одной коробке inv_name = ammo-5.56x45-ss190 - ссылка на string_id, содержащий имя для инвентаря inv_name_short = ammo-5.56x45-ss190_s - ссылка на string_id, содержащий краткое имя для инвентаря inv_weight = 0.33 - вес inv_grid_width = 2 - координаты первого угла иконки по x inv_grid_height = 1 - координаты первого угла иконки по y inv_grid_x = 14 - координаты второго угла иконки по x inv_grid_y = 11 - координаты второго угла иконки по y k_dist = 1 - коэффициент дальности, сама дальность - в стволе, тупо расстояние. k_disp = 2.5 - кучность, завязана с кучностью в стволе k_hit = 1 - убойность, завязана с убойностью в стволе k_impulse = 1 - чисто наскока эффектно ногами непись дрыгнет во время кердыка k_pierce = 1 - коэффициент наскока испорится броня при попадании impair = 1 - коэффициент износа ствола от пули buck_shot = 1 - кол-во составляющих в пуле (напр картечь - 4, пуля - 1) tracer = on - является ли патрон трассирующим (on/off) wm_size = 0.05 - визуальный размер дырки на стене от пули
Как заставить фонарик светить дальше?
в файле gamedata\configs\models\objects\light_night.ltx увеличьте range-параметры
Подробное описание конфигов: [torch_definition] range = 30 ; дистанция в метрах. range_r2 = 30 ; дистанция в метрах (для динамического освещения). color = 0.22,0.22,0.22,0.2 ; цвет, из 4 компонентов <r,g,b,a> значением от 0 до 3. color_r2 = 1.1,1.1,1.1,0.0 ; цвет, из 4 компонентов <r,g,b,a> значением от 0 до 3 (для динамического освещения). omni_range = 3 ; дистанция освещения от фонариков неписей в метрах. omni_range_r2 = 3 ; дистанция освещения от фонариков неписей в метрах (для динамического освещения). omni_color = 1.0,1.0,1.0,0.1 ; цвет фонариков неписей, из 4 компонентов <r,g,b,a> значением от 0 до 3. omni_color_r2 = 1.0,1.0,1.0,0.1 ; цвет фонариков неписей, из 4 компонентов <r,g,b,a> значением от 0 до 3 (для динамического освещения). color_animator = empty ; цвет аниматора (empty - аниматор не используется). spot_texture = internalinternal_light_torch_r2 ; текстура яркой точки (для динамического освещения). spot_angle = 45 ; угол освещения в градусах. glow_texture = glowglow_torch_r2 ; текстура свечения фонарика, когда он направлен в глаза (обязательный параметр). glow_radius = 0.3 ; радиус свечения в метрах. guide_bone = lights_bone ; кость, к направлению которой привязывается фонарик (изменять строго не рекомендуется).
Как редактировать торговцев, торговлю с обычными сталкерами?
все настройки, связанные с ассортиментом торговцев в игре, находятся в файлах gamedata\configs\misc\trade_***.ltx для всех остальных сталкеров - gamedata\configs\misc\trade_generic.ltx Структура файла Секция [trader_generic_buy] Эта секция описывает какие товары торговец будет покупать. Название предмета = минимальная цена покупки, максимальная цена покупки Например: wpn_vintorez = 0.5, 0.7Это значит что торговец купит оружие от 50% полной его стоимости до 70%, т.е. если Винторез стоит 1000, то торговец купит его в диапазоне от 500 до 700 рублей. Диапазон зависит от отношения торговца к Меченому - чем лучше, тем дороже купит
Секция [supplies_start] Эта секция описывает какие товары у торговца будут вначале. Название предмета = количество, вероятность появления Например: bandage = 5, 1Это значит что у торговеца всегда будут 5 бинтов, с 100 процентной вероятностью появления в магазине. bandage = 5, 0.6 А тут уже вероятность появления 60%. Т.е. бинты не всегда будут.
Секция [supplies_after_***] Тоже самое, что в секции [supplies_start], но после выполнения квестов торговца.
Секция [trader_start_sell] Эта секция описывает за какую цену торговец будет продавать. Название предмета = минимальная цена продажи, максимальная цена продажиНапример: wpn_vintorez = 1, 2Это значит что торговец продаст оружие от 100% полной его стоимости до 200%, т.е. если Винторез стоит 1000, то торговец продаст его в диапазоне от 1000 до 2000 рублей. Диапазон зависит от отношения торговца к Меченому - чем лучше, тем дешевле продаст
Секция [trader_after_***_sell] Тоже самое, что в секции [trader_start_sell], но после выполнения квестов торговца.
деньги торговцев правятся в character_desc_название локации.xml, например, в character_desc_escape.xml такая строка: <money min="100000" max="100000" infinitive="1"/> (если infinitive="1" - бесконечные деньги)
Как редактировать костюмы?
Итак, секции с параметрами находятся в файле: config\misc\outfit.ltx Рассмотрим, например, параметры классического костюма сталкера.
[stalker_outfit]:outfit_base ; название секции костюма. именно к нему игра будет обращаться. outfit_base - базовая (наследуемая) секция (изменять строго не рекомендуется).
visual = equipments\stalker_suit ; модель, используемая для сложенного костюма, лежащего на земле. actor_visual = actors\hero\stalker_hood.ogf ; модель, используемая для игрока, когда на нем надет костюм. inv_name = stalker_outfit_name ; название в инвентаре. inv_name_short = stalker_outfit_name ; название в инвентаре (в принципе, можно здесь продублировать значение предыдущего параметра - так чаще всего и делают). description = stalker_outfit_description ; ссылка на текстовую строку с описанием. inv_weight = 5.0 ; вес.
cost = 15000 ; базовая цена (см. примечание 2). full_scale_icon = 14,11 ; иконка сталкера в костюме в полный рост (отображается в инвентаре справа). nightvision_sect = effector_nightvision_bad ; тип ПНВ ("плохой" - зеленый, "хороший" - синий).
; ниже идут параметры защиты владельца от различных типов воздействий, обеспечиваемые костюмом. burn_protection = 0.5 ; защита от воздействия огня (костры, аномалия "Жарка" и т.д.). strike_protection = 0.5 ; защита от ударов (наносятся мутантами, например, псевдогигантом). shock_protection = 0.5 ; защита от поражения электричеством. wound_protection = 0.4 ; защита от ранений (наносятся мутантами, например, собаками, кровососами и т.д.). radiation_protection = 0.5 ; защита от радиации. telepatic_protection = 0.0 ; защита от пси-воздействия (например, присутствие контроллера серьезно влияет на psy_health). chemical_burn_protection = 0.5 ; защита от химического воздействия. explosion_protection = 0.3 ; защита от взрывов/осколков. fire_wound_protection = 0.3 ; защита от огнестрельного оружия (наиболее важный параметр для большинства костюмов). power_loss = 0.87 bones_koeff_protection = gilet_antigas_damage
[sect_stalker_outfit_immunities] ; коэффициенты иммунитета самого костюма, то есть - то, насколько сильно он сам подвержен повреждениям от различных типов воздействий. по значениям каждого типа - см. выше. burn_immunity = 0.03 strike_immunity = 0.01 shock_immunity = 0.03 wound_immunity = 0.015 radiation_immunity = 0.00 telepatic_immunity = 0.00 chemical_burn_immunity = 0.03 explosion_immunity = 0.03 fire_wound_immunity = 0.01
Как сделать так, чтобы стволы не убирались сами?
Изменить эти строки в файле gamedata\scripts\sr_no_weapon.script
function action_no_weapon:zone_enter() self.state = state_inside bind_stalker.restore_weapon(self.object:id()) end function action_no_weapon:zone_leave() self.state = state_outside bind_stalker.restore_weapon(self.object:id()) end
Как сделать вид от третьего лица?
В конце файла C:\Documents and Settings\All Users\Documents\STALKER-STCS\user.ltx (путь к папке STALKER-STCS может быть другим) добавить эти строки:
Конфиги лежат по адресу gamedata\configs\weapons в файлах w_f1.ltx для Ф1 и w_rgd5.ltx для РГД-5; важные параметры: destroy_time = 1800 ; Время детонации 1.8 секунды blast = 3.0 ; Урон наносимый фугасным воздействием blast_r = 8 ; радиус фугасного воздействия blast_impulse = 550 ; Сила удара от фугаса frags = 300 ; Количество осколков frags_r = 25 ; Радиус разлета осколков frag_hit = 3.50; Урон от осколка frag_hit_impulse = 300 ; Сила удара от осколков fragment_speed = 500 ; Скорость осколков
Как реализовать качание прицела?
Конфиги, отвечающие за эту особенность, в файле gamedata\configs\misc\effectors.ltx:
[zoom_inertion_effector] camera_move_epsilon = 0.03 ;разница между двумя векторами направления камера, когда считается что камера двинулась disp_min = 0.01 speed_min = 0.00001 zoom_aim_disp_k = 1.0 ;коэффициенты соотношения полной дисперсии стрельбы zoom_aim_speed_k = 0.0025 ;и покачивания прицела delta_time = 3000 ;время через которое эффектор меняет направление движения (в милисекундах)
Как отключить вспышку выстрела у винтореза, вала, ПБ?
Теперь после выстрела появляется легкая дымка, как при стрельбе с обычным глушителем, для этого в файлах gamedata\configs\weapons\w_vintorez.ltx, gamedata\configs\weapons\w_val.ltx, gamedata\configs\weapons\w_pb.ltx изменить параметр flame_particles = weapons\generic_shoot_00
Как сделать, чтобы у главного героя было много денег?
Деньги правятся в файле gamedata\configs\gameplay\character_desc_general.xml - в самом начале:
<money min="100" max="100" infinitive="0"/>, ставьте, сколько надо, а если вместо infinitive="0" поставить единицу, то у вас будут бесконечные деньги. Примечание: изменения вступят в силу после начала новой игры.
Как "изменить" рост главного героя?
В файле gamedata\configs\creatures\actor.ltx поменять параметр camera_height_factor = 0.92
Где лежат конфиги сталкеров и существ Зоны?
В файлах gamedatabig\configs\creatures\m_название объекта.ltx
Где лежат конфиги артефактов?
Все артефакты описаны в файле gamedatabig\configs\misc\artefacts.ltx
В этой статье я попытаюсь передать практический опыт скриптового создания точек перехода между уровнями. Файл all.spawn меняться не будет, поэтому такой механизм более удобен для совмещения модов и не требует начала новой игры.
В качестве примера попробуем реализовать режим freeplay - продолжение игры после уничтожения О-Сознания. Для этого нужно создать как минимум две точки — возврат на ЧАЭС-1 со внутреннего дворика (после уничтожения О-Сознания) и переход из ЧАЭС-1 в Припять. К слову сказать, если вернуться на ЧАЭС-1, то там будет продолжать действовать таймер "выброса", который в конце-концов включит "deadzone". Отключить счетчик мне пока не удалось, но зато можно легко отключить сам "выброс" и всласть побегать по уровню.
Часть 1.Генерация работающего LEVEL_CHANGER
Стандартной функции alife():create(…) недостаточно для создания полноценного level_changer. Собственно методика создания сложных объектов описана в статье Один из методов спавна. Сложность заключалась лишь в порядке полей и свойствах Shape. Неоценимую помощь в этом вопросе оказала утилита ACDC (created by bardak).
Ниже я привожу код функции, которая создает и инициализируетlevel_changer:
function create_level_changer( p_story_id, -- STORY_ID нового level_changer (понадобится нам позже) p_position, -- вектор, координаты точки, в которой будет располагаться центр нового level_changer p_lvertex_id, -- level_vertext_id - идентифицируют уровень, на котором будет создан level_changer p_gvertex_id, -- game_vertext_id
p_dest_lv, -- level_vertex_id - идентифицируют уровень, на который level_changer будет перебрасывать игрока p_dest_gv, -- game_vertex_id p_dest_pos, -- координаты точки, в которой на новом уровне окажется игрок p_dest_dir, -- направрение взгляда игрока p_dest_level, -- название уровня, например "L11_Pripyat" p_silent -- следует задать 1, чтобы подавить вопрос о смене уровня (автоматический переход) ) local obj = alife():create("level_changer", p_position, p_lvertex_id, p_gvertex_id)
local packet = net_packet() obj:STATE_Write(packet)
-- свойства cse_alife_object local game_vertex_id = packet:r_u16() local cse_alife_object__unk1_f32 = packet:r_float() local cse_alife_object__unk2_u32 = packet:r_u32() local level_vertex_id = packet:r_u32() local object_flags = packet:r_u32() local custom_data = packet:r_stringZ() local story_id = packet:r_u32() local spawn_story_id = packet:r_u32()
-- свойства cse_shape local shape_count = packet:r_u8() for i=1,shape_count do local shape_type = packet:r_u8() if shape_type == 0 then -- sphere local center = packet:r_vec3() local radius = packet:r_float() else -- box local axis_x_x = packet:r_float() local axis_x_y = packet:r_float() local axis_x_z = packet:r_float() local axis_y_x = packet:r_float() local axis_y_y = packet:r_float() local axis_y_z = packet:r_float() local axis_z_x = packet:r_float() local axis_z_y = packet:r_float() local axis_z_z = packet:r_float() local offset_x = packet:r_float() local offset_y = packet:r_float() local offset_z = packet:r_float() end end
-- свойства cse_alife_space_restrictor local restrictor_type = packet:r_u8()
-- свойства cse_level_changer local dest_game_vertex_id = packet:r_u16() local dest_level_vertex_id = packet:r_u32() local dest_position = packet:r_vec3() local dest_direction = packet:r_vec3() local dest_level_name = packet:r_stringZ() local dest_graph_point = packet:r_stringZ() local silent_mode = packet:r_u8()
-- news_manager.send_tip(db.actor, "LC creation finished", nil, nil, 30000) end
Для shape типа "box" загрузка координат методом packet:r_matrix() окончилась неудачей. Я подозреваю, что не был прочитан вектор "offset", но точной уверенности нет, поэтому пока остановился на покомпонентной выборке и сохранении координат.
[править]
Часть 2.Создание точек перехода
Теперь следует написать функции создания нужных точек перехода и подключить их к игре. Сами функции просты:
db.actor:give_info_portion("freeplay_activated1") end
-- создается переход из ЧАЭС в Припять create_chaes2pripyat_exit()
-- актер перебрасывается в level_changer, возвращающий его на ЧАЭС, ко входу в бункер db.actor:set_actor_position( vector():set(-13.26, 47.71, 46.57) ) end
function refuze_o_sozn() if (not has_alife_info("freeplay_activated2")) then create_level_changer(21410, vector():set(946.872, 6.0, 167.66), 240852, 2637, 472710, 2280, vector():set( 1062.15, -0.0982, -3.512 ), vector():set( 0.0 , 0.0 , -1.0 ), "L12_Stancia", 1)
db.actor:give_info_portion("freeplay_activated2") end
-- создается переход из ЧАЭС в Припять create_chaes2pripyat_exit()
-- актер перебрасывается в level_changer, возвращающий его к правым воротам ЧАЭС db.actor:set_actor_position( vector():set(946.872, 6.0, 167.66) ) end
function create_chaes2pripyat_exit() -- создается переход из ЧАЭС в Припять if (not has_alife_info( "exit_chaes2pripyat_created" )) then create_level_changer(31410, vector():set( 917.35, 0.419, -316.35 ), 403866, 2401, 73868, 2117, vector():set( 31.3, 3.0, 240.0 ), vector():set( 0.0, 0.0, -1.0 ), "L11_Pripyat", 0)
db.actor:give_info_portion("exit_chaes2pripyat_created") end end Функцию exit_monolit я создал исключительно для тестирования, но решил оставить и тут. Вдруг кто-то захочет реализовать более сложный возврат: Меченого грузят в "грузовик смерти" и он снова приходит в себя на кордоне...
Функция exit_monolit создает «тихий» переход на уровень ЧАЭС-1 и обычный - в начале уровня ЧАЭС-1 для возврата в Припять, после чего перебрасывает актера прямо внутрь созданного перехода. Функция refuze_o_sozn делает тоже самое, только игрок появляется перед воротами в правом верхем углу карты (мне кажется, что так более логично). Все телепорты защищаются уникальными info_portions, дабы избежать их повторного создания, ведь игрок может захотеть «закончить» игру несколько раз.
Теперь подключение. Во-первых надо добавить новые info-portions. Я решил не изменять оригинальные файлы игры, а сделал для них (ну и для других тоже) отдельный файл config\gameplay\_info_sa.xml
Теперь в этот файл можно будет добавлять новые info_portion, которые вы будете использовать в своих сюжетах. Подключается этот файл в system.ltx в секции «info_portions»:
Кстати, именно так я рекомендую добавлять новые диалоги и новых персонажей. Это упростит процессы совмещения модов и аддонов.
Следующий шаг - подключение наших скриптов к игре. Для этого откройте файл
config\ui\ui_movies.xml
найдите элементы «mov_desire_» (их пять, по количеству ложных концовок игры - все варианты общения с Монолитом). Внутри каждого элемента есть дочерние элементы «function_on_stop», которые задают функцию, запускающуюся сразу после ролика. Стандартное содержимое:
Функция xr_effects.game_credits запускает финальные титры. Именно ее и нужно заменить на вызов нашей функции _freeplay_sa.exit_monolit. Вот что должно получиться:
Старый элемент я советую не удалять, а закомментировать.
Чуть ниже «mov_desire_5» находится тэг ролика для концовки «Присоединение к О-Сознанию». Его мы трогать не будем - Меченый станет медузой. А вот после него - тэг для ролика «Отказ от О-Сознания»: «mov_refuse_osoznanie». Функцию завершения в нем заменим следующим образом:
Можно запускать и, если есть сохранения перед монолитом и/или о-сознанием, тестировать. Первые переходы срабатывают «тихо» - запрос на смену уровня не выдается (в параметре p_silent задана 1). До перехода в Припять можно успеть добежать, пока не сработал выброс... Но это как-то неправильно, выброс надо остановить (он же произошел, пока мы были внутри станции). «По-честному» (скриптом, без модификации all.spawn) таймер выброса отключить не получится, но зато выброс можно подавить небольшим «хаком». Найдите файл xr_logic.script, а в нем - функциюswitch_to_section.Ее нужно модифицировать следующим образом:
-- Выполняет переключение на указанную секцию, если задана.
-- Если section == nil, остается работать старая секция. function switch_to_section(npc, st, section) if section == nil or section == "" then return false end
-- 15.03.2008 by SA: -- отключает "смертельные зоны" на ЧАЭС после запуска режима FREEPLAY -- таймер не отключается, но сам "выброс" не происходит if (section == "sr_aes_deadzone") then if (has_alife_info("freeplay_activated1") or has_alife_info("freeplay_activated2")) then return false end end
... далее без изменений ... end
Данный способ оставляет висящий на нулях таймер и все эффекты начала выброса, но сам «выброс» отключается.
И последнее: переход ЧАЭС1-Припять необходимо отметить на карте. Для этого существует вполне «легальный» механизм. Находим файлlevel_tasks.scriptи в конце функцииadd_lchanger_locationдописываем следующее:
-- aes (++16.03.2008 by SA): obj = sim:story_object(31410) if obj then level.map_add_object_spot(obj.id, "level_changer", "To Pripyat") end
Здесь 31410 - story_id нашего level_changer, который создается нашей функцией create_chaes2pripyat_exit.
На этом пока все (мелкие огрехи типа направления взгляда игрока после смены уровня исправлю позже). Прошу тестировать и дополнять.
- Получение параметров лч. function get_lc_data(obj) local packet = net_packet() obj:STATE_Write(packet) local size=packet:w_tell() packet:r_seek(0)
local t={} t.game_vertex_id = packet:r_u16() t.distance = packet:r_float() t.direct_control = packet:r_s32() t.level_vertex_id = packet:r_s32() t.object_flags = packet:r_s32() t.custom_data = packet:r_stringZ() t.story_id = packet:r_s32() t.spawn_story_id = packet:r_s32() local shape_count = packet:r_u8() t.shapes={} for i=1,shape_count do local shape_type = packet:r_u8() t.shapes<I>={} t.shapes.shtype=shape_type if shape_type == 0 then t.shapes.center = packet:r_vec3() t.shapes.radius = packet:r_float() else t.shapes.v1 = packet:r_vec3() t.shapes.v2 = packet:r_vec3() t.shapes.v3 = packet:r_vec3() t.shapes.offset = packet:r_vec3() end end t.restrictor_type = packet:r_u8() t.dest_game_vertex_id = packet:r_u16() t.dest_level_vertex_id = packet:r_s32() t.dest_position = packet:r_vec3() t.dest_direction = packet:r_vec3() t.dest_level_name = packet:r_stringZ() t.dest_graph_point = packet:r_stringZ() t.silent_mode = packet:r_u8() if packet:r_elapsed() ~= 0 then abort("left=%d", packet:r_elapsed()) end return t end
-- Запись параметров лч. function set_lc_data(t,obj) local packet = net_packet() packet:w_begin(t.game_vertex_id) packet:w_float(t.distance) packet:w_s32(t.direct_control) packet:w_s32(t.level_vertex_id) packet:w_s32(t.object_flags) packet:w_stringZ(t.custom_data) packet:w_s32(t.story_id) packet:w_s32(t.spawn_story_id) packet:w_u8(table.getn(t.shapes)) for i=1,table.getn(t.shapes) do packet:w_u8(t.shapes.shtype) if t.shapes.shtype == 0 then packet:w_vec3(t.shapes.center) packet:w_float(t.shapes.radius) else packet:w_vec3(t.shapes.v1) packet:w_vec3(t.shapes.v2) packet:w_vec3(t.shapes.v3) packet:w_vec3(t.shapes.offset) end end packet:w_u8(t.restrictor_type) packet:w_u16(t.dest_game_vertex_id) packet:w_s32(t.dest_level_vertex_id) packet:w_vec3(t.dest_position) packet:w_vec3(t.dest_direction) packet:w_stringZ(t.dest_level_name) packet:w_stringZ(t.dest_graph_point) packet:w_u8(t.silent_mode) packet:r_seek(0) obj:STATE_Read(packet, packet:w_tell()) end
-- Создание лч и перемещение ГГ(Автор Xiani). function start_jump_to(x,y,z,lv, gv, dx, dy, dz, level_name) amk.mylog("jump:create_lc") local lc = alife():create("level_changer", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id()) amk.mylog("jump:get_lc_data") local tbl = get_lc_data(lc)
local shapes={} shapes[1]={} shapes[1].shtype=0 shapes[1].radius = 10 shapes[1].center = vector():set(0,0,0)
db.actor:set_actor_position(lc.position) amk.mylog("jump:finished") end А использовать просто: function road_to_yantar(actor, npc) dialogs.relocate_money(npc, 3500, "out") start_jump_to(29.146209716797,-11.688985824585,-279.86639404297,54978,1480, 0,0,0,"L08_yantar") end -- попадёшь в бункер к Сахарову.
Уроки не мои , вроде авторов написал , а если нет , то источником служили документы к локационному моду , большое спасибо ребятам за их труд
Создание нового НПС через скрипт, создавать новые секции для НПС и создавать характеры, или редактировать старые.
Автор: Vova Miller [мод Истинный Путь]
1. Для начала создадим секцию нашего нового НПС. В файлеconfig\creatures\spawn_sections.ltxсоздаем секцию. Вот пример: Code [test_stalker_1]:stalker character_profile = test_stalker_1_xapaktep
test_stalker_1 - имя секции (не должно повторяться) stalker - сравнивается с уже существующей секцией stalker, чтобы не писать лишнего. character_profile - направление к классу характера. test_stalker_1_xapaktep - ID класса характера.
2. Создадим секцию класса вconfig\gameplay\npc_profile.xml.Пример: Code <character id="test_stalker_1_xapaktep">
test_stalker_1_xapaktep - сверху ID, а снизу название самого класса. Для чайников: Код нужно вводить между <xml> и </xml> Иногда ниже <class></class> прописывается: Code <specific_character>ID_профиля</specific_character>
Но в таком случае нельзя будет создать несколько "характеров" для одного класса. Я честно говоря не знаю зачем эта штука, но когда происходил вылет я приписывал это и всё решалось.
3. Теперь создадим сам характер. Пропишем его, скажем, вconfig\gameplay\character_desc_escape.xml
Вот пример: Code <specific_character id="test_stalker_1_xapaktep_1" team_default = "1">
Для чайников: Профиль нужно ставить между <xml> и </xml>.
<name>esc_wolf_name</name>- Имя НПС (прописать можно сразу на русском языке)
<icon>ui_npc_u_stalker_neytral_balon_1</icon>- Иконка НПС. Берётся из config\ui\ui_npc_unique.xml <bio>esc_wolf_bio</bio>- История НПС. (В игре не используется) <class>test_stalker_1_xapaktep</class>- наш класс. <community>stalker</community>- группировка НПС. <terrain_sect>stalker_terrain</terrain_sect>- terrain НПС. Берётся изconfig\creatures\m_stalker.ltx <rank>434</rank>- Ранг НПС. <reputation>5</reputation>- репутация НПС. <money min="600" max="2000" infinitive="0"/>- Минимальное (600) и максимальное (2000) кол-во денег. (Если вместо 0 поставить 1, то у НПС будет неограниченное кол-во денег.) <snd_config>characters_voice\human_01\stalker\</snd_config>- звуки НПС. <visual>actors\neytral\stalker_neytral_balon_1</visual>- форма НПС. Между<supplies>и</supplies>- Инвентарь НПС, а конкретно: патроны, оружие и другие предметы, типа рации.
4. Теперь наконец "заспавним" нашего НПС через скрипт.
Создайте свой скрипт в папкеgamedata\scripts\и пропишите в него: Code function my_func_1 ()
alife():create("test_stalker_1",vector():set( -49.19, -10.03, -61.49 ),230520,77) end
my_func_1- название функции (пригодится для выполнения)
test_stalker_1- спавним нашего нового Сталкера с данной секцией.
49.19, -10.03, -61.49- координаты X Y Z 230520- level_vetrex_id 77- game_vetrex_id
Данные координаты, это Кордон, в туннеле под дорогой, рядом с раненным Толиком. Напоминаю, что свои координаты можно снять через Position Informer.
5. Всё сделано, помимо одной вещи: Не выполняется функция спанва. Её выполнение можно прописать в диалог, или в инфопоршень. Пропишем, для примера, в инфопоршень, который выполняется с самого начала игры, то есть наш НПС тоже будет появляться с самого начала игры. Откройтеconfig\gameplay\info_portions.xmlи ниже:<task>storyline_eliminate_gunslinger</task>добавьте это:<action>имя_вашего_скрипта.my_func_1</action>. То есть весь инфопоршеньstoryline_actor_startбудет выглядеть так: Code <info_portion id="storyline_actor_start">
6. Запускаем игру, и если вы всё сделали правильно, то ваш НПС обязательно появится. Примечание: Начальный инфопоршень storyline_actor_start выполняется тогда, когда ГГ находится на Кордоне. Так что не пугайтесь, если вы таким образом заспавните НПС на Свалке и сами начнёте игру со неё и НПС не появится. Можно без проблем сделать отдельный инфопоршень, который выдаётся где бы ни был ГГ, и туда прописывать функции спавна.
Взял его урок так как он мне показался наиболее понятным .
Создание задания, типа сюжетных и пр. Например, найти, поговорить, убить. Научившись делать это, можно создать и не однотипные задания.
Автор: Vova Miller [мод Истинный Путь]
1. Для начала расскажу какова роль "Инфопоршней" в создании подобных заданий. Благодаря "Инфопоршням" мы можем сделать заданию условие выполнения, провала, начала квестов. Выполнить инфопоршень можно многими способами, и каждый инфопоршень только один раз.
2. Приступим к самому созданию квеста. Чтобы вас не запутать, для начала объясню как делается самое простое задание: Поговорить со Сталкером. Конкретнее, сделаем задание "Поговорить с Волком", состоящее из одного пункта. Открываем файл config\gameplay\tasks_escape.xml (В файлахconfig\gameplay\tasks_******.xmlхранятся основы заданий) Там, вставляем это (можно в самое начало): <!----------------------------------------------------------Поговорить с Волком---------------------------------------------------------->
Первая строка необязательна. Обычно я ставлю её над каждым новым заданием, чтобы в случае чего быстро найти любой сделанный тобою квест.
mod_perviy_quest- ID задания. Не должен повторяться с ID других квестов. prio="100"- важность задания, то есть на каком месте он будет стоять в PDA. Чем меньше значение, тем выше в PDA будет задание. <title>Информация</title>- заголовок задания Первый тег<objective></objective>- в нём сама основа задания (иконка, описание, инфопоршень выполнения, провала всего задания и т.д.) <text>Волк - не человек</text>- данный текст игра не читает, так что в это теге можно писать, что душа пожелает, но убирать его не стоит. <icon>ui_iconsTotal_esc_dinamit_to_volk</icon>- иконка задания. Берётся из config\ui\ui_iconstotal.xml <infoportion_complete>mod_perviy_quest_done</infoportion_complete>- инфопоршень, при выполнении которого выполняется всё задание. <infoportion_fail>esc_wolf_dead</infoportion_fail>- инфопоршень, при выполнении которого проваливается всё задание. <map_location_type hint="Волк">blue_location</map_location_type>- название метки и её тип. <object_story_id>esc_lager_leader</object_story_id>- куда будет указывать метка. Всегда используется вместе с предыдущей строкой. Берётся изconfig\game_story_ids.ltx <article>mod_perviy_quest_article</article>- описание задания. Берётся изconfig\gameplay\storyline_info_taskmanager.xml Второй тег<objective></objective>- составляет первый пункт задания. Так как квест у нас состоит из одного пункта, то содержимое этого тега пусто и заполнение некоторых строк необязательно. Если вы захотите создать квест уже с двумя пунктами, вам нужно будет создавать третий подобный тег. <text>Поговорить с Волком</text>- название первого пункта квеста. Следующие две строки снова метка. Присутствие этих двух строк в теге первого пункта необязательно.
Итак, с этим разобрались. В задании прописаны, но отсутствуют в игре инфопоршень выполнения, старта квеста (понадобится) и описание задания. Чтобы сделать описание откроем, как уже было сказано,config\gameplay\storyline_info_taskmanager.xml.В самый низ вставим: Code <article id="mod_perviy_quest_article" name="kill_stalker" article_type="task">
<text>Необходимо поговорить с Волком. Он должен был вернуть нам килограмм урана.</text> </article> Инфопоршни пропишем в файлеconfig\gameplay\info_l01escape.xml.После<game_information_portions>пропишем инфопоршень, при выполнении которого начнётся квест:
Code <info_portion id="mod_perviy_quest_start">
<task>mod_perviy_quest</task>
</info_portion>
mod_perviy_quest_start - ID инфопоршня. Не должен повторятся с другими. <task>mod_perviy_quest</task>- здесь мы указали ID нашего задания, которое стартует после выполнения данного инфопоршня.
И вставим инфопоршень выполнения квеста: Code <info_portion id="mod_perviy_quest_done"></info_portion>
Отступление: Возможно вы спросите: "А как же инфопоршень 'провала' квеста?" Инфопоршень провала квеста уже существует в оригинальном ТЧ. Он выполняется при смерти Волка. Конечно, если в будущем вам нужно будет поговорить с другим сталкером, то инфопоршень нужен будет уже другой. Вы его пропишете как новый и поставите его выполнение через логику данного НПС при смерти, но это уже другая тема.
3. Итак, основа задания готова. Теперь нужно 'внедрить' его в игру, то есть поставить куда-нибудь старт квеста (например, через диалог) и, в нашем случае, поставить диалог Волку, где выполнится задание. Как создать диалог? - Вы можете прочитать в учебнике от IP Team Диалоги: Создание и редактирование.
4. Не столь важный пункт в создании квеста, но всё же расскажу об этом. Если оставить задание так, то при его выполнении ГГ не будет получать опыт и выполненное задание не будет отображаться в PDA в Статистике. Исправим этот недочет. Открываемconfig\misc\task_manager.ltx.Там, строкой ниже [list ], вставляемmod_perviy_quest. В этом же файле в самый низ вставляем: Code [mod_perviy_quest] type = storyline reward_rank = 15
reward_rank = 15- количество получаемого опыта. Затем, чтобы в Статистике наш квест не отображался как"mod_perviy_quest", в файлеconfig\text\rus\ui_st_pda.xml(можно в любой другой, находящийся в этой же папке) перед</string_table>или после<string_table>прописываем: Code <string id="mod_perviy_quest">
</start_dialog>- это диалог, в котором первую ветку самого диалога будет говорит НПС (не забывайте, что</start_dialog>может использоваться у каждого НПС только один раз). </actor_dialog>- это диалог, в котором первая фраза будет твоя (можно использовать на одном НПС сколько угодно).
2. Теперь переходим к самому диалогу. Откраемconfig\gameplay\dialogs_(локация).xml Листаем в самый низ, и вставляем диалог перед</game_dialogs>и после</dialog>(</dialog>- закрывает предыдущий диалог, а между<game_dialogs>и</game_dialogs>содержаться все диалоги). Вот пример простейшего диалога, который можно сделать за 5 секунд (пример с</actor_dialog>):
Т.к. мы привязали этот диалог к НПС как actor_dialog, то у нас будет возможность сказать НПС: "Глупый НПС, дай денег!", в ответ получим: "Нету денег. Все уже раздал.", и снова мы можем ответить: "Ладно, завтра отдашь.". На последней фразе диалоговое окно зароется, т.к. на ней прописана функция: <action>dialogs.break_dialog</action> Напомню что бы было, если бы я прописал это не какactor_dialog, а как start_dialog, чтобы у вас в голове прояснилось в чем разница: НПС: "Глупый НПС, дай денег!" (сказал бы сразу при открытие диалогового окна) ГГ: "Нету денег. Все уже раздал." (и при нажатии на фразу диалог бы закрылся, т.к. в последней фразе стоит функция.)
Теперь посмотрим на ID фраз. Первую фразу всегда лучше начинать с 0. Это будет первая фраза. В ней же (в нашем примере) стоит:<next>1</next>, то есть следующая фраза подID 1. Предположим если первая фраза выглядела бы вот так:
То НПС мог бы нам ответить как и фразой с ID 1, так и с фразой ID 2 (в игре мы уже не сможем проконтролировать как конкретно ответит НПС). Если бы фразу "Глупый НПС, дай денег!" сказал бы НПС, то у нас бы было два варианта, как ответить ему фразами 1 и 2.
Если вы ничего не поняли, или просто лень разбираться в тексте, то предлагаю вам самим тестировать разные варианты в игре (например так я и научился создавать диалоги).
3. Построим диалог по-длиннее, чтобы вы поняли, как дополнять ещё фразы. Вот пример (actor_dialog): Code <dialog id="mod_my_first_dialog">
Попробуйте сами проанализировать, как диалог будет выглядеть в игре (запишите скажем на листочке), а потом уже посмотрите как получится в игре. Если у вас не было ни одной ошибки, то смело переходите к следующему пункту. Если же были ошибки, то проверьте в чем ошиблись, и лучше ещё рассмотрите структуру диалогов в конфиге.
4. Здесь чуть позже научу вас как прописывать функции в диалог (забирает деньги, даёт деньги, даёт предметы или забирает и т.д.) и др.
Примечания:
1:start_dialogможет использоваться только на одном диалоге у определённого НПС.
2: В конфиге диалога нельзя писать большие тексты, иначе будет вылет. Чтобы написать большой текст во фразу и чтобы не было вылета, в конфиге диалога на месте текста, напишите, например:mod_long_phrase_1 Откройтеconfig\text\rus\stable_dialogs.xml, листай в самый низ, и вставьте следующий код после</string>и перед</string_table>:
Code <string id="mod_long_phrase_1">
<text>Большой текст нужно писать сюда</text> </string>
Такой принцип может использоваться не только для больших текстов.
3: Замечали, что в оригинале ТЧ в некоторых диалогах воспроизводился голос? Вы можете сделать то же самое. Пользуясь схемой, как в п. 2, делаем такую же фразу для НПС, на которой проиграется звук (не работает на фразах ГГ). Предположим мы между<text>и</text>прописали:mod_long_phrase_2. Открываем папку:sounds\characters_voice\dialogs\и туда добавляем нужный нам звук с названиемmod_long_phrase_2.ogg.
4 (Инфопоршни): Как же сделать, чтобы в ветке диалога выполнялся инфопоршень, и чтобы диалог не повторялся бесконечно? Помогут "инфопоршни". Как поставить выполнение инфопоршня в диалог? - В определённую ветку диалога ниже текста вставляем :
Code <give_info>ID_инфопоршня</give_info> Как сделать чтобы диалог не повторялся? - В созданном диалоге выше<phrase_list>, но ниже строки с ID диалога вставляем: Code <dont_has_info>инфопоршень_1</dont_has_info>
И в ветку диалога, после которой он больше не будет повторятся вставляем выполнение инфопоршня "инфопоршень_1". То есть для диалога мы указали, чтобы он отображался, если "инфопоршень_1" не выполнен.
Как сделать чтобы какой-либо диалог отображался только после другого диалога? - В первый диалог, после которого откроется другой, в нужную ветку вставляем выполнение инфопоршня, например, "инфопоршень_2". Во второй диалог, который должен появится после первого, выше<phrase_list>, но ниже строки с ID диалога вставляем:
Code <has_info>инфопоршень_2</has_info>
То есть, мы сделали так, чтобы второй диалог не отображался, пока не выполнится "инфопоршень_2".
Кстати, теги<has_info>и<dont_has_info>можно использовать не только для всего диалога, но и для отдельной ветки диалога. Тогда, их нужно вставлять выше тега текста.
ID инфопоршней прописываются вconfig\gameplay\info_*******.xml
это попытка автора создать телепорт через скрипт , без папочки all. так что можете пробовать и вполне удача вам улыбнется , а нет то получите опыт работы со скриптами
Теория этого дела
В игре существует такой объект как "zone_teleport", но если мы его создадим через create, то он будет выглядеть и переливаться как настоящий телепорт, но телепортировать нас куда-либо увы не сможет. Связано это с тем что, у аномалий ( а телепорт это такая разновидность аномалии ) параметры задаются хитромудро, через all.spawn. Вобщем штатным способом телепорты без полнофункционального редактора карт не получить (хотя возможно я не прав уже после написания этого текста появились идеи как это сделать через all.spawn). Значит на нашу долю остаються способы "не штатные" Реализуем самый простой. Будем считать что у нас на карте есть квадрат с заданными координатами при попадании в который актера должно переместить в точку с другими координатами. Для этого будем периодически проверять координаты актера, и если он в квадрате - перемещяем. Вот в краце принцип действия нашего "самодельного" телепорта. Реализация
В каталоге gamedata\scripts\ Создадим файл bind_mteleport.script с логикой работы нашего телепорта. -- ************************************************
function actor_update(delta) local i,v,acter_poz,s
-- Получим позицию актера (что-бы каждый раз не запрашивать) acter_poz = db.actor:position()
-- Проверяем наши телепорты for i, v in pairs(teleport_binders) do s = v.parametrs
local obj = level.object_by_id( i ) if obj ~= nil then -- Наш телепорт в онлайне проверяем дальше if s.teleporte ~= nil and s.teleporte ~= false then -- Телепорт запущен if ( time_global() <= s.time ) then -- Если время отведенное на показ спецэфектов -- прошло, производим телепортацию teleportate(s.poz_x,s.poz_y,s.poz_z) if s.rotate ~= nil then db.actor:set_actor_direction(s.rotate) end s.teleporte = false end return end
-- Пороверим не забрел-ли актер в наш телепорт if (abs_comp(s.x, acter_poz.x)< v.parametrs.radius and abs_comp(s.z, acter_poz.z)< v.parametrs.radius and abs_comp(s.y, acter_poz.y)< v.parametrs.z_radius) then -- Актер в зоне действия телепорта, запустим телепорт s["teleporte"] = true s["time"] = time_global() + 500
-- Запускаем спецэфекты телепортации level.add_pp_effector ("teleport.ppe", 2006, false) end end end end
function bind( obj ) obj:bind_object( restrictor_teleport( obj ) ) end
---------------------------------------------------------------------------------------------------- class "restrictor_teleport" ( object_binder )
function restrictor_teleport:__init(obj, char_ini) super(obj) end
function restrictor_teleport:net_spawn(data) local char_ini = system_ini()
-- Если это телепорт то занесем его в специальный список телепортов if self.teleport == true then teleport_binders[self.object:id()] = self
-- Заполним таблицу параметров self["parametrs"] = {} if char_ini:line_exist(self.section, "radius") then self.parametrs["radius"] = tonumber(char_ini:r_string(self.section, "radius")) else self.parametrs["radius"] = 2 -- Дефолтный радиус по xy end if char_ini:line_exist(self.section, "z_radius") then self.parametrs["z_radius"] = tonumber(char_ini:r_string(self.section, "z_radius")) else self.parametrs["z_radius"] = self.parametrs["radius"] -- если радиус высоты не задан то задаем равным радиусу xy end
-- Запомним позицию что-бы каждый раз не считать local s_obj = alife():object(self.object:id()) self.parametrs["x"] = tonumber(s_obj.position.x); self.parametrs["y"] = tonumber(s_obj.position.y); self.parametrs["z"] = tonumber(s_obj.position.z);
if char_ini:line_exist(self.section, "rotate") then self.parametrs["rotate"] = tonumber(char_ini:r_string(self.section, "rotate")) end end return true end
function restrictor_teleport:net_destroy() -- Удаляем наш телепорт teleport_binders[self.object:id()] = nil self.parametrs = nil object_binder.net_destroy(self) end
function restrictor_teleport:reload(section) local char_ini = system_ini()
self.section = section -- Если это телепорт то if char_ini ~= nil and char_ini:line_exist(self.section, "teleport") then self["teleport"] = true end end
Для постоянного обновления нужно прицепить функцию actor_update() к биндеру актера, для чего в файле bind_stalker.script найдем функцию:
function actor_binder:update(delta)
В ней найдем вызов обновления рестрикторов bind_restrictor.actor_update(delta) под которым вставим строку с вызовом нашей функции обновления: bind_mteleport.actor_update(delta)
Все с программной частью закончили, теперь задаем данные телепорта.
В каталоге gamedata\config\misc открываем файл zone_teleport.ltx и в конце файла добавляем следующие строки описывающие конкретный телепорт: [m_teleport_1]:zone_teleport teleport = standart script_binding = bind_mteleport.bind ;Параметры нашего телепорта radius = 2 ;Высота захвата телепорта z_radius = 2
;Куда телепортируемся (телепортация всегда идет в пределах карты) poz_x = 22.78 poz_y = 20.35 poz_z = 659.24
; Угол зрения при появлении. Если параметра нет то не меняется. rotate = 1.5
Параметры нашего телепорта: radius - на самом деле не радиус, а половина длинны стороны нашего квадрата (в начале я хотел сделать его кругом, но посчитал, что лучше не тратить процессорное врямя по пусту). Центром квадрата является точка респавна телепорта. z_radius - высота нашего телепорта. poz_x, poz_y, poz_z - координаты точки телепортации. rotate - Угол поворота после телепортации от оси X (я не разбирался в каких единицах задается, но 1.5 примерно равно 90 градусов). Если параметр удалить то будет оставатья угол под которым актер вошел в телепорт. Использование
Теперь с помощью create создадим наш телепорт: Пример: local obj local a = vector() a.x = -244.55 a.y = -19.46 a.z = -125.42 obj = alife():create("m_teleport_1",a,12829,8,65535)
Создаст телепорт возле выхода из бункера Сидоровича. Наш телепорт перебрасывает игрока на вышку блокпоста (перед выходом с уровня).
Я пытался этим способом не вышло. Игра не принимает типы совмещения портов. То есть не желает создавать т.к. два телепорта в одном месте капризничают)
Ну надо сделать их подальше друг от друга , ведь даже вход на локацию и выход с нее нужно делать в разных местах желательно на хорошем расстоянии , а то будет кидать туда и обратно, но данный урок я написал он только теоретический ,надежнее через all. но попробуй развести порты подальше
Я еще Милера попросил написать урок по затирки сюжетной линии на примере начала игры , а то многие советуют , но это через all, а он обещал скриптами, единственное что у него со временем туго , они все рожают Истинный путь .Пролог. как бы начало своего мода ИП , надо кстати его мод сюда на сайт закинуть.
Меня просили как можно содавать худ и что это вот ответ , атора я незнаю , но большое спасибо человеку за его старания
Теория
Мне кажется многие задавались вопросом "Как же создать худ маски"? Немного пораздумав, я создал функцию, которая крепит текстуру к определенному костюму.
Опытным модмейкерам может показаться моя функция усложненной, но главное, что все работает и не вылетает! [править] Практика [править] Работа со скриптами
Первым делом в директории gamedata\scripts создайте файл с названием xr_mask.script
Открываем его пишем:
function hud_gas() local slot_stalker = db.actor:item_in_slot(6) local object_1 = db.actor:object("stalker_outfit") local slot_killer = db.actor:item_in_slot(6) local object_2 = db.actor:object("killer_outfit") if slot_stalker and slot_stalker:section() == "stalker_outfit" and object_1 ~= nil or slot_killer and slot_killer:section() == "killer_outfit" and object_2 ~= nil then local hud = get_hud() local custom_static = hud:GetCustomStatic("hud_gas") if custom_static == nil then hud:AddCustomStatic("hud_gas", true) end else local hud = get_hud() local custom_static = hud:GetCustomStatic("hud_gas") if custom_static ~= nil then hud:RemoveCustomStatic("hud_gas", false) end end end
Теперь поясню:
function hud_gas() -- функция local slot_stalker = db.actor:item_in_slot(6) -- переменная костюма local object_1 = db.actor:object("stalker_outfit") -- переменная объекта local slot_killer = db.actor:item_in_slot(6) -- переменная костюма local object_2 = db.actor:object("killer_outfit") -- переменная объекта if slot_stalker and slot_stalker:section() == "stalker_outfit" and object_1 ~= nil or slot_killer and slot_killer:section() == "killer_outfit" and object_2 ~= nil then -- проверяем надет ли костюм сталкера\наемника local hud = get_hud() -- худ local custom_static = hud:GetCustomStatic("hud_gas") if custom_static == nil then -- если худа нет, выдаем, если одет костюм hud:AddCustomStatic("hud_gas", true) end else local hud = get_hud() local custom_static = hud:GetCustomStatic("hud_gas") if custom_static ~= nil then -- если худ есть, убираем при смене костюма hud:RemoveCustomStatic("hud_gas", false) end end end
Теперь зайдем в bind_stalker.script, который находится в gamedata\scripts, найдем функцию: function actor_binder:update(delta) и после пишем: xr_mask.hud_gas() в итоге:
function actor_binder:update(delta) xr_mask.hud_gas() object_binder.update(self, delta) local time = time_global() game_stats.update (delta, self.object)
[править] Работа с XML - описателем
Итак, заходим в директорию gamedata\config\ui, находим файл с названием ui_custom_msgs, открываем его и в самом конце перед строкой: </header> пишем:
<hud_gas x="0" y="0" width="1024" height="768" stretch="1"> <texture>hud\hud_gas</texture> -- текстура маски. Посмотрите внимательно в скрипте мы указывали '''hud_gas''' </hud_gas>
[править] Текстура
Теперь заходим в gamedata\textures\ui, находим файл с названием ui_mainmenu.dds. Копируем его, заходим в gamedata\textures\hud вставляем его и переминуем в hud_gas.dds Открываем программой Adobe Photoshop и рисуем подходящую для вас маску.
Еще один урок от vova Miler . правда он не совсем скриптовый , но все же частично скриптовый частично ACDC.
Удаление оригинального сюжета в игре S.T.A.L.K.E.R Shadow of Chernobyl Повествует Vova Miller (IP Team)
В этом относительно небольшом учебнике я отвечу на частый вопрос начинающих модостроителей и просто любителей покопаться в файлах игры. Итак, как же убрать оригинальный сюжет из игры? На самом деле, чтобы ответить на этот вопрос исчерпывающе, понадобится чрезвычайно большое количество букв и страниц для одного учебника. Но, во-первых, я надеюсь, что Вы люди сообразительные, и мне не придётся расписывать каждую мелочь. Во-вторых, я опущу много деталей, которые большинству либо вообще не понадобятся, либо до которых Вы все сами сможете додуматься, если захотите. Под “деталями” я подразумеваю такие элементы оригинального сюжета, как, например, задание с Кротом на Агропроме, с Бесом на Свалке, с Кругловым на Дикой территории и ещё неимоверное количество подобных заданий, которые могут всплыть сами по себе, без прохождения ряда других квестов. В этом же учебнике я в большей степени обращу внимание на то, как убрать начальную болтовню Сидоровича, заточение в его же “погребе” и другие мелочи, которые касаются оригинального сюжета в начале игры.
Для удаления сюжета Вам понадобятся: Хотя бы самые базовые умения делать моды Папка gamedata со всеми файлами оригинальной игры (далее я не буду каждый раз говорить, что нужно перенести этот файл в вашу папка gamedata, бла-бла, и тому подобное, я основываюсь на то, что вы сами сообразите, что да как) Блокнот для работы с текстовыми документами ACDC для работы с all.spawn
Сидорович Чтобы жирный наглец не трепал языком в начале игры, а также чтобы мы смогли спокойно выйти из его конуры, нам потребуется изменить 2 файла: gamedata\config\scripts\esc_trader.ltx gamedata\config\scripts\esc_trader_door.ltx Не буду объяснять, что конкретно нужно менять и почему, потому что у большинства от этого голова перейдёт в состояние сублимации. Как должен выглядеть результат изменений этих файлов, смотрите приложение 1 в архиве с учебником. Далее уберём стартовые диалоги Сидоровича. В файле gamedata\config\gameplay\character_desc_escape.xml находим такие строчки:
Это набор диалогов торговца, он находится почти в самом начале файла, начинается на 21-й строчке в оригинальном файле игры. Чтобы убрать ненужные нам разговоры, выше приведённые строки нужно заменить на: <actor_dialog>escape_trader_talk_info</actor_dialog> <actor_dialog>tm_trader_dialog</actor_dialog> <actor_dialog>tm_trader_reward</actor_dialog> Инфопоршни Чтобы убрать одну из причин появления оригинального задания “Убить Стрелка” (вторую рассмотрим чуть позже), нам понадобится файл gamedata\scripts\bind_stalker.script Находим там следующее (в оригинальном файле игры на 314-й строке): if not has_alife_info("storyline_actor_start") and (level.name() == "l01_escape") then self.object:give_info_portion("storyline_actor_start") _G.g_start_avi = true printf("*AVI* RUN START AVI") end И заменяем эти строки на следующие: if not has_alife_info("esc_serious_talk") then self.object:give_info_portion("esc_serious_talk") end if not has_alife_info("tutorial_end") then self.object:give_info_portion("tutorial_end") end Вообще, можно было просто удалить выше приведённые строки, но, вставив другие, мы активировали инфопоршни, благодаря которым у Сидоровича появятся некоторые стандартные ветки диалога, типа “Мне нужно работа. Есть что на примете?”. all.spawn Сейчас нам придётся удалить немало объектов в файле gamedata\spawns\all.spawn Здесь блокнотом не обойтись. Настоятельно советую Вам для редактирования данного файла использовать программу ACDC. Быть может, новичку в ней сложно сориентироваться, почему многие берутся за программу xrSpawner, где всё предельно ясно, но тем самым в будущем вы осознаете, что допустили ошибку. Например, программа xrSpawner хоть и в меру удобная, но в ней чрезвычайно ограничены возможности редактирования all.spawn, взять те же патрульные пути (заданные точки, по которым двигаются транспорт, монстры, НПС). Более того, отредактировав файл в xrSpawner’е, вы, с большей вероятностью, банально не сможете после этого перейти на пользование программой ACDC с целью отредактировать всё тот же all.spawn, будут ошибки при декомпиляции. Так что привыкайте к ACDC, в будущем не пожалеете. Эту программу вы сможете найти в архиве с учебником. Итак, декомпилировав all.spawn, открываем файл alife_l01_escape.ltx В подобного рода файлах каждый объект обычно нумеруется. Например, в первой строчке: [0] – это объект, грубо говоря, с номером 0. Всё, до строчки [1] (не включительно) относится к этому объекту. Поэтому, если я скажу вам, что нужно будет удалить объект [0], то вы удалите всё, что его касается, то есть все строчки (отступы можно оставить) до строки [1] (повторяюсь, не включительно, то есть строку [1] удалять не нужно, иначе вы заденете объект, который трогать не нужно было). Приступим, наконец, к удалению. Нам требуется удалить: [90], [91], [92], [255], [257], [286], [840]. К удалённым объектам относятся: выдачи сюжетных заданий из оригинальной игры (начальное задание “Убить Стрелка” включительно), сцена с “плотью-суицидкой” около входа в бункер Сидоровича.
Теперь, если Вы запустите игру, предварительно всё сделав правильно, то при старте новой игры вы появитесь всё у того же торговца. Но теперь он не толкует начальную речь, у него нет диалогов о всяких Стрелках и документах с Агропрома. Дверь Сидоровича уже предварительно открыта. Стартовое задание отсутствует. Если вы пробежитесь по Кордону, то на вас не будут навешивать задания из оригинальной игры, и всё, казалось бы, хорошо. Но осталось неимоверное количество деталей, о которых я и говорил в самом начале. Некоторые из них, что у меня есть на памяти, могу перечислить. Бесполезный кейс на блокпосте; отсутствие возможности поговорить с кем-либо в лагере новичков; появление неведомой метки о каком-то сталкере на карте; после прохождения некоторых локаций, возможно, появятся НПС, связанные с сюжетом из оригинальной игры и т.д. И, представьте, это только Кордон, я уж промолчу про другие локации. Впрочем, если разобраться, то всё это можно убрать самому и не стоит донимать других людей, чтобы те отвечали всегда на вещи, с которыми вы можете поработать сами, что пойдёт только на пользу в плане умений делать моды. В принципе, саму основу оригинального сюжета мы убрали.
Все изменения, описанные в этом учебнике, я сохранил в архиве в виде отдельного мода в приложении 2.
На этом всё. Буду рад, если кому-то поможет этот небольшой туториал. Удачи в модостроении!
ДЛЯ ТЕХ КОМУ ВАЖНА ЭТА ТЕМА ДАЮ ПРЯМУЮ ССЫЛКУ НА УРОК МИЛЛИРА ПО ЗАТИРКЕ СЮЖЕТА Скачать учебник...