Как изменить спавн гг в сталкер тч
Спавн через скрипт
Содержание
1 Теория
2 Практика (часть 1)
3 Практика (часть 2)
4 Спавн NPC
5 Авторы
В скриптах есть одна единственная функция, отвечающая за спавн объектов:
alife():create(section,position,levelvertex,gamevertex)
Строго говоря, их две: create create_ammo но различия между ними не существенны. Imp 22:45, 23 июля 2007 (EEST)
Первый параметр - секция в конфигурациях, описывающая объект, например "bolt","med_kit" - это простые секции, простых объектов а есть объекты, которые переходят в онлайн/оффлайн, это неписи, монстры и так далее, например mil_killer_respawn_2 - спавнится снайпер группировки киллеров.
С позицией, думаю объяснять не надо, только существует нюанс - высота это Y, а не Z. Задать позицию можно такой конструкцией vector():set(x,y,z), где x, y и z - координаты точки на уровне, где спавним объект.
Дальше сложнее, так как сам толком сформулировать не могу.
Начнем от простого к сложному. На каждом уровне много объектов, все объекты состоят из полигонов, у каждого полигона есть вершины – вертексы.
Именно они и должны здесь указываться, зачем - не особо понимаю, скорее всего для точного позиционирования объекта. Например, можно получить вертекс ближайший к актору - db.actor:level_vertex_id()
Дальше идет гораздо более интересный параметр game_vertex_id, это почти то же самое, что и level_vertex_id, но (!) это глобальные величины! Если level_vertex считается для уровня, то game_vertex_id - для всей игры, и нужен он для того, чтобы указать на какой карте спавнить объект (более вразумительного объяснения я не нашел).
Соответственно, чтобы заспавнить что-нибудь на другой карте, достаточно указать game_vertex_id в четвертом параметре Например:
db.actor:game_vertex_id()
Итак, чтобы, например, заспавнить болт под ногами актора, пишем:
alife():create("bolt", db.actor():position(), 1, db.actor:game_vertex_id())
Почему 1, а не level_vertex_id? Проверено - разницы особой нет, какой level_vertex_id, хотя в некоторых случаях надо прописывать валидный вертекс, а то предмет может просто заспавнится не там, где планировалось. Но по большей части все проходит нормально и с единицей. (Игнорирование level_vertex_id может приводить к проваливанию произведенных предметов/персонажей под землю.) А вот game_vertex решает все - он указывает на каком уровне спавнить предмет, поэтому его надо указывать. Теоретически можно просто найти для каждого уровня по одному game_vertex'у и использовать их в скриптах. На самом деле game_vertex показывает какой фрагмент карты используется (вся карта разбита на кусочки имеющие сквозную нумерацию по всем уровням и game_vertex выбирает нужный) соответсвенно неправильное использование черевато.
Кроме того - есть еще один параметр - ID объекта, если указать ID NPC или актора - то предмет заспавнится у него в инвентаре.
Пример (спавним артефакт Медуза в инвентаре у актора):
alife():create("af_medusa", db.actor():position(), 1, db.actor:game_vertex_id(), db.actor:id())
Функция спавна возвращает серверный объект, то есть ни NPC, ни монстра ни что-либо еще.
Серверный обьект позволяет свеже созданного NPC или тайник затарить разными рулезами/артефактами. Например, вот так создадим перед входом к Сидоровичу долговца и засунем в него пачку патронов:
local obj
local a = vector() -- Задаем тип переменной
local dir = db.actor:direction()
a.x = -243.61 -- координата X
a.y = -19.52 -- высота Y
a.z = -127.17 -- координата Z
obj = alife():create("bar_dolg_respawn_3", a, 13193, 8, 65535)
alife():create_ammo("ammo_9x18_fmj",
obj.position,
obj.m_level_vertex_id,
obj.m_game_vertex_id,
obj.id,
20) -- число патронов
Кстати, create_ammo - практически тоже самое, что и create, разница в том, что create_ammo предназначена специально для спавна патронов и позволяет создавать неполные пачки патронов. Возможно есть еще какие-то отличия. Стоит учесть, что сами авторы игры спавнят патроны исключительно через create_ammo. Imp 22:38, 23 июля 2007 (EEST)
Просто минимальный набор - координаты, ID, секция,а из него (серверного объекта) обычно нужен только ID, так как по ID можно получить этот самый серверный объект:
(alife():object(id))
Его можно использовать, чтобы поставить метку, например, но я его лично использую для других целей - спавн сложных объектов, конкретно – NPC.
Например надо решить следующую задачу - надо создать наемника, сменить ему группировку и изменить его инвентарь, ну и в нагрузку - сделать другом для игрока.
В определенный момент заспавненый объект переходит онлайн, в этот момент вызывается callback - net_spawn.
Что мы делаем? Сверяем ID онлайн объекта с сохраненным ID!
Если они совпадают, например так:
if obj:id()==saved_id then .
Важно то, что у серверного объекта ID - это параметр, а у онлайнового объекта ID получается с помощью функции. Это важно, а то можно прогореть.
Итак, мы поймали нашего киллера по ID.
Далее все очень просто - вызываем команды для спавна гаусса и патронов к нему в инвентаре NPC (см. выше), меняем группировку специальной функцией, и делаем его другом.
Зачем такие сложности? Просто в оффлайне NPC как бы не существует, есть только косвенное упоминание о нем, и, плюс, все эти функции работают именно с объектом типа "NPC", а не с серверными объектами.
Более простая функция спауна в одну строчку:
Пример:
alife():create("stalker",vector():set(0,0,0),1,135) -- спаунит сталкера на водокачке. (Игра ЧН, на уровне Болото)
alife():create(section,position,levelvertex,gamevertex)
section - это секция предмета
position - Это его позиция (Через vector()) Брать в игре с помощью консольной команды rs_stats 1 или rs_cam_pos 1 (Тока в ЧН)
levelvertex - Пусть равно 1
gamevertex - Его Game Vertex, определяет уровень где будет спаун.
GV можно взять либо скриптом, либо через распакованный all.spawn.
Практика (часть 1)
1. Чтобы не повторяться в описании создания нового квеста, просто изучите статью по созданию квестов от Fr3nzy – лучшей статьи на эту тему я просто не видел :) Мы просто свяжем все воедино и научимся спавнить объекты из скрипта.
Почему предпочтительнее делать спавн скриптом, а не через тот же xrSpawner? Программа xrSpawner, при всех своих достоинствах, обладает одним недостатком, а именно – она делает спавн через файл all.spawn, что приводит к:
Невозможности совместить два мода, такой спавн использующих
Необходимости каждый раз начинать новую игру
При спавне через скрипт ситуация иная: в подавляющем большинстве случаев, ранее сохраненные игры будут работать, что не может не радовать :)
Итак, определимся с квестом.
Задача: после разговора с Сидоровичем спавним зомби на территории фабрики в первой локации. Для того, чтобы не повредить оригинальный сюжет игры, задание будет выдаваться после прохождения квеста с флешкой Шустрого, так как появись там зомби одновременно с бандитами и Шустрым. я думаю, исход боя предрешен :)
Реализация: Постараюсь описать все действия максимально подробно, буквально по шагам. Первым делом запустите игру :)
В консоли введите команду:
rs_stats on или rs_stats 1
Тем самым мы включаем вывод информации на экран. Далее вводим еще одну команду:
demo_record 1
И «летим» на фабрику. Нам нужно выбрать место для спавна объектов и данный режим как нельзя лучше подходит для реализации задуманного. Помещаем камеру в точке предполагаемого спавна и записываем координаты - у меня получились 115, -6, -16.
Для выхода из режима demo_record нажимаем Esc, в консоли пишем rs_stats off или rs_stats 0 (убираем вывод информации).
Добавим пятую модель.
Для этого в конце файла создадим секцию:
[zombie_ghost]:zombie_strong
Это означает, что наш пятый зомби наследует все параметры zombie_strong, мы добавим лишь визуальное представление.
Все. Сохраняем изменения и закрываем файл.
2. Пишем скрипт спавна. В папке gamedata создаем новую папку scripts, в ней создаем новый текстовый документ и называем его esc_zombie.script.
При написании статьи использовался оригинальный скрипт zombie_story.script из horror-mod’а. Концепция спавна перенесена практически без изменений, поэтому на авторство этого способа спавна я никоим образом не претендую :)
Итак, открываем наш пустой файл на редактирование, первой строкой объявляем переменную, в которой хранятся наши зомби:
local zombie_types =
Далее пишем функцию:
function spawn_zombies( position, total )
local zombie_index -- тип зомби из массива zombie_types
local new_pos, x_offset, z_offset -- объявляем переменные
for zombie_index=1, total do -- крутим цикл столько раз, сколько
задает переменная total
x_offset = math.random(5) -- случайное (рандомное) x от 1 до 5
z_offset = math.random(5) -- случайное (рандомное) z от 1 до 5
new_pos = position -- передаем координаты в функцию
new_pos.x = new_pos.x + x_offset -- прибавляем к указанной нами
координате x полученное выше рандомное x
new_pos.z = new_pos.z + z_offset -- прибавляем к указанной нами
координате z полученное выше рандомное z
-- Ниже, собственно и вызывается функция спавна случайного типа зомби
zombie_types[math.random(5)] привязанного к нашим координатам
alife():create(zombie_types[math.random(5)],new_pos,db.actor:level_vertex_id(),db.actor:game_vertex_id())
end
end
И последнее:
function zomby_story_1( actor, npc )
-- десять зомби на фабрике (Кордон)
local spawn_point = vector():set( 115, -6, -16 ) -- здесь указываем координаты,
выбранные нами для спавна, когда «летали» камерой :)
spawn_zombies( spawn_point, 10 ) -- собственно вызов предыдущей функции
с передачей ей координат и количества объектов
end
Все. Сохраняем и закрываем файл.
Для того, чтобы игра не вылетала после того, как мы добавили новый тип монстров, их нужно добавить в файл xr_statistic.script. Итак, скопируем этот файл из папки игры scripts в нашу папку к файлу esc_zombie.script и откроем на редактирование.
Добавим в local killCountProps к монстрам строчку:
zombie_weak = 1, zombie_normal = 2, zombie_strong = 3
В local sect_alias строчку:
zombie_weak = "zombie_weak", zombie_normal = "zombie_normal", zombie_strong = "zombie_strong"
А ниже в monster_classes строчку:
[clsid.zombie_s ] = "zombie"
В функцию getNpcType(npc) добавляем конструкцию:
elseif npc:character_community() == "zombie" then
community = "zombie"
Сохраняем изменения и закрываем файл.
Все верно – игра не знает какую иконку нам показывать для зомби. Иконки монстров хранятся в файле ui_npc_monster.dds. Здесь есть два варианта:
Если дружите с Фотошопом, отредактировать этот файл (нарисовать, добавить иконки);
Взять готовый из любого мода, естественно, с разрешения авторов мода. Сейчас мы пропустим данный аспект и присвоим нашим зомби иконки контролера :)
Вернемся к файлу m_zombie.ltx и в секцию [m_zombie_e]:monster_base впишем параметр
icon = ui_npc_monster_kontroler
Все. Вылетов не будет.
3. Тема данной статьи не предусматривает подробного описания того, как сделать новый диалог. В начале статьи я упомянул источник, где можно найти исчерпывающую информацию по созданию диалогов, могу также привести в пример статью по созданию диалогов от BAC9-FLCL.
Нам нужно просто проверить работоспособность скриптового спавна, поэтому я приведу просто собственно сам измененный диалог из файла dialogs_escape.xml:
<dialog >
………
<phrase >
<text>escape_trader_talk_info_999</text>
<next>7770</next>
<next>9991</next>
<next>9992</next>
<next>9993</next>
<next>9994</next>
<next>9995</next>
<next>9996</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_9992</text>
<next>99922</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_99922</text>
<next>9996</next>
<next>9995</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_9993</text>
<next>99933</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_9995</text>
</phrase>
<phrase >
<text>escape_trader_talk_info_3121</text>
<next>9996</next>
<next>9995</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_3131</text>
<next>9996</next>
<next>9995</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_41</text>
<next>9996</next>
<next>9995</next>
</phrase>
<!------Наш диалог: Начало------->
<phrase >
<text>escape_trader_talk_info_7770</text>
<next>7771</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_7771</text>
<next>7772</next>
<next>7773</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_7772</text>
<next>7777</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_7773</text>
<next>7779</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_7779</text>
<next>9996</next>
<next>9995</next>
</phrase>
<phrase >
<text>escape_trader_talk_info_7777</text>
<action>esc_zombie.zombie_story_1</action>
<next>9996</next>
<next>9995</next>
</phrase>
<!------Наш диалог: Конец------->
<phrase >
<text>escape_trader_talk_info_51</text>
<next>9996</next>
<next>9995</next>
</phrase>
……
</dialog>
И также связанный с ним файл stable_dialogs_escape.xml. В самом начале файла пишем следующее:
<string >
<text>Происшествий никаких не было?</text>
</string>
<string >
<text>Да знаешь. Вроде как тихо все у нас. Хотя, вот, вспомнил! Говорили мне
на днях, что на фабрике, ну, там, где бандюки околачиваются постоянно, видели какиих-то то ли
людей, то ли призраков. Мало ли что спьяну почудится - я и сказал этим паникерам, мол,
закусывать надо! Хех, блин, алкаши. </text>
</string>
<string >
<text>Дык мне по любому мимо фабрики топать - заодно и посмотрю на этих
"людей-призраков".</text>
</string>
<string >
<text>Да я как-то не собирался в ту сторону. </text>
</string>
<string >
<text>Ну, смотри сам, все равно будь осторожен.</text>
</string>
<string >
<text>Ага. Сходи, проветрись. Потом зайдешь, расскажешь, что там и как.</text>
</string>
<string >
<text>Здесь проход воспрещён, сталкер.</text>
</string>
Все. Можно запускать игру, идти на Кордон, после разговороа с Сидоровичем, в зависимости от выбранного Меченным решения, бежим на фабрику и … смотрим сами :)
Готовые файлы примера(перезалито)
Spawn Lib
Домашнее задание - вернуть в игру 6-ой тип гражданского зомби :)
Практика (часть 2)
Файл модели до редактирования
Файл модели после редактирования
На скринах видно, что мы просто изменили для этой модели путь к текстуре. Все. Без использования 3D-редакторов и затраты кучи времени на обработку модели в них, мы получили абсолютно новую (на внешний вид) модель. :)
в файле esc_zombie.script изменяем массив в первой строке:
local zombie_types = "zombie_old", "zombie_ghost">
В функции spawn_zombies изменяем строку спавна:
alife():create(zombie_types[math.random(6)],new_pos,
db.actor:level_vertex_id(),db.actor:game_vertex_id())
в функции zombie_story_1 меняем число объектов на кратное 6-ти (необязательно):
spawn_zombies( spawn_point, 12 )
Всё. Сохраняем и закрываем.
<article name="Zombieg" group="Mutants">
<texture>ui_npc_monster_zombieg</texture>
<text>enc_mutant_zombieg_general</text>
</article>
Копируем сюда же файл stable_statistic_caption.xml и изменяем в нем 3 строчки:
<string >
<text>зомбированный, гражданский</text>
</string>
<string >
<text>зомби-призрак, гражданский</text>
</string>
<string >
<text>зомби, гражданский</text>
</string>
Сохраняем и закрываем.
Вкратце, что описывает файл ui_npc_monster.xml: в нем задаются координаты иконок, расположенных в файле ui_npc_monster.dds, применительно к каждому типу монстров в игре.
Заключительный штрих. Откройте файл m_zombie.ltx и в первой секции замените строку
icon = ui_npc_monster_kontroler
На:
icon = ui_npc_monster_zombie
В секцию [zombie_ghost] добавьте строку:
icon = ui_npc_monster_zombieg
Сохраняйте изменения. Всё.
Вот готовые файлы примера. Удачи и спасибо за внимание :)
Эта часть статьи написана Arhet и создана на примере того, как в SRP Mod были созданы NPC группировки "Грех".
Начнем с character_desc_escape.xml. Описание что значит каждая строка писать не буду, так как все до меня уже сделано.
Тут создадим нового персонажа:
<specific_character team_default = "1">
<name>GENERATE_NAME_bandit</name>
<icon>ui_npc_dark_1</icon>
<map_icon x="0" y="0"></map_icon>
<bio>sim_stalker_novice_bio</bio>
<class>esc_dark_stalker_01</class> - вот тут наш новый класс кстати.
<community>dark_stalker</community> <terrain_sect>stalker_terrain</terrain_sect>
<money min="200" max="600" infinitive="0"></money>
Впишем наш код после какого-нибудь </specific_character>
Теперь идем в npc_profile.xml и туда вгоняем:
<character >
<class>esc_dark_stalker_01</class>
<specific_character>esc_dark_stalker_1</specific_character>
</character>
Теперь берем любой скрипт спавна NPC, вгоняем туда имя секции из spawn_sections.ltx и ву-а-ля.
Тока забыли что данному НПС будет присвоенная дефолтовая логика (т.е. тупо хожу куда сам не знаю) забыли упомянуть про (ххх - лока):
ххх gulag.script (действия НПС! Где можно: где можно присвоить статус кампера; волкера; и.д.т)
ххх gulag.ltx (дублер логики т.е. дублирует кратко действия НПС)
Статья создана:
xStream
OffBar
Fr3nzy
Imp
Arhet
Как изменить спавн гг в сталкер тч
[63]
; cse_abstract properties
section_name = actor
name = level_prefix_actor_0001
position = -246.726303100586,-24.7932605743408,-134.433868408203
direction = 0.00431653670966625,-1.39625442028046,-0.00068671052576974
s_flags = 0x29
; cse_alife_object properties
game_vertex_id = 4
distance = 0.699999988079071
level_vertex_id = 11713
object_flags = 0xffffffbf
custom_data = <<END
[dont_spawn_character_supplies]
[spawn]
wpn_binoc
device_torch
END
; 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 = 0x75732029
upd:creature_flags = 0x70
upd:position = -246.726303100586,-24.7932605743408,-134.433868408203
upd:o_model = 0
upd:o_torso = -1.39625442028046,0.00431653670966625,0
upd:g_team = 0
upd:g_squad = 0
upd:g_group = 0
; cse_alife_trader_abstract properties
money = 40
trader_flags = 0
character_profile = actor
upd:actor_state = 0xd20
upd:actor_accel_header = 0
upd:actor_accel_data = 0
upd:actor_velocity_header = 0
upd:actor_velocity_data = 0
upd:actor_radiation = 0
upd:actor_weapon = 110
upd:num_items = 0
Как изменить спавн гг в сталкер тч
*1
Для начала создадим профиль!
Откроем фаил character_****.xml
и создаем там новый профиль
Пример:
<specific_character team_default = "1">
<name>GENERATE_NAME_stalker</name>
<icon>иконка</icon>
<map_icon x="1" y="0"></map_icon>
<bio>Опытный сталкер. Детальная информация отсутствует.</bio>
<rank>цифры от 0 до 900</rank>
<reputation>цифры от 0 до 1000</reputation>
*2
Теперь нужно прописать класс нашего НПС в npc_profile.xml
Пример:
<character из character_****.xml">
<class>класс прописанный вами ранее</class>
<specific_character>название_секции из character_****.xml</specific_character>
</character>
*4
Потом открываем xr_conditions.script
и добавляем вот такую функцию
function is_sniper_enemy(enemy, object)
return enemy:id()
= db.actor:id()
end
PS:Если нет такого фаила ,то возьмите из оригинальной Игры!
*5
Теперь осталось Заспавнить Нашего НПСа
PS:Тем кто делает это впервые ,прочитайте дальше :),а если сталкивались ,всё равно читайте
function save_variable(variable_name, value)
xr_logic.pstor_store(db.actor, variable_name, value)
end
function load_variable(variable_name, value_if_not_found)
return xr_logic.pstor_retrieve(db.actor, variable_name, value_if_not_found)
end
*5.4
Когда вписали всех наших Снайперов и все функции спавна и внесли их в "список",то добавляем вызов нашей функции в bind_stalker.script
*6
Теперь работаем с логикой.
в папке configs/scripts создаём папку с sniper_addon , открываем её
*6.1
Создаём два фаила
sniper_addon_friend_logic.ltx и sniper_addon_enemy_logic.ltx
*6.2
открываем sniper_addon_friend_logic.ltx
и вписываем туда:
;SNIPER ADDON
;Меченый(Стрелок)
[logic]
active = remark@search
[remark@fire]
combat_ignore_cond =
radius = 0
anim = hide
on_info = remark@search
wounded = wounded@work
sniper = true
[remark@search]
combat_ignore_cond = true
combat_ignore_keep_when_attacked = false
anim = hide
target = actor
on_info = remark@fire
wounded = wounded@work
[smart_terrains]
none = true
[wounded@work]
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
Сохраняем этот фаил и открываем второй
и вставляем туда
;SNIPER ADDON
;Меченый(Стрелок)
[logic]
active = remark@search
[remark@fire]
combat_ignore_cond =
radius = 0
anim = hide
on_info = remark@search
wounded = wounded@work
sniper = true
[smart_terrains]
none = true
[remark@search]
combat_ignore_cond = true
combat_ignore_keep_when_attacked = false
anim = hide
target = actor
on_info = remark@fire
wounded = wounded@work
[wounded@work]
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
Как изменить спавн гг в сталкер тч
Автор программы: ADEnT_MOHOJIuTA
Возможности программы:
Сборка спавн-меню на ТЧ, Чн, ЗП, а также их модов. + Распаковка архивов *.dbx(Игровой формат архива).
Последние изменения:
1. Прикрутил конфиги к программе
2. Теперь спавнер хранится в ресурсах программы и после нажатия на кнопку "Собрать" в папке с программой появляется готовый спавнер.
3. Обновлен спавнер от naxac , теперь большие описания предметов можно прокручивать, также добавлены вкладки "Квестовое" и "Аддоны"
Меню можно включить и до загрузки игры (сохранения) - просто посмотреть предметы.
Читайте также: