Cпавн через скрипт, Cпавн через скрипт (xStream)

Материал из Mod Wiki.

(Различия между версиями)
Перейти к: навигация, поиск
Версия 15:55, 6 июля 2007 (править)
BAC9-FLCL (Обсуждение | вклад)

← К предыдущему изменению
Текущая версия (14:26, 24 июля 2007) (править) (отменить)
BAC9-FLCL (Обсуждение | вклад)
Cпавн через скрипт (xStream)» переименована в «Cпавн через скрипт»: Над статьей в равной мере работало несколько человек.)
 
Строка 1: Строка 1:
-==Скриптовый спавн==+#REDIRECT [[Cпавн через скрипт]]
- +
-В скриптах есть одна единственная функция, отвечающая за спавн объектов:+
-<pre>alife():create(section,position,levelvertex,gamevertex)</pre>+
- +
-Первый параметр - секция в конфигурациях, описывающая объект, например "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 в четвертом параметре+
-Например:+
-<pre>db.actor:game_vertex()</pre>+
- +
-Итак, чтобы, например, заспавнить болт под ногами актора, пишем: +
-<pre>alife():create("bolt",db.actor():position(),1,db.actor:game_verte())</pre>+
- +
-Почему 1, а не level_vertex? Проверено - разницы особой нет, какой level_vertex, а вот game_vertex решает все.+
- +
-Кроме того - есть еще один параметр - ID объекта, если указать ID NPC или актора - то предмет заспавнится у него в инвентаре.+
- +
-Пример (спавним артефакт Медуза в инвентаре у актора):+
-<pre>alife():create("af_medusa", db.actor():position(), 1, db.actor:game_vertex(), db.actor:id())</pre>+
- +
-Функция спавна возвращает серверный объект, то есть ни NPC, ни монстра ни что-либо еще.+
- +
-Просто минимальный набор - координаты, ID, секция,а из него (серверного объекта) обычно нужен только ID, так как по ID можно получить этот самый серверный объект:+
-<pre>(alife():object(id))</pre>+
- +
-Его можно использовать, чтобы поставить метку, например, но я его лично использую для других целей - спавн сложных объектов, конкретно – NPC.+
- +
-Например надо решить следующую задачу - надо создать наемника, сменить ему группировку и изменить его инвентарь, ну и в нагрузку - сделать другом для игрока.+
- +
-В определенный момент заспавненый объект переходит онлайн, в этот момент вызывается callback - net_spawn.+
- +
-Что мы делаем? Сверяем ID онлайн объекта с сохраненным ID!+
- +
-Если они совпадают, например так:+
-<pre>if obj:id()==saved_id then ...</pre>+
- +
-Важно то, что у серверного объекта ID - это параметр, а у онлайнового объекта ID получается с помощью функции. Это важно, а то можно прогореть.+
- +
-Итак, мы поймали нашего киллера по ID.+
- +
-Далее все очень просто - вызываем команды для спавна гаусса и патронов к нему в инвентаре NPC (см. выше), меняем группировку специальной функцией, и делаем его другом.+
- +
-Зачем такие сложности? Просто в оффлайне NPC как бы не существует, есть только косвенное упоминание о нем, и, плюс, все эти функции работают именно с объектом типа "NPC", а не с серверными объектами.+
- +
- +
-1. Чтобы не повторяться в описании создания нового квеста, просто изучите статью «Создание квестов» от Fr3nzy – лучшей статьи на эту тему я просто не видел :) Мы просто свяжем все воедино и научимся спавнить объекты из скрипта. +
- +
-Небольшое отступление: почему предпочтительнее делать спавн скриптом, а не через тот-же xSpawner? Программа xSpawner при всех своих достоинствах, обладает одним недостатком, а именно – она изменяет файл all.spawn и, установив очередной мод, затрагивающий данный файл, игру приходится начинать сначала, ИМХО, это ОЧЕНЬ НЕУДОБНО, не говорю уже о полной несовместимости таких модов. При спавне через скрипт ситуация иная, в подавляющем большинстве случаев, ранее сохраненные игры будут работать, что не может не радовать :)+
- +
-Итак, определимся с квестом. +
-Задача: после разговора с Сидоровичем спавним зомби на территории фабрики в первой локации. Для того, чтобы не повредить оригинальный сюжет игры, задание будет выдаваться ПОСЛЕ прохождения квеста с флешкой Шустрого, так как появись там зомби одновременно с бандитами и Шустрым…. я думаю, исход боя предрешен :)+
- +
-Реализация: Постараюсь описать все действия максимально подробно, буквально по шагам. Первым делом запустите игру :) В консоли введите команду +
- +
-<pre>rs_stats on или rs_stats 1 </pre>+
- +
-тем самым мы включаем вывод информации на экран. +
-Далее вводим еще одну команду +
-<pre>demo_record 1 </pre>+
-и «летим» на фабрику. Нам нужно выбрать место для спавна объектов и данный режим как нельзя лучше подходит для реализации задуманного. Помещаем камеру в точке предполагаемого спавна и записываем координаты - у меня получились 115, -6, -16. +
- +
-<pre>Для выхода из режима demo_record нажимаем Esc, в консоли пишем rs_stats off или rs_stats 0 (убираем вывод информации). </pre>+
- +
-Выходим из игры, идем в папку с установленной игрой и создаем каталог gamedata (предполагается, что «лепим» свой «мод» на «чистую» игру, без установленных модов, и имеем распакованные ресурсы игры в папке, скажем, gamedata_source).+
-В папке gamedata создаем папку config, а в ней - папку creatures. Скопируем из оригинальной папки файл m_zombie.ltx и откроем его на редактирование.+
- +
-Еще отступление:+
-В файлах игры присутствуют 5 моделей гражданских зомби, +
-<pre>файлы zombi_1.ogf, zombi_1_ghost.ogf, zombi_2.ogf, zombi_trup.ogf, zombi_trup_2.ogf. </pre>+
-Вернем в игру их всех :)+
- +
-Уже имеются секции +
-<pre>[zombie_weak]:m_zombie_e, [zombie_normal]:m_zombie_e, [zombie_strong]:m_zombie_e и [zombie_immortal]:zombie_strong. </pre>+
- +
-Два последних типа используют одну и ту же модель zombi_trup.ogf, хм… непорядок, исправляем. +
-Последняя секция выглядит теперь так:+
- +
-<pre>[zombie_immortal]:zombie_strong+
-$spawn = "monsters\zombies\zombie_immortal"+
-visual = monsters\zombi\zombi_trup_2+
-panic_threshold = 0.05 </pre>+
- +
-Добавим пятую модель. +
- +
-Для этого в конце файла создадим секцию:+
-<pre>[zombie_ghost]:zombie_strong</pre>+
- +
-Это означает, что наш пятый зомби наследует все параметры zombie_strong, мы добавим лишь визуальное представление.+
- +
-Пишем дальше:+
- +
-<pre>$spawn = "monsters\zombies\zombie_ghost"+
-visual = monsters\zombi\zombi_1_ghost</pre>+
- +
-Все. Сохраняем изменения и закрываем файл.+
- +
-2. Пишем скрипт спавна. В папке gamedata создаем новую папку scripts, в ней создаем новый текстовый документ и называем его esc_zombie.script. +
- +
-Отступление третье:+
-При написании статьи использовался оригинальный скрипт zombie_story.script из horror-mod’а. Концепция спавна перенесена практически без изменений, поэтому на авторство этого способа спавна я никоим образом не претендую :)+
- +
-Итак, открываем наш пустой файл на редактирование, первой строкой объявляем переменную, в которой хранятся наши зомби+
- +
-<pre>local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"}</pre>+
- +
-Далее пишем функцию+
- +
-<pre>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 </pre>+
- +
-И последнее+
- +
-<pre>function zomby_story_1( actor, npc )+
--- 10 зомби на фабрике (Кордон)+
- local spawn_point = vector():set( 115, -6, -16 ) -- здесь указываем координаты, выбранные нами для спавна, +
-когда «летали» камерой :)+
- spawn_zombies( spawn_point, 10 ) -- собственно вызов предыдущей функции с передачей ей координат и +
-количества объектов+
-end</pre>+
- +
-Все. Сохраняем и закрываем файл.+
- +
-Продолжаем разговор :) Для того, чтобы игра не вылетала после того, как мы добавили новый тип монстров, их нужно добавить в файл xr_statistic.script. Итак, скопируем этот файл из папки игры scripts в нашу папку к файлу esc_zombie.script и откроем на редактирование. +
- +
-Добавим в local killCountProps к монстрам строчку:+
-<pre> zombie_weak = 1, zombie_normal = 2, zombie_strong = 3</pre>+
- +
-В local sect_alias строчку:+
-<pre> zombie_weak = "zombie_weak", zombie_normal = "zombie_normal", zombie_strong = "zombie_strong"</pre>+
-А ниже в monster_classes строчку:+
-<pre> [clsid.zombie_s ] = "zombie"</pre>+
-В функцию getNpcType(npc) добавляем конструкцию:+
-<pre> elseif npc:character_community() == "zombie" then+
- community = "zombie"</pre>+
-Сохраняем изменения и закрываем файл.+
- +
-Все будет работать на ура, пока мы не попробуем обыскать убитого зомби. Как только мы это сделаем, игра вылетит с примерно такой ошибкой+
- +
-<pre>Expression : fatal error+
-Function : CInifile::r_string+
-File : D:\xray-svn\xrCore\Xr_ini.cpp+
-Line : 351+
-Description : <no expression>+
-Arguments : Can't find variable icon in [zombie_weak]</pre>+
- +
-Все верно – игра не знает какую иконку нам показывать для зомби. Иконки монстров хранятся в файле ui_npc_monster.dds. Здесь есть два варианта – а) если дружите с Фотошопом, отредактировать этот файл (нарисовать, добавить иконки); б) взять готовый из любого мода, естественно, с разрешения авторов мода. Сейчас мы пропустим данный аспект и присвоим нашим зомби иконки контролера :)+
- +
-Вернемся к файлу m_zombie.ltx и в секцию [m_zombie_e]:monster_base впишем параметр+
-<pre> icon = ui_npc_monster_kontroler</pre>+
- +
-Все. Вылетов не будет.+
- +
-3. Тема данной статьи не предусматривает подробного описания того, как сделать новый диалог. В начале статьи я упомянул источник, где можно найти исчерпывающую информацию по созданию диалогов, могу также привести в пример статью «Создание диалогов» от BAC9-FLCL+
-Нам нужно просто проверить работоспособность скриптового спавна, поэтому я приведу просто собственно сам измененный диалог из файла +
-dialogs_escape.xml+
- +
- <pre> <dialog id="escape_trader_talk_info">+
-………+
- <phrase id="999">+
- <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 id="9992">+
- <text>escape_trader_talk_info_9992</text>+
- <next>99922</next>+
- </phrase>+
- <phrase id="99922">+
- <text>escape_trader_talk_info_99922</text>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
- <phrase id="9993">+
- <text>escape_trader_talk_info_9993</text>+
- <next>99933</next>+
- </phrase>+
- <phrase id="9995">+
- <text>escape_trader_talk_info_9995</text>+
- </phrase>+
- <phrase id="3121">+
- <text>escape_trader_talk_info_3121</text>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
- <phrase id="3131">+
- <text>escape_trader_talk_info_3131</text>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
- <phrase id="41">+
- <text>escape_trader_talk_info_41</text>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
- <!------Наш диалог Начало------->+
- <phrase id="7770">+
- <text>escape_trader_talk_info_7770</text>+
- <next>7771</next>+
- </phrase>+
- <phrase id="7771">+
- <text>escape_trader_talk_info_7771</text>+
- <next>7772</next>+
- <next>7773</next>+
- </phrase>+
- <phrase id="7772">+
- <text>escape_trader_talk_info_7772</text>+
- <next>7777</next>+
- </phrase>+
- <phrase id="7773">+
- <text>escape_trader_talk_info_7773</text>+
- <next>7779</next>+
- </phrase>+
- <phrase id="7779">+
- <text>escape_trader_talk_info_7779</text>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
- <phrase id="7777">+
- <text>escape_trader_talk_info_7777</text>+
- <action>esc_zombie.zombie_story_1</action>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
- <!------Наш диалог Конец------->+
- <phrase id="51">+
- <text>escape_trader_talk_info_51</text>+
- <next>9996</next>+
- <next>9995</next>+
- </phrase>+
-……+
- </dialog></pre>+
- +
-И также связанный с ним файл stable_dialogs_escape.xml+
- +
-В самом начале файла пишем следующее+
- +
-<pre> <string id="escape_trader_talk_info_7770">+
- <text>Происшествий никаких не было?</text>+
- </string>+
- <string id="escape_trader_talk_info_7771">+
- <text>Да знаешь... Вроде как тихо все у нас. Хотя, вот, вспомнил! Говорили мне на днях, что на фабрике, ну, там, +
-где бандюки околачиваются постоянно, видели какиих-то то ли людей, то ли призраков... Мало ли что спьяну почудится - я и сказал +
-этим паникерам, мол, закусывать надо! Хех, блин, алкаши...</text>+
- </string>+
- <string id="escape_trader_talk_info_7772">+
- <text>Дык мне по любому мимо фабрики топать - заодно и посмотрю на этих "людей-призраков".</text>+
- </string>+
- <string id="escape_trader_talk_info_7773">+
- <text>Да я как-то не собирался в ту сторону...</text>+
- </string>+
- <string id="escape_trader_talk_info_7779">+
- <text>Ну, смотри сам, все равно будь осторожен.</text>+
- </string>+
- <string id="escape_trader_talk_info_7777">+
- <text>Ага. Сходи, проветрись. Потом зайдешь, расскажешь, что там и как.</text>+
- </string>+
- <string id="esc_bridge_soldiers_start_11">+
- <text>Здесь проход воспрещён, сталкер.</text>+
- </string></pre>+
- +
-Все. Можно запускать игру, идти на Кордон, после разговороа с Сидоровичем, в зависимости от выбранного Меченным решения, бежим на фабрику и … смотрим сами :)+
- +
- [http://data.cod.ru/1281523146 Готовые файлы примера]+
- [http://slil.ru/24600587 Spawn Lib]+
-Домашнее задание - вернуть в игру 6-ой тип гражданского зомби :)+
- +
-Продолжение следует…+
- +
- +
- +
-[[Категория:Статьи участников]]+

Текущая версия

  1. REDIRECT Cпавн через скрипт
Личные инструменты