Как изменить визуал НПС? Для начала скачиваем сам визуал, все готовы тогда начнем.
Сперва перекинем визуал в папку с игрой: gamedata\meshes\actors. Там открываем папку для примера stalker_bandit (у каждого своя папка). Все пол дела сделано.
Переходим по пути: gamedata\configs\gameplay там открываем character_desc_zaton (взял для примера).
Находим НПС которому хотим поменять визуал, нашли молодцы. Теперь в строке <visual>actors\stalker_bandit\stalker_bandit_3_face_1</visual> вместо stalker_bandit_3_face_1 прописываем название визуалки.
Вот и все сохраняем, начинаем новую игру и вуаля НПС изменил визуал.
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
Дата: Воскресенье, 12.07.2015, 23:16 | Сообщение # 3
Агро-Разработчик
[ Легенда Зоны ]
КВАДЫ СТАЛКЕРОВ
Или как сделать, чтобы сталкеры ходили поодиночке и все разговаривали - сделать всех лидерами.
Итак, данный урок поможет вам сделать так, чтобы сталкеры и монстры гуляли по одному(это касается обычных, не квестовых нпс, т.е тех, которые спавнятся по алайфу.)
1) В файле : gamedata/configs/miscs/quad_descr.ltx покоятся описания квадов, вам нужны исключительно эти строки, в каждой секции сквада. Сталкеры: npc_in_squad = 1, 1 (количество нпс в скваде)
как видите , было 2, 3 , ставте 1, 1 и будут у вас сталкеры одиночки.
Мутанты: Далее, если хотите увеличить популяцию монстров, в логику смартов лучше не лезть, а сразу записывать здесь 4, 6 и.т.
Две цифры 2, 3 означают минимум, максимум, поэтому сначала ставите меньшее, за ним большее.
НО не ставте только одну цифру, и 0, 0 я еще не проверил .
Так же можно изменить иконку отображения командира на карте на обычную точку, и вуаля ТЧ, одиночки и все говорят. Но это не касается квестовых, а тех лучше не трогать.
Нужна новая игра.! Иначе сквады по 2.3 человека никуда не денутся.
Убираем точки лидеров.
1) В файле:gamedata/configs/ui/map_spots.xml (map_spots_16.xml - широкий моник)
PS. А у врагов можно не править, командиров у них все равно нет, они берутся из другого конфига. Вот , теперь все одинакового цвета и рамера. Советую использовать вместе с правкой по квадам. Будет Зона одиночек!
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
Файлы имён НПС (респавнищихся) генерация из двух файлов . Имя и Прозвище: st_generate_fnames.xml st_generate_snames.xml
1)Редактируемst_characters.xml
Валет
Что выделено жирным - не трогаем, это конструкция транслита системных названий в перевод. Зелёным - это системное имя НПС (указывается в файле профиле как имя) Жёлтым -правим текст, это то мы и ищем. (Если НПС уже заспавнена, то правка имени ни на что не повлияет!!! Т.Е. Нужна новая игра.)
2)Правим диалоги:
Подскажи мне насчёт одного дела...
Что выделено жирным - не трогаем, это конструкция транслита системных названий в перевод. Зелёным- это системное имя диалога (указывается в фскелете диалогов) Жёлтым -правим текст, это то мы и ищем.
3)Прозвища: Для респавнищихся НПС. Из файла st_generate_fnames.xml берётся рандомное Имя, из файла st_generate_snames.xml берётся рандомное Прозвище. В итоге получается Имя Прозвище.
Если вылетает ссылаясь на правленный файл - значит удалили закрывающий тег (там точка, скобка, стрелка, лишние кавычки) Да и не вздумайте ставить " "..." " вот так, это не правльно, так нельзя. Используйте другие кавычки в виде стрелок.
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
Дата: Воскресенье, 12.07.2015, 23:30 | Сообщение # 5
Агро-Разработчик
[ Легенда Зоны ]
Редактируем acdc_cop.pl
Допустим вы хотите собрать all.spawn но вы понаделали там разных секций, которые в оригинальном acdc_cop.pl нет. И при компиляции он валится. Для этого открываем acdc_cop.pl где-то на строке 2100 , вы увидите подобные вещи....
Т.е допустим вы добавили профиль burer_weak и хотите заспавнить бюрера с таким профилем (т.е по профилю), но при компиляции будет обвал.... поэтому каждый новый профиль нужно дописывать в свой acdc_cop.pl.
Занесение данных при подключении новых локаций в acdc_cop.pl
С помощью ggtool.pl (Там надо раскоментировать строку $gg->show_level_gvids()) section4.bin) Выбьет список геймвертексов. Запоминаешь для своего уровня.
Открываем acdc_cop.pl Там дописываешь себе по типу:
Код
use constant levels_info => ( { gvid0 =>yyyy, }, -- yyy - xxx + количество геймвертексов локи ( { gvid0 => xxx, name => 'твоя_лока' }, -- где xxx - цифра, которую нашел с помощью [b]ggtool.pl[/b] ... { gvid0 => nnn , name => 'zaton' }, );
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
1. Распаковщик ресурсов. 2. Блокнот, notepad ++. Я работаю с нотепадом т. к. у него есть подсветка синтаксиса. 3. Прямые руки. Кривые не подойдут. 4. Светлая голова. 5. Терпение.
Методом проб и ошибок научился выводить сообщения на экран, сейчас распишу как:
Для вывода сообщения на экран нужен любой исполняемый файл, к примеру возьмем файл gamedata/scripts/ui_main_menu.script - все файлы *.script написаны на языке LUA.
Итак приступим:
Находим в файле вот это:
Код
function main_menu:OnKeyboard(dik, keyboard_action) --virtual function CUIScriptWnd.OnKeyboard(self,dik,keyboard_action) local bind = dik_to_bind(dik) local console = get_console()
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then if dik == DIK_keys.DIK_ESCAPE then if level.present() and ( ((db.actor ~= nil)and(db.actor:alive())) or (false==IsGameTypeSingle()) ) then self.OnButton_return_game() --' xStream 02.2008 -- console:execute("main_menu off") --' xStream 02.2008 end end
-- if dik == DIK_keys.DIK_S then -- self:OnButton_load_spawn()
-- else if dik == DIK_keys.DIK_Q then self:OnMessageQuitWin() end
end
return true end
И вставляем вот это:
Код
elseif dik == DIK_keys.DIK_F1 then self:sms()
Под это:
Код
if dik == DIK_keys.DIK_Q then self:OnMessageQuitWin()
Должно получится вот так:
Код
function main_menu:OnKeyboard(dik, keyboard_action) --virtual function CUIScriptWnd.OnKeyboard(self,dik,keyboard_action) local bind = dik_to_bind(dik) local console = get_console()
if keyboard_action == ui_events.WINDOW_KEY_PRESSED then if dik == DIK_keys.DIK_ESCAPE then if level.present() and ( ((db.actor ~= nil)and(db.actor:alive())) or (false==IsGameTypeSingle()) ) then self.OnButton_return_game() --' xStream 02.2008 -- console:execute("main_menu off") --' xStream 02.2008 end end
-- if dik == DIK_keys.DIK_S then -- self:OnButton_load_spawn()
-- else if dik == DIK_keys.DIK_Q then self:OnMessageQuitWin()
elseif dik == DIK_keys.DIK_F1 then self:sms() end
end
return true end
Далее пишем в самый конец файла:
Код
function main_menu:sms() sms.sms() end
Сохраняем и помещаем файл в gamedata/scripts
Теперь создадим файл sms.txt и переименуем его в sms.script
Откроем и впишем в него:
Код
function sms() local text local a = vector() local text a = db.actor:position() text = "%c[239,255,6,13]Свободу тушканчикам!\nТушканчики всех стран объединяйтесь!" news_manager.send_tip(db.actor, text, nil, nil, 30000) end
Сохраняем и помещаем файл в gamedatascripts
Поясняю строчки:
text = "%c[239,255,6,13]Свободу тушканчикам!\nТушканчики всех стран объединяйтесь!" news_manager.send_tip(db.actor, text, nil, nil, 30000)
%c[239,255,6,13] - цвет шрифта
Свободу тушканчикам! - сообщение
\n - перенос сообщения на другую строчку
30000 - время показа сообщения в милисекундах
Теперь заходим в игру, начинаем новую игру после того как игра загрузилась выходим в главное меню ESC жмём F1 возвращаемся в игру и видим своё сообщение, таким образам можно вызвать сообщение хоть от куска колбасы.
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
Результат - вылет с ссылкой на ошибку в логике. Поковыряв, я обнаружил отсутствие файла sr_sound.script. Я добавил его, запустил игру и получил тот же самый вылет с тем же контекстом. Значит надо этот файл зарегистрировать. Лезем в modules.script. Внутри скрипта ищем:
Всё зарегистрировали. Теперь снова загружаем нашу игру и, добежав до нашего space_restrictor-а, ловим вылет:
Код
Expression : !m_error_code Function : raii_guard::~raii_guard File : D:\prog_repository\sources\trunk\xrServerEntities\script_storage.cpp Line : 748 Description : ....e.r. - Зов Припяти\gamedata\scripts\sr_sound.script:201: attempt to call field 'get_safe_sound_object' (a nil value)
Залез в sr_sound.script на 201 строку я обнаружил, что get_safe_sound_object - это функция xr_sound.script
В xr_sound.script я наткнулся на отсутствие get_safe_sound_object, а sr_sound.script я брал из ТЧ, куда и лезем за помощью в xr_sound.script, где данная функция есть. После нехитрых рассуждения я скомуниздил из тч-льского файла xr_sound.script следующий код:
Код
--' Соунд обжект
--' Таблица для хранения созданных саунд обжектов. sound_object_by_theme = {} --' type = [random|seq|looped] function get_sound_object(theme, t_type) if sound_theme.ph_snd_themes[theme] == nil then abort("ph_snd_themes for theme %s", tostring(theme)) return end
if sound_object_by_theme[theme] == nil then sound_object_by_theme[theme] = {} end
if t_type == nil then t_type = "random" end
--' Выбор следующего айдишника local play_id = -1 local table_size = table.getn(sound_theme.ph_snd_themes[theme]) if sound_object_by_theme[theme].last_id == nil then if t_type == "random" then if table_size >= 2 then play_id = math.random(1, table_size) else play_id = 1 end else play_id = 1 end else if t_type == "random" then if table_size >= 2 then play_id = math.random(1, table_size - 1) if play_id >= sound_object_by_theme[theme].last_id then play_id = play_id + 1 end else play_id = 1 end else if sound_object_by_theme[theme].last_id < table_size then play_id = sound_object_by_theme[theme].last_id + 1 else if type == "looped" then play_id = 1 end end end end
printf("SOUND_OBJECT: selected id [%s] for theme [%s], type [%s], size [%s]", tostring(play_id), tostring(theme), tostring(type), table_size)
if play_id == -1 then return end --' Проверяем создан ли у нас соответствующий саунд обжект или его надо создать if sound_object_by_theme[theme][play_id] == nil then if type(sound_theme.ph_snd_themes[theme][play_id]) == "table" then sound_object_by_theme[theme][play_id.."_r"] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id][1].."_r") sound_object_by_theme[theme][play_id.."_l"] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id][1].."_l") else sound_object_by_theme[theme][play_id] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id]) end end
sound_object_by_theme[theme].last_id = play_id
--' Возвращаем саунд обжект if type(sound_theme.ph_snd_themes[theme][play_id]) == "table" then return sound_object_by_theme[theme][play_id.."_r"], sound_object_by_theme[theme][play_id.."_l"] else return sound_object_by_theme[theme][play_id] end end
local sound_object_by_path = {} --' Обертка вокруг функции, возвращающий звуковой объект. function get_safe_sound_object(path) if sound_object_by_path[path] == nil then sound_object_by_path[path] = sound_object(path) end return sound_object_by_path[path] end
function stop_all_sound_object() for k,v in pairs(sound_object_by_path) do if v:playing() then v:stop() end end end function clear_all_sound_object() sound_object_by_theme = {} end
Добавив его в файл xr_sound.script уже ЗП и запустив игру я обнаружил, что моя логика заработала!!!
P.S. Делал данную рокировку я на ЗП на добавленном мною кордоне из ТЧ, откуда я и брал дополнительные скрипты.
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
function use_snd(obj) local obj_sect = obj:section() local snd if obj_sect == 'ваш предмет' then snd = [[Путь_до_звука_относительно_папки_sounds]] elseif obj_sect == 'ваш предмет' then snd = [[Путь_до_звука_относительно_папки_sounds]] elseif obj_sect == 'ваш предмет' then snd = [[Путь_до_звука_относительно_папки_sounds]] elseif obj_sect == 'ваш предмет' then snd = [[Путь_до_звука_относительно_папки_sounds]] end if snd then local snd_obj = xr_sound.get_safe_sound_object(snd) snd_obj:play_no_feedback(db.actor, sound_object.s2d, 0, vector(), 1.0) end end
Сохраняем. Открываем bind_stalker.script и в функцию function actor_binder:net_destroy() пишем:
Как лечить раненных НПС-врагов Сложность:оч. легко Совместимость с модами:легко совместимо Многие люди в своих модификациях хотят добавить возможность лечить раненных врагов, как, например, в Солянке. Я тоже однажды заинтересовался этим вопросом и, не найдя на него ответа в интернете, занялся решением проблемы сам. В итоге мне это удалось и теперь выкладываю плоды своих стараний на просторы интернета .
Запрет диалога с раненными противниками находится в файле xr_wounded.script, и выглядит так (я снабдил его комментариями, если вы не сильно шарите в скриптах):
Код
if self.object:relation(db.actor) == game_object.enemy then --если отношение НПС к ГГ = отношению к врагум self.object:disable_talk() --блокировать диалоги else --иначе self.object:enable_talk() --разрешить диалог end --конец условия (if)
Дабы позволить ГГ говорить с врагами (только раненными) достаточно удалить лишнее и оставить всего одну строку:
Код
self.object:enable_talk()
Но! Если ГГ попробует обратиться к раненным представителям бандитов, монолитовцев, наёмников, зомби (возможно), военных или противников на Арене - скорее всего произойдёт Фатал Еррор с логом на отсутствие подходящей фразы для диалога (в оригинальной игре с вероятностью 99%). Так вот, лично для себя я нашёл простое решение, которое подходило и по концепции моего мода - запретить диалог с данными группировками. Вот таким макаром:
Код
local comm = self.object:character_community() --переменной обозначил "понятие" группировки обьекта (НПС) if comm == "zombied" or --если НПС - зомби, или comm == "bandit" or --НПС - бандит, или comm == "monolith" or --НПС - монолитовец, или comm == "arena_enemy" or --НПС - боец арены, или comm == "killer" or --НПС - наёмник, или comm == "military" then --НПС - вояка, тогда self.object:disable_talk() --запретить диалог else -- иначе self.object:enable_talk() --разрешить диалог end -- The End!
просто заменить изначальные строки этими и теперь ГГ сможет лечить врагов одиночек, долговцев, свободовцев и учёных. Но есть ещё один момент. При лечении врагов, если всё сделать как было написано будет ещё одна проблемка - они так и останутся врагами после лечения и будут дальше атаковать ГГ. Разумно было бы сделать НПС если не другом, то по крайней мере нейтралом. Для этого необходимо в файле dialogs.script кусок скрипта
Код
if second_speaker:relation(first_speaker) ~= game_object.enemy then second_speaker:set_relation(game_object.friend, first_speaker) end first_speaker:change_character_reputation(10); end
заменить на
Код
if second_speaker:relation(first_speaker) == game_object.enemy then second_speaker:set_relation(game_object.friend, first_speaker) first_speaker:set_relation(game_object.friend, second_speaker) end first_speaker:change_character_reputation(10); end
Всё!
Да и уже готовый файл xr_wounded.script и dialogs.script со всеми описанными правками прилагается Посмотреть.
Как сделать костюм с системой автолечения (изначально для ТЧ) Сложность:легко Совместимость с модами:придётся поработать Подобную схему делал для своего мода, теперь выкладываю здесь ее аналог, мало мальски продуманный для оригинального ТЧ:
Принцип работы Функция (скрипт), указанная в бинд_сталкер.скрипт (кто не знает что это - загуглите :)) выполняется движком несколько раз в секунду. Задача функции - проверять одет ли на ГГ нужный костюм, сколько у ГГ здоровья и если здоровья мало - использовать медикаменты (если у ГГ они есть, разумеется). Вот и всё! Порядок работы (для оригинального ТЧ) Создаём новый костюм. Можно конечно и для существующего прописать всё, но лучше потратить на минутку больше и сделать качественнее. В файл gamedata/config/misc/unique_items.ltx в конец добавляем новую секцию:
В файл gamedata/config/text/rus/string_table_outfit.xml в конец перед тэгом дописываем:
Код
<string id="stalker_outfit_name_m3"> <text>Прототип мед. комбинезона</text> </string> <string id="stalker_outfit_description_m3"> <text>Данный образец является прототипом защитного комбинезона сталкера. От оригинала он отличается наличием уникальной системы приёма медикаментов. Если здоровье хозяина опуститься ниже 20% будет автоматически использован мед. препарат.</text> </string>
Делаем схему рабочей В файле bind_stalker.script под строкой function actor_binder:update(delta) пишем med_outfit.main() --лечащий костюм, примерно так (таким образом мы будем вызывать наш будущий скрипт несколько раз в секунду):
Код
function actor_binder:update(delta) med_outfit.main() --Лечащий костюм
Создаём файл med_outfit.script в соответствующей папке и в сам файл пишем:
Код
function main() local medkit = db.actor:object("medkit") local medkit_army = db.actor:object("medkit_army") local medkit_scientic = db.actor:object("medkit_scientic") local outfit = db.actor:item_in_slot(6) --определяем предмет в слоте 6 (костюм) local snd = sound_object([[device/pda/pda_tip]]) --звук сообщения if outfit and outfit:section() == "outfit_stalker_m3" and db.actor.health < 0.20 and db.actor.health > 0.005 then if medkit then db.actor:eat(medkit) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 1) db.actor:give_game_news("\n%c[255,255,0,0]Была автоматически использована аптечка.", "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 2000) elseif medkit_army then db.actor:eat(medkit_army) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 1) db.actor:give_game_news("\n%c[255,255,0,0]Была автоматически использована армейская аптечка.", "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 2000) elseif medkit_scientic then db.actor:eat(medkit_scientic) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 1) db.actor:give_game_news("\n%c[255,255,0,0]Была автоматически использована научная аптечка.", "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 2000) end end end
Теперь если ХП у актёра меньше 20%, одет нужный костюм и есть аптечка - она автоматически используется. Чтобы Волк выдал его в начале игры в файле escape_dialog.script в функции give_weapon_to_actor допишем:
Дата: Воскресенье, 10.01.2016, 22:36 | Сообщение # 11
Агро-Разработчик
[ Легенда Зоны ]
Здравствуйте, сегодня мы рассмотрим добавление места для сна в ЗП. Это моя первая статья, так что прошу сильно ногами не бить.... 1. Итак, мы решили добавить место для сна. Сначала мы распакуем all.spawn, откроем alife_zaton.ltx и добавим в конце секцию
Код
[Ваш номер секции] ; cse_abstract properties section_name = space_restrictor name = произвольное название вашего места position=155.8231048584,-6.5563974380493,-138.71978759766 direction = 0,0,0 version = 0x7c script_version = 8
Дата: Воскресенье, 17.01.2016, 05:49 | Сообщение # 12
Агро-Разработчик
[ Легенда Зоны ]
Если спавнил эксклюзива через смарт-террейн, то в логике точки пути надо писать сокращенно
Т.е. если в way_локация.ltx вейпоинт называется marsh_base_stalker_trader_walker_1_walk (look), а имя смарт-террейна marsh_base, В логике надо писать path_walk = stalker_trader_walker_1_walk (без имени смарта). Если-же спавнил через All.spawn - тогда полное имя пути нужно.
Код
[logic] active = walker
[walker] path_walk = bar_bar_visitor_dolg_walk path_look = bar_bar_visitor_dolg_look def_state_standing = scaner_stand on_game_timer = 150 | walker@1 meet = meet danger = danger_ignore on_info = {!is_day} walker@sleep_night ;условие -!(отрицание) если день - переход ко сну
[walker@sleep_night] ;спать path_walk = bar_bar_visitor_dolg_walk path_look = bar_bar_visitor_dolg_look def_state_standing = sleep on_info = {=is_day} walker ; =(соответствует) если день meet = no_meet ;чтобы не будили
На примере Юпитера:
Заменяем все содержимое файла jup_crow_spawner.ltx на это
Также можно поудалять все Spawn_path из way_локация.ltx
Создаем скрипт, например scripts\new_script.script
В него вставляем следующие функции:
-- Тут мы проверяем, получали ли мы раньше инфопоршень info_new_level -- И если мы его не получали, то нам отмечается переход, и выдается этот инфопоршень -- Нужно это для того, чтобы мы получали Отметку только один раз
Код
function level_changer() if not has_alife_info("info_new_level") then otmetit_perehod() db.actor:give_info_portion("info_new_level") end end
function otmetit_perehod() for i=1,65534 do local obj = alife():object(i) if obj then if obj:name() == "Название 1-го левел чэнджера" then level.map_add_object_spot_ser(obj.id,"level_changer_up","Подпись 1") elseif obj:name() == "Название 2-го левел чэнджера" then level.map_add_object_spot_ser(obj.id,"level_changer_up","Подпись 2") --elseif ..... end end end
Название берётся из поля name level_changer'а в all.spawn; Подпись - например, "На Кордон". Далее, в bind_stalker.script после function actor_binder:update(delta) надо написать new_script.level_changer() и в файле info_portions.xml зарегистрировать наш инфопоршень, добавив строку
Код
<info_portion id="info_new_level"></info_portion>
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
Сохраните изменения в файле. Теперь стартового ролика после начала новой игры не будет.
Итак, допустим, вы делаете мод на ЗП, и вам нужно восстановить Сидоровича со всеми его анимациями и фразами. В этой статье я расскажу и опишу этот процесс. 1. Для начала откроем папку creatures и создадим там файл с расширение ltx Назовем его, скажем, m_sidor Теперь в этот файл пишем следующее
species of monster species = human [trader_foot_bones] front_left = bip01_l_foot front_right = bip01_r_foot [trader_step_manager] order left, right -------------------------------------------------------------------------- animation Cycles | time1 | power1 | time2 | power2 | -------------------------------------------------------------------------- [barman_movement_speeds] barman can't crouch or run ; danger ;; crouch ;;; walk danger_crouch_walk_forward = 0.8 danger_crouch_walk_backward = 0.575 danger_crouch_walk_left = 0.8 danger_crouch_walk_right = 0.8 ;;; run danger_crouch_run_forward = 2.0 danger_crouch_run_backward = 1.1 danger_crouch_run_left = 2.0 danger_crouch_run_right = 2.0 ;; stand ;;; walk danger_stand_walk_forward = 1.2 danger_stand_walk_backward = 1.2 danger_stand_walk_left = 1.2 danger_stand_walk_right = 1.2 ;;; run danger_stand_run_forward = 5.0 danger_stand_run_backward = 1.5 danger_stand_run_left = 5.0 danger_stand_run_right = 5.0 ; free ;; stand ;;; forward free_stand_walk_forward = 0.85 free_stand_run_forward = 2.5 ; panic ;; stand ;;; run ;;;; forward panic_stand_run_forward = 6.5
Это мы создали спавн секцию торговца. Еще нужно в stalkers.ltx, который находится в той же папке, добавить инклуд 1. include "m_sidor.ltx" 2. В спавн секции указан биндер bind_trader Нужно его создать. В папке создаем файл с расширением script и называем его bind_trader В него пишем следующее
Код
-- Sidor etc binding function bind(obj) local new_binder = trader_object_binder(obj) obj:bind_object(new_binder) end class "trader_object_binder" (object_binder) function trader_object_binder:__init(obj) super(obj) self.loaded = false end
function trader_object_binder:reload(section) object_binder.reload(self, section) end function trader_object_binder:reinit() object_binder.reinit(self) db.storage[self.object:id()] = { } self.st = db.storage[self.object:id()] end function trader_object_binder:update(delta) object_binder.update(self, delta) -- Апдейт торговли if self.object:clsid() == clsid.script_trader then trade_manager.update(self.object) end local st = db.storage[self.object:id()] if st ~= nil and st.active_scheme ~= nil then xr_logic.try_switch_to_another_section(self.object, st[st.active_scheme], db.actor) end if self.st.active_section ~= nil then xr_logic.issue_event(self.object, self.st[self.st.active_scheme], "update", delta) end end function trader_object_binder:net_spawn(sobject) if not object_binder.net_spawn(self, sobject) then return false end local on_offline_condlist = db.storage[self.object:id()] and db.storage[self.object:id()].overrides and db.storage[self.object:id()].overrides.on_offline_condlist if on_offline_condlist ~= nil then xr_logic.pick_section_from_condlist(db.actor, self.object, on_offline_condlist) end if not self.object:alive() then return true end if alife():object(self.object:id()) == nil then return false end db.add_obj(self.object) if self.object:clsid() == clsid.script_trader then self.object:set_trader_global_anim("idle_spinka") smart_terrain.setup_gulag_and_logic_on_spawn( self.object, self.st, sobject, modules.stype_trader, self.loaded) end return true end function trader_object_binder:net_destroy() xr_sound.stop_sounds_by_id(self.object:id()) local st = db.storage[self.object:id()] if st and st.active_scheme then xr_logic.issue_event(self.object, st[st.active_scheme], "net_destroy") end if db.offline_objects[self.object:id()] then db.offline_objects[self.object:id()].level_vertex_id = self.object:level_vertex_id() db.offline_objects[self.object:id()].active_section = db.storage[self.object:id()].active_section end db.del_obj(self.object) db.storage[self.object:id()] = nil object_binder.net_destroy(self) end function trader_object_binder:net_save_relevant() return true end function trader_object_binder:save(packet) set_save_marker(packet, "save", false, "trader_object_binder") object_binder.save(self, packet) xr_logic.save_obj(self.object, packet) if self.object:clsid() == clsid.script_trader then trade_manager.save(self.object, packet) end set_save_marker(packet, "save", true, "trader_object_binder") end function trader_object_binder:load(reader) self.loaded = true set_save_marker(reader, "load", false, "trader_object_binder") object_binder.load(self, reader) xr_logic.load_obj(self.object, reader) if self.object:clsid() == clsid.script_trader then trade_manager.load(self.object, reader) end set_save_marker(reader, "load", true, "trader_object_binder") end
3. В той же папке scripts создадим файл mob_trader.script и в него пишем
} head_animations = { forester_talk_1 = {"sit_talk_1_in","sit_talk_1","sit_talk_1_out"}, forester_talk_2 = {"sit_talk_2_in","sit_talk_2","sit_talk_2_out"}, forester_talk_3 = {"sit_talk_3_in","sit_talk_3","sit_talk_3_out"}, forester_reaction = {"reaction_in","reaction","reaction_out"}, normal = {"talk_0","talk_1","talk_4"}, angry = {"talk_3","talk_2","talk_1"}, good = {"talk_glad_0"}, first_phrase = {"vstuplenie_head"} } function on_start_tutorial_item_1() if db.trader == nil then return end db.trader:external_sound_start("characters_voice\\scenario\\trader\\trader_tutorial_pda_12") end function on_stop_tutorial_item() if db.trader == nil then return end db.trader:external_sound_stop() end class "mob_trader" function mob_trader:__init(obj, storage) self.object = obj self.st = storage end function mob_trader:reset_scheme() trader_obj = self.object self.st.signals = {} self.object:set_callback(callback.trader_global_anim_request, self.on_global_anim_request, self ) self.object:set_callback(callback.trader_head_anim_request, self.on_head_anim_request, self ) self.object:set_callback(callback.trader_sound_end, self.on_sound_end, self ) self.object:set_callback(callback.use_object, self.use_callback, self) -- start global animation self.object:set_trader_global_anim(self:select_global_animation()) -- start sound and head animation if (self.st.sound_phrase) then local snd = mob_sound.pick_sound_from_set(self.object, self.st.sound_phrase, {}) self.object:set_trader_sound(snd, self:select_head_animation()); end if self.st.anim_head == nil then self.st.anim_head = "normal" end db.trader = self.object end function mob_trader:use_callback() -- dialog_manager.restore_npc_disabled_phrases(self.object:id()) end function mob_trader:update(delta) if xr_logic.try_switch_to_another_section(self.object, self.st, db.actor) then return end end function mob_trader:select_global_animation() local anim_set = global_animations[self.st.anim_global] local r = math.random(1, #anim_set) return anim_set[r] end function mob_trader:select_head_animation() -- random select local anim_set = head_animations[self.st.anim_head] local r = math.random(1, #anim_set) return anim_set[r] end function mob_trader:on_global_anim_request() self.st.signals["animation_end"] = true if (not self.st.play_once) then self.object:set_trader_global_anim(self:select_global_animation()) end end function mob_trader:on_head_anim_request() if self.st.anim_head == nil then return end self.object:set_trader_head_anim(self:select_head_animation()); end function mob_trader:on_sound_end() self.st.signals["sound_phrase_end"] = true end function mob_trader:deactivate() self.object:set_callback(callback.trader_global_anim_request, nil ) self.object:set_callback(callback.trader_head_anim_request, nil ) self.object:set_callback(callback.trader_sound_end, nil ) self.object:set_callback(callback.use_object, nil ) self.st.signals = {} db.trader = nil end function add_to_binder(npc, ini, scheme, section, storage) printf("DEBUG: add_to_binder: npc:name()='%s', scheme='%s', section='%s'", npc:name(), scheme, section) local new_action = mob_trader(npc, storage) -- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы: xr_logic.subscribe_action_for_events(npc, storage, new_action) end function set_scheme(npc, ini, scheme, section, gulag_name) local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section) st.logic = xr_logic.cfg_get_switch_conditions(ini, section, npc) st.anim_global = utils.cfg_get_string(ini, section, "anim_global", npc, true, "") st.can_talk = utils.cfg_get_bool(ini, section, "can_talk", npc, false, true) st.tip_text = utils.cfg_get_string(ini, section, "tip_text", npc, false, "", "character_use") if st.tip_text == nil then st.tip_text = "" end npc:set_tip_text(st.tip_text) if (ini:line_exist( section, "sound_phrase")) then st.anim_head = utils.cfg_get_string(ini, section, "anim_head", npc, false, "") st.sound_phrase = utils.cfg_get_string(ini, section, "sound_phrase", npc, false, "") else st.anim_head = nil st.sound_phrase = nil end
--' check if play once animation st.play_once = false if (ini:line_exist( section, "on_signal")) then local str = utils.cfg_get_string(ini, section, "on_signal", npc, false, "") local par = utils.parse_params(str) if par[1] == "animation_end" then st.play_once = true end end if st.can_talk == true then npc:enable_talk() else npc:disable_talk() end end
4. Создаем профиль торговцу (подробно на этом останавливаться не буду) В character_desc_ пишем:
5. Далее нужно заспавнить Сидора. Это можно сделать через Perl, редактирую all.spawn, либо через СДК, что намного удобнне. Если вы решили делать через Perl, то вставляем в alife_ это (координаты спавна Сидоровича на Кордоне ЧН; вертексы меняйте на свои) [482]
Не забудьте создать файл торговли Сидора trade_sidor, который указали в логике, иначе вылет. Вот и все. Сидор должен занять свое место и все должно работать. P.S. Все скрипты и логику Сидора можно взять и в ЧН. Удачи в моддинге.
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014
Дата: Понедельник, 22.02.2016, 19:54 | Сообщение # 15
Агро-Разработчик
[ Легенда Зоны ]
Один из основных скриптов, грузится через class_registrator.script все функции из него считаются глобальными.
Код
prefetch("_G")
Код
function load_scheme(filename, scheme, stype)
загружает схему поведения НПС из файла скрипта подробнее можно поглядеть в modules.scriot
Код
function action(obj,...)
Задает объекту некоторое действие или несколько действий
Код
function round (value)
округляет число value до целого также в lua есть глобальная функция math.ceil(value) - округляет число, до нижнего значения т.е. math.ceil(2.9342) = 2
Код
function distance_between(obj1, obj2)
возвращает дистанцию между объектами, судя по всему в "метрах"
Код
function distance_between_safe(obj1, obj2)
аналогична предыдущей функции, НО! не вылетает, если один из объектов = nil
Код
function has_alife_info(info_id)
Проверка на инфопоршны, даже если игрока не существует info_id - строка, имя инфопоршена
Код
function reset_action (npc, script_name)
Перезагружает схему у НПС
Код
function GiveInfoViaPda(obj_receiver, obj_sender, info_number)
Скидывает на ПДА кому-угодно сообщение от кого-угодно (судя по всему осталось от 1935-го билда, где можно было общаться через ПДА) obj_receiver - npc получатель obj_sender - npc отправитель info_number - айдишник инфопоршена
Код
function interrupt_action(npc, script_name)
Если в данный момент у НПС выполняется какое-то действие, прерывает его и отключает скриптовый режим
Код
function random_choice(...)
случайно возвращает одно из введенных значений
Код
function new_action(...)
так и не понял, что она делает - используется толь в скрипте copy of a1.script
Код
function set_current_time (hour, min, sec)
Задает игровое время
Код
function str_split (str)
разбивает строку на 4 части, ориентируясь по разделителю "_" (судя по всему из ранних билдов, ибо сейчас нигде не используется)
Код
function random_number (min_value, max_value)
Возвращает случайное число в диапазоне от min_value до max_value
Код
function day_time()
Возвращает время в миллисекундах
Код
function local_hours()
Возвращает время в часах
Код
function parse_names( s )
разбивает строку S на таблицу из имен чего-либо, возвращает таблицу
Код
function parse_nums( s )
разбивает строку S на таблицу из чисел, возвращает таблицу
Код
function is_object_online(obj_id)
Возвращает является ли объект в онлайне
Код
function get_clsid(npc)
Возвращает id класса объекта
Код
function isWeapon(object)
Возвращает является ли объект оружием благодаря этой функции НПС просят актора убрать оружие
Код
function yaw( v1, v2 )
Возвращает какое-то значение поворота для этих точек
Код
function vector_rotate_y (v, angle)
Вращает вектор вокруг оси y против часовой стрелки возвращает вектор
Код
function clear_table (t)
Функция очищает таблицу t
Код
function stop_play_sound(obj)
прерывает звук от объекта
Код
function object_type(obj)
возвращает строку-название типа объекта , например "stalker" "monster"
Код
function is_object_monster(obj)
Возвращает является ли оbj монстром
Код
function switch_online (id) function switch_offline (npc)
переводят объект в оффдайн и онлайн
Код
function get_actor_id()
Возвращает id актора
Код
function IsMonster (object, class_id)
Возвращает является ли объект монстром
Код
function IsStalker (object, class_id)
Возвращает является ли объект сталкером (актору тоже выдает true)
Код
function level_object_by_sid( sid )
Возвращает объект по его story_id
Код
function id_by_sid( sid )
возвращает id объекта по его story_id
Код
function set_postprocess(name_ini_file) function remove_postprocess()
задает/снимает постпроцесс имя файла указывается с расширением .PPE
Код
function set_inactivate_input_time(delta)
отключает управление актором на время delta в секундах
Код
function set_sleep_relocate(point, look, timeout)
Задает актору позицию положения, позицию куда смотреть, время сна в минутах. Это все в силе, если раскомментировать часть функции
Код
function odd( x )
Проверяет целую часть числа x на нечётность
Код
function on_actor_critical_power() function on_actor_critical_max_power() function on_actor_bleeding() function on_actor_satiety() function on_actor_radiation() function on_actor_weapon_jammed() function on_actor_cant_walk_weight() function on_actor_psy()
Функции, которые выполняются при кровотечении, истощении, голоде и т.п. - редактируются тольок в самом _g.script
Возвращает имя файла текстуры по ее id Также возвращает x2 - ширину текстуры y2 - высоту тестуры
И так, всегда самая большая проблема, это тогда, когда изменяют наприклад что выдаёт волк, и в тот момент они пишут кучу повторяющихся строчек например
пишут столько раз, сколько таких вещей надо добавить. Но оказывается есть более простой способ, при котором можно написать даную стройчку только один раз, но заставить ПК выдать ГГ столько вещей сколько хочешь. Дело в том, что скрипты написаны на Языке Программирования(далее сокращено ЯП) Lua. А я как программист подумал, раз уж это ЯП, то там полюбом есть цыклы. А это такая штука которая заставт ПК сделать какое-то действие столько раз, сколько вы укажете. Хватит болтовни, перейдем к сути, синтаксис цыклов в ЛУА:
Код
for i = 1 , 10 dо --.....действие end
и вот на таком хитрим способом мы изменим наш скрип на вот такое:
Код
for i = 1 , 30 do dialogs.relocate_item_section(trader, "ammo_m209", "in") end
И вуаля, нам волк выдаст 30 подствольных гранат м209. Если хотите 150 таких патронов, тогда просто вместо 30-ти пишем 150.
Код
for i = 1 , 150 do dialogs.relocate_item_section(trader, "ammo_m209", "in") end
все просто, и ненадо 150 раз копировать одну и ту же строчку, и к тому же уменьшаете нагрузку на ПК и ваш Жёрсткий Диск)
IP-адрес: Страна: Российская Федерация Город: Москва Дата регистрации: 25.10.2014