Спавн через скрипт - створення модів - модифікації - s

У скриптах є одна єдина функція, що відповідає за спавн об'єктів:
alife (): create (section, position, levelvertex, gamevertex)

Перший параметр - секція в конфігураціях, що описує об'єкт, наприклад "bolt", "med_kit" - це прості секції, простих об'єктів а є об'єкти, які переходять в онлайн / оффлайн, це непісям, монстри і так далі, наприклад mil_killer_respawn_2 - спавна снайпер угруповання кілерів.







З позицією, думаю пояснювати не треба, тільки існує нюанс - висота це Y, а не Z. Задати позицію можна такою конструкцією vector (): set (x, y, z), де x, y і z - координати точки на рівні, де спавн об'єкт.

Далі складніше, так як сам толком сформулювати не можу.

Почнемо від простого до складного. На кожному рівні багато об'єктів, всі об'єкти складаються з полігонів, у кожного полігону є вершини - вертекси.

Саме вони і повинні тут бути вказано, навіщо - не особливо розумію, швидше за все для точного позиціонування об'єкта. Наприклад, можна отримати вертекс найближчий до актору - db.actor:level_vertex ()

Далі йде набагато цікавіший параметр game_vertex, це майже те ж саме, що і level_vertex, але (!) Це глобальні величини! Якщо level_vertex вважається для рівня, то game_vertex - для всієї гри, і потрібен він для того, щоб вказати на якій карті спавн об'єкт (більш зрозумілого пояснення я не знайшов).

Відповідно, щоб заспавніть що-небудь на іншій карті, досить вказати game_vertex в четвертому параметрі Наприклад:
db.actor:game_vertex ()

Отже, щоб, наприклад, заспавніть болт під ногами актора, пишемо:
alife (): create ( "bolt", db.actor (): position (), 1, db.actor: game_vertex ())

Чому 1, а не level_vertex? Перевірено - різниці особливої ​​немає, який level_vertex, хоча в деяких випадках треба прописувати валідний вертекс, а то предмет може просто заспавнітся не там, де планувалося. Але здебільшого все проходить нормально і з одиницею. (Ігнорування level_vertex може призводити до провалювання вироблених предметів / персонажів під землю.) А ось game_vertex вирішує все - він вказує на якому рівні спавн предмет, тому його треба вказувати. Теоретично можна просто знайти для кожного рівня по одному game_vertex'у і використовувати їх в скриптах. Насправді game_vertex показує який фрагмент карти використовується (вся карта розбита на шматки мають наскрізну нумерацію по всіх рівнях і game_vertex вибирає потрібний) соответсвенно неправильне використання черевато.

Крім того - є ще один параметр - ID об'єкта, якщо вказати ID NPC або актора - то предмет заспавнітся у нього в інвентарі.

Приклад (спавн артефакт Медуза в інвентарі у актора):
alife (): create ( "af_medusa", db.actor (): position (), 1, db.actor:game_vertex (), 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) - число патронів

Просто мінімальний набір - координати, ID, секція, а з нього (серверного об'єкта) зазвичай потрібен тільки ID, так як по ID можна отримати цей самий серверний об'єкт:
(Alife (): object (id))

Його можна використовувати, щоб поставити мітку, наприклад, але я його особисто використовую для інших цілей - спавн складних об'єктів, конкретно - NPC.

Наприклад треба вирішити наступне завдання - треба створити найманця, змінити йому угруповання і змінити його інвентар, ну і на додачу - зробити іншому для гравця.

У певний момент заспавнений об'єкт переходить онлайн, в цей момент викликається callback - net_spawn.

Що ми робимо? Звіряємо ID онлайн об'єкта зі збереженим ID!

Якщо вони збігаються, наприклад так:
if obj: id () == saved_id then.

Важливим є те, що у серверного об'єкта ID - це параметр, а у онлайнового об'єкта ID виходить за допомогою функції. Це важливо, а то можна прогоріти.

Отже, ми зловили нашого кілера по ID.

Далі все дуже просто - викликаємо команди для спавна Гаусса і патронів до нього в інвентарі NPC (див. Вище), міняємо угруповання спеціальний пристрій, який і робимо його другом.

Навіщо такі складнощі? Просто в офлайні NPC як би не існує, є тільки непряме згадка про нього, і, плюс, всі ці функції працюють саме з об'єктом типу "NPC", а не з серверними об'єктами.
Практика (частина 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 (прибираємо висновок інформації).

Інший спосіб отримання тих же відомостей - прийти в потрібне місце і запустити там скрипт, який видасть всі необхідні координати. Я користуюся наступним скриптом (викликаю загальновідомим способом, через main_menu):
function main_menu: main_cheat_f3 ()






-- Віддам повідомлення про наше місце розташування
local text
local vid
local gvid
local a = vector () - Тип змінної
local text

Додамо п'яту модель.

Для цього в кінці файлу створимо секцію:
[Zombie_ghost]: zombie_strong

Це означає, що наш п'ятий зомбі успадковує всі параметри zombie_strong, ми додамо лише візуальне уявлення.

Пишемо далі:
$ Spawn = "monsters \ zombies \ zombie_ghost"
visual = monsters \ zombi \ zombi_1_ghost

Усе. Зберігаємо зміни і закриваємо файл.

2. Пишемо скрипт спавна. В папці gamedata створюємо нову папку scripts, в ній створюємо новий текстовий документ і називаємо його esc_zombie.script.

Отже, відкриваємо наш порожній файл на редагування, першим рядком оголошуємо змінну, в якій зберігаються наші зомбі:
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_str 3

У local sect_alias рядок:
zombie_weak = "zombie_weak", zombie_normal = "zombie_normal", zombie_str "zombie_strong"

А нижче в monster_classes рядок:
[Clsid.zombie_s] = "zombie"

У функцію getNpcType (npc) додаємо конструкцію:
elseif npc: character_community () == "zombie" then
community = "zombie"

Зберігаємо зміни і закриваємо файл.

Все буде працювати на ура, поки ми не спробуємо обшукати вбитого зомбі. Як тільки ми це зробимо, гра вилетить з приблизно такою помилкою.
Expression. fatal error
Function. CInifile :: r_string
File. D: \ xray-svn \ xrCore \ Xr_ini.cpp
Line. 351
Description:
Arguments. Can not find variable icon in [zombie_weak]

Повернемося до файлу m_zombie.ltx і в секцію [m_zombie_e]: monster_base впишемо параметр
icon = ui_npc_monster_kontroler

Усе. Вильотів не буде.

3. Тема даної статті не передбачає докладного опису того, як зробити новий діалог. На початку статті я згадав джерело, де можна знайти вичерпну інформацію по створенню діалогів, можу також привести в приклад статтю зі створення діалогів від BAC9-FLCL.

Нам потрібно просто перевірити працездатність скриптового спавна, тому я приведу просто власне сам змінений діалог з файлу dialogs_escape.xml:

escape_trader_talk_info_999
7770
9991
9992
9993
9994
9995
9996


escape_trader_talk_info_99922
9996
9995


escape_trader_talk_info_3121
9996
9995


escape_trader_talk_info_3131
9996
9995


escape_trader_talk_info_41
9996
9995


escape_trader_talk_info_7779
9996
9995


escape_trader_talk_info_7777
esc_zombie.zombie_story_1
9996
9995

escape_trader_talk_info_51
9996
9995


І також пов'язаний з ним файл stable_dialogs_escape.xml. На самому початку файлу пишемо наступне:

Подій ніяких не було?


Та чи знаєш. Ніби як тихо все у нас. Хоча, ось, згадав! говорили мені
на днях, що на фабриці, ну, там, де бандюки тиняються постійно, бачили какііх чи то
людей, то чи привидів. Хіба мало що сп'яну почудится - я і сказав цим панікерам, мовляв,
закушувати треба! Хех, блін, алкаші.


Дик мені з будь-якого повз фабрику топати - заодно і подивлюся на цих
"Людей-привидів".


Так я якось не збирався в ту сторону.


Ну, дивись сам, все одно будь обережний.


Ага. Сходи, провітрити. Потім зайдеш, розкажеш, що там і як.


Тут прохід заборонено, сталкер.


Усе. Можна запускати гру, йти на Кордон, після разговороа з Сидоровичем, в залежності від обраного Міченим рішення, біжимо на фабрику і ... дивимося самі :)
Готові файли прикладу
Spawn Lib

Домашнє завдання - повернути в гру 6-ий тип громадянського зомбі :)

Далі буде…
Практика (частина 2)

Файл моделі до редагування

Файл моделі після редагування

5. Тепер пропишемо нашого нового зомбі в усі файли, які ми створили раніше. У файл m_zombie.ltx в самий кінець додаємо секцію:
[Zombie_old]: zombie_normal
$ Spawn = "monsters \ zombies \ zombie_old"
visual = monsters \ zombi \ zombi_3

в файлі 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)

Усе. Зберігаємо і закриваємо.

6. Копіюємо в папку gamedata \ config \ gameplay \ файл encyclopedia_mutants.xml, додаємо опис зомбі в енциклопедію:


І в пов'язаний з ним файл string_table_enc_mutants.xml в папці gamedata \ config \ text \ rus \ додаємо:


Зомбі-привид відрізняється від звичайного зомбі лише тим, що
вплив Вижигатели мізків повністю зруйнувало не тільки структуру особистості, а й
тіло, тому зомбі-привид трохи більш живучий в порівнянні зі звичайним зомбі.


Вплив Вижигатели мізків повністю руйнує структуру особистості,
залишаючи тільки тілесну оболонку. \ n \ n Побродивши трохи по Зоні, позбавлені розуму тіла
починають перетворюватися в справжніх зомбі. З рефлексів у них залишаються лише найпримітивніші,
зброя військово-промислового комплексу скоро приходять в непридатність. В результаті зомбі стають собою ні чим
іншим, як повільними напівтрупами, яких наявні лише два ефективних подразника:
їжа і сон. Зомбі абсолютно нерозбірливі у виборі їжі і пиття, тому їх тіла буквально
просякнуті радіацією і токсинами. Як правило, ці істоти безцільно бродять по Зоні або,
немов трупи, валяються всередині занедбаних будівель. Однак, як тільки зомбі почує близьке
присутність живої людини, він відразу ж намагається атакувати. Навчені досвідом сталкери
намагаються обходити ці незграбні спустошені оболонки.


Копіюємо сюди ж файл stable_statistic_caption.xml і змінюємо в ньому 3 рядки:


Зберігаємо і закриваємо.

7. І останнє - додамо іконки. Скажу відразу, скористався готовим файлом, вже містить іконки зомбі і інших «відновлених монстрів» (спасибі Fr3nzy). Тому просто скопіюйте файл ui_npc_monster.dds з архіву в папку gamedata \ textures \ ui \, а файл ui_npc_monster.xml - в папку gamedata \ config \ ui \. Якщо ви хочете зробити власні - прочитайте урок зі зміни текстур.

Якщо коротко, що описує файл 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

Зберігайте зміни. Усе.

Ось готові файли прикладу. Успіху і спасибі за увагу :)
спавн NPC

Ця частина статті написана Arhet і створена на прикладі того, як в SRP Mod були створені NPC угруповання "Гріх".

Задіємо файли:
gamedata \ config \ gameplay \ character_desc_escape.xml
gamedata \ config \ gameplay \ npc_profile.ltx
gamedata \ config \ creatures \ spawn_sections.ltx

Почнемо з character_desc_escape.xml. Опис що означає кожен рядок писати не буду, так як все до мене вже зроблено.

Тут створимо нового персонажа:

esc_dark_stalker_01 - ось тут наш новий клас до речі.
dark_stalker stalker_terrain

actors \ dark_stalker \ dark_stalker_1
characters_voice \ human_01 \ monolith \
-1
0

[Spawn] \ n
wpn_dark_colt1911 \ n
ammo_11.43x23_hydro \ n
#include "gameplay \ character_items.xml" \ n
#include "gameplay \ character_drugs.xml" \ n
#include "gameplay \ character_food.xml"


Впишемо наш код після якогось

Тепер йдемо в npc_profile.xml і туди вганяємо:

Тепер беремо будь-який скрипт спавна NPC, вганяємо туди ім'я секції з spawn_sections.ltx і ву-а-ля.

Тока забули що даним НПС буде привласнена дефолтовая логіка (тобто тупо ходжу куди сам не знаю) забули згадати про (ххх - лока):

ххх gulag.script (дії НПС! Де можна: де можна привласнити статус Кампера; Волкера; і.д.т)

ххх gulag.ltx (дублер логіки тобто дублює коротко дії НПС)