Итак, как и обещал, привожу пример ПРОСТЕЙШЕГО спавна монстров через скрипт. Прежде всего перелестните эту страницу форума на страничку с номером 1. Там подробно написано о том как узнать координаты и вертексы (level_vertex, game_vertex_id) с помощью скрипта, который необходимо прописать в файле ui_main_menu.script (если уж кто вобще чайник, то script это расширение)
по адрессу STALKER/gamedata/scripts. Дальнейший материал взят с портала http://sdk.stalker-game.com/ru/index.php/C%D0%BF%D0%B0%D0%B2%D0%BD_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82. Прежде всего читаем первую часть Теории с вышеуказанного портала (без неё никак!), а с практикой я помогу. Заходим в игру, узнаём кординаты и вертексы. (Весь двльнейший текст одна сплошная цитата) Далее в папке gamedata создаем папку config, а в ней - папку creatures. Скопируем из оригинальной папки файл m_zombie.ltx и откроем его на редактирование. (Я же просто редактирую оригиналы извлечённых файлов, предварительно поместив их backup версии (копии) в отдельную папку).
В файлах игры присутствуют 5 моделей гражданских зомби:
файлы zombi_1.ogf, zombi_1_ghost.ogf, zombi_2.ogf, zombi_trup.ogf, zombi_trup_2.ogf Вернем в игру их всех :)
Уже имеются секции:
[zombie_weak]:m_zombie_e, [zombie_normal]:m_zombie_e, [zombie_strong]:m_zombie_e и [zombie_immortal]:zombie_strong. Два последних типа используют одну и ту же модель zombi_trup.ogf, хм... непорядок, исправляем. Последняя секция выглядит теперь так:
[zombie_immortal]:zombie_strong
$spawn = "monsters\zombies\zombie_immortal"
visual = monsters\zombi\zombi_trup_2
panic_threshold = 0.05 Добавим пятую модель.
Для этого в конце файла создадим секцию:
[zombie_ghost]:zombie_strong Это означает, что наш пятый зомби наследует все параметры zombie_strong, мы добавим лишь визуальное представление.
Пишем дальше:
$spawn = "monsters\zombies\zombie_ghost"
visual = monsters\zombi\zombi_1_ghost
Все. Сохраняем изменения и закрываем файл. Пишем скрипт спавна. В папке gamedata создаем новую папку scripts, в ней создаем новый текстовый документ и называем его esc_zombie.script. ( В строке тип файла ставим галочку на пункт "all files", а после названия ставим точку и прописываем "script". Всё, сохранили, как файл с расширеним "script") Отступление третье:
При написании статьи использовался оригинальный скрипт zombie_story.script из horror-mod’а. Концепция спавна перенесена практически без изменений, поэтому на авторство этого способа спавна я никоим образом не претендую :) (Я же вял эти материалы с вышеупомянутого источника и тоже ни коим образом не претендую на авторство.)
Итак, открываем наш пустой файл на редактирование, первой строкой объявляем переменную, в которой хранятся наши зомби:
local zombie_types = (Пишем всё в одну строку, просто здесь не поместилось.) {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"} Далее пишем функцию:
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 zombie_story_1( actor, npc )
-- десять зомби на фабрике (Кордон)
local spawn_point = vector():set( 115, -6, -16 ) -- здесь указываем координаты,
выбранные нами для спавна, когда «летали» камерой :)
spawn_zombies( spawn_point, 10 ) -- собственно вызов предыдущей функции
с передачей ей координат и количества объектов
end
Все. Сохраняем и закрываем файл.
(Так, здесь поподробнее, очено важный аспект. С первой строкой, я полагаю, всё понятно - перечисление типов зомби. Следующая строка - function spawn_zombies - говорит о том, что это функция (людям, не знакомым с программированием это слово ничего не скажет), и что называется она spawn_zombies (дословный перевод строки: функция "рождение зомби"). position, total - я так полагаю, составляющие функции - позиция и количество циклов, судя по комментариям, или что-то такое, ну, в общем не важно. Следующая строка ясна, я надеюсь (следите за комментами напротив строки). Следующая строка нам не нужна, а следующая за ней (for zombie_index=1, total do) может пригодиться, но я с ней особо не разбирался, так что полистайте, если хотите предыдущие страницы, там кажись чёт было по этому тэгу (грубо говоря). Следующие две строки я не совсем понял, впрочем как и ещё три, следующие за ними, если кто знает поясните, хотя в принципе они нам и не нужны. Так, двигаемся дальше.
alife():create(zombie_types[math.rando(5)],new_pos,db.actor:level_vertex_id(),db.actor:game_vertex_id()) - как следует из комментов, сама функция спауна зомби (Кстати, тоже пишется на одной строке). Дальше разбираем её составляющие. На пером месте за открывающей скобкой, как мы узнали из раздела "Теория" на вышеуказанном портале, должен следовать объект спауна. Ага, кажись понял - [math.rando(5)] - это случайное переменное из перечисленных нами зомби, короче функция (или скрипт, чёрт их разберёт)
случайно выбирает один из перечисленных нами типов зомби для спауна. Далее new_pos - позиция, местоположение, но какое- то "скользское", короче оставляем как есть. db.actor:level_vertex - уже знакомая нам из теории миниконструкция, но всё равно поясню - если всё оставить как есть, то будет браться ближайший к актёру level_vertex. Если хотите заспаунить монстра в другом месте, то меняем всё это на цифры, к примеру:329582. С db.actor:game_vertex_id() всё обстоит точно так же.
Переходим к функции function zombie_story_1
local spawn_point = vector():set( 115, -6, -16 ) - местоположение спауна монстров. В скобках координаты, точно как на уроке математики (10 минут вспоминал, как пишется слово)
, по порядку - X, Y, Z, где Y - высота. spawn_zombies( spawn_point, 10 ) - как я понял, итог, команда выполнения всех прописанных нами условий или что мы там писали
При этом, 10 - это количество монстров, которых необходимо заспаунить.)
Пример готового скелета скрипта:
local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"}
function spawn_zombies( position, total )
local zombie_index
local new_pos, x_offset, z_offset
for zombie_index=1, total do
x_offset = math.random(5)
z_offset = math.random(5)
new_pos = position
new_pos.x = new_pos.x + x_offset
new_pos.z = new_pos.z + z_offset
alife():create(zombie_types[math.random(5)],new_pos,326087,91)
end
end
function zombie_story_1(actor, npc)
local spawn_point = vector():set(43.21, 2.14, 47.16)
spawn_zombies(spawn_point, 10)
end
(Два пояснения: первые две строчки пишутся на одной строке - local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"} - эти имеются в виду. И ещё, по идее скрипт работоспособен, но я, насколько помню, тестил с целыми числами в графе координат. Мы молодцы, потсроили скрипт, но это ещё не всё. Дальше опять сплошная цитата.)
Для того, чтобы игра не вылетала после того, как мы добавили новый тип монстров, их нужно добавить в файл 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"
Сохраняем изменения и закрываем файл.
(Очень важное пояснение - обязательно проставьте запятые в этих файлах после вставки!Обязательно следите за запятыми! Если вы этого не сделаете, то игра начнёт виснуть при запуске. Я вначале не обратил внимания на них, и поэтому при запуске новой игры, первым и последним, что я видел был оскал Сидоровича, который могла стереть только волшебная кнопочка на системнике!
И наконец, последняя стадия - в файле по адрессу STALKER/gamedata/config/gameplay/dialogs_escape найдите строки:
<phrase id="11111111">
<text>escape_lager_volk_talk_11111111</text>
<next>111111111</next>
<next>111111112</next>
и поменяйте на
<phrase id="11111111">
<text>escape_lager_volk_talk_11111111</text>
<action>esc_zombie.zombie_story_1</action>
<next>111111111</next>
<next>111111112</next>
Сохраняем и всё. Вы в первый раз говорите с волком на Кордоне, соглашаетесь спасти сталкеров на фабрике, выходите на дорогу, доходите до остановки и встречаете 10 неубиваемых зомби. Только не пытайтесь их обыскать - игра вылетит. Если хотите, почитайте там же где и всегда, как избавиться и от этого, а также статью, посвящённую созданию диалогов (на вышеуказанном портале). Но будете осторожны - многие примеры не работают на том портале (в том числе из-за орфографических ошибок), поэтому прежде чем тупо копировать код скрипта, просмотрите его, авось и вы найдёте баг. Так, пока вроде всё. Ещё раз повторяю - это пример простейшего спауна, рассчитанный на новичков. Бывалым скриптёрам это объяснение возможно покажется комичным, но более понятно, я думаю, не объяснить. Итак, база заложена. Научусь чему нибудь ещё - обязательно выложу (это что касательно скриптового спауна).
P.S.:э-эх, до полуночи не уложился. Надеюсь смайлики развеселили смотрящих эту страницу, потому как я готов рвать и метать от злости, потому что когда я уже почти закончил, браузер выдал ошибку и закрыл окно, а у меня была сохранена только половина текста.