singapur22 14 Опубликовано 13 Июля 2011 Поделиться Опубликовано 13 Июля 2011 (изменено) Описание: Менеджер контроля за положением курсора мыши на экране. (экспериментальный, как вариант)Автор: Singapur22Принцип: "1 из 4'ёх >> компресс >> 1 из 4'ёх >> компресс >> и т.д." 1. Создаём скриптовый файл, например: _mouse_pos.script 2. Вписываем в тело файла, код класса: local const_wins = {"winLT", "winRT", "winLD", "winRD"} --/summary/>> Event Rece function StaticRece(args) args[1].rec = args[2] end local win_id = 0 class "mouse_position" (CUIStatic) function mouse_position:__init(x, y, width, height, scriptWnd) super() win_id = win_id + 1 self.id = win_id self.X = x self.Y = y self.widthEl = width / 2 --ширина элемента зоны контроля, в режиме ожидания self.heightEl = height / 2 --высота элемента зоны контроля, в режиме ожидания self.rec = nil --постоянная элемента, на котором произашло событие захвата курсора self.get = false --ключ запуска, определения позиции курсора self.method = nil --метод (функция), в которую требуется передать полученные координаты self.owner = nil --объект, которому требуется передать полученные координаты self:SetWndRect(x, y, width, height) --устанавливаем общий размер зоны контроля (относительно её и будут выдаваться координаты) scriptWnd:Register(self, "event_winZC"..self.id) scriptWnd:AddCallback("event_winZC"..self.id, ui_events.STATIC_FOCUS_LOST, self.ZoneControllLost, self) --//делим зону контроля на 4 части self.winLT = CUIStatic() --элемент левого, верхнего угла self.winRT = CUIStatic() --элемент правого, верхнего угла self.winLD = CUIStatic() --элемент левого, нижнего угла self.winRD = CUIStatic() --элемент правого, нижнего угла self.winLT.X, self.winLT.Y = x, y self.winRT.X, self.winRT.Y = x + self.widthEl, y self.winLD.X, self.winLD.Y = x, y + self.heightEl self.winRD.X, self.winRD.Y = x + self.widthEl, y + self.heightEl for _, v in ipairs(const_wins) do self[v]:Init(self[v].X, self[v].Y, self.widthEl, self.heightEl) self[v]:SetAutoDelete(true) local reg_name = "event_"..v..self.id scriptWnd:Register(self[v], reg_name) scriptWnd:AddCallback(reg_name, ui_events.STATIC_FOCUS_RECEIVED, StaticRece, {self, v}) self:AttachChild(self[v]) end end --/summary/>> Event Lost Zone_Controll function mouse_position:ZoneControllLost() self.rec = nil if self.get then self.get = false self:recompress_zone() end end --/summary/>> Method Compress function mouse_position:compress_zone(win) if not win then return end local x, y = win.X, win.Y local width = win:GetWidth() / 2 local height = win:GetHeight() / 2 if win:GetWidth() < 5 then if self.method then self.method(self.owner, x + width, y + height) self.get, self.method, self.owner = false self:recompress_zone() end return end self:SetWndRectElements(x, y, width, height) end --/summary/>> Method Recompress function mouse_position:recompress_zone() self:SetWndRectElements(self.X, self.Y, self.widthEl, self.heightEl) end --/summary/>> Method SetWndRect function mouse_position:SetWndRectElements(x, y, width, height) self.winLT.X = x self.winLT.Y = y self.winLT:SetWndRect(self.winLT.X, self.winLT.Y, width, height) self.winRT.X = x + width self.winRT.Y = y self.winRT:SetWndRect(self.winRT.X, self.winRT.Y, width, height) self.winLD.X = x self.winLD.Y = y + height self.winLD:SetWndRect(self.winLD.X, self.winLD.Y, width, height) self.winRD.X = x + width self.winRD.Y = y + height self.winRD:SetWndRect(self.winRD.X, self.winRD.Y, width, height) end --/summary/>> Update function mouse_position:Update() if self.get then if not self.rec then self.get = false return end get_console():execute("mouse_pos="..tostring(self.rec)) self:compress_zone(self[self.rec]) end end --/summary/>> Method Start Get Position Cursor function mouse_position:GetPos(method, owner) self.get, self.method, self.owner = true, method, owner end Конструктор, инициализатор менеджера позиции курсора: self.mp = _mouse_pos.mouse_position(x, y, width, height, scriptWnd) Где:x = позиция начала координат, зоны контроля, по Xy = позиция начала координат, зоны контроля, по Ywidth = ширина зоны контроляheight = высота зоны контроляscriptWnd = объект класса CUIScriptWnd, относительно которого была произведена инициализация менеджера позиции курсора. Апдейт схемы контроля: self.mp:Update() Апдейт необходимо производить из виртуальной функции Update(), объекта класса CUIScriptWnd, относительно которого была произведена инициализация менеджера позиции курсора. Метод определения координат, относительно зоны контроля: self.mp:GetPos(method, owner) Где:method = метод (функция), в которую требуется передать полученные координаты, после завершения просчётаowner = объект, в котором нужно обратиться к указанному методу. если method является простой функцией (не методом), то owner передаётся в неё как первый аргумент. Приаттачиваем менеджер к объекту контроля: self:AttachChild(self.mp) Изменено 15 Декабря 2017 пользователем Murarius 1 Опаа-а!!! Ливер вылез! Ссылка на комментарий
Akella-96 aka SvD 35 Опубликовано 15 Июля 2011 Поделиться Опубликовано 15 Июля 2011 (изменено) Всем привет… Я долго искал статью по созданию работающего радио в ЗП, это было бессмысленно, пришлось учиться самому… Итак приступим…Для того что бы сделать новое РАБОТАЮЩЕЕ радио нам понадобятся файлы:all.spawn (распакованный)sound_theme.scriptИтак сначала заходим в файл alife_zaton.ltx (он находится в распакованном all.spawn)И добавляем в конец вот такие строки: [1866] ; cse_abstract properties section_name = physic_object name = zaton_radio position = 131.13690185547,-6.1206126213074,177.25036621094 direction = 0,2.40000009536743,0 ; cse_alife_object properties game_vertex_id = 296 distance = 0.400000005960464 level_vertex_id = 1189961 object_flags = 0xffffff3a custom_data = <<END [logic] cfg = scripts\zaton_radio.ltx END ; cse_visual properties visual_name = dynamics\el_tehnika\priemnik_gorizont ; cse_ph_skeleton properties skeleton_flags = 1 ; cse_alife_object_physic properties physic_type = 0x3 mass = 10 fixed_bones = link Теперь сохраняем и можно собирать all.spawn он нам больше не нужен(не забывайте ставить его на место переименовывая из файла new в all.Так теперь по порядку все объясню: [1866] – номер секции, он не должен повторяться.Если у вас чистый all то номер будет 1866 ; cse_abstract properties section_name = physic_object name = zaton_radio – уникальное имя position = 131.13690185547,-6.1206126213074,177.25036621094 - координаты direction = 0,2.40000009536743,0 ; cse_alife_object properties game_vertex_id = 296 – координаты вертикс distance = 0.400000005960464 level_vertex_id = 1189961 - координаты уровня object_flags = 0xffffff3a custom_data = <<END [logic] cfg = scripts\zaton_radio.ltx – путь к логике END ; cse_visual properties visual_name = dynamics\el_tehnika\priemnik_gorizont – путь визуалу модели ogf причем заметьте что ogf т.е. формат писать не надо ; cse_ph_skeleton properties skeleton_flags = 1 ; cse_alife_object_physic properties physic_type = 0x3 mass = 10 fixed_bones = link Редактируем только те места которые я откомментировал!!!Так теперь самое главное… ЛогикаЗаходим в папку gamedata//configs//scripts создаём там файл zaton_radio.ltx и в нём пишем: [logic] active = ph_sound [ph_sound] snd = music_radio looped = false min_idle = 300 max_idle = 500 random = true Сохраняем…Теперь заходим в папку gamedata\\ sound\\ characters_voice\\scenario\\ и создаем там папку zaton_radio после чего кидаем в эту папку музыкальные файлы в формате ogg и назовем их примерно так: zaton_1, zaton_2, zaton_3, zaton_4, zaton_5 (я написал только 5 названий песен, потому что вам для начало и 5 треков хватит)Все с музыкальными файлами закончили…Теперь открываем файл gamedata\\script\\sound_theme.script и в самом начале после строчки theme = {} пишем вот это: ph_snd_themes = {} ph_snd_themes["music_radio"] = { "characters_voice\\scenario\\zaton_radio\\zaton_5", "characters_voice\\scenario\\zaton_radio\\zaton_4", "characters_voice\\scenario\\zaton_radio\\zaton_3", "characters_voice\\scenario\\zaton_radio\\zaton_2", "characters_voice\\scenario\\zaton_radio\\zaton_1" } Сохраняем…После последней строчки запятую ставить не надо!!!Всё можно идти на и слушать радио (оно появится в скадовске на столе)(Теперь для тех, кто ещё не понял, строки в виде: "characters_voice\\scenario\\zaton_radio\\zaton_1" - это списки песен, которые будет проигрывать наше радио)Внимание: этот метод проверялся на чистом сталкере зов припяти версии 1.6.00На некоторых модах может не работать из-за не совместимостиСтатья от Akella-96 Изменено 19 Сентября 2014 пользователем World_Stalker 1 AWRP : Re - Load 0.2 © Ссылка на комментарий
Капрал Хикс 521 Опубликовано 24 Сентября 2011 Поделиться Опубликовано 24 Сентября 2011 (изменено) Сложность: средне.Что потребуется: программа для снятия координат (Position Informer или любая другая), распаковщик-запаковщик all.spawn – ACDC конвертер от bardak’а, несколько файлов из ЗП.Для начала снимаем координаты того места, где нужно поставить метку. Желательно снимать метку, находясь в центре нужного объекта. Записываем координаты x,y,z, level- и game-vertex'ы.Распаковываем all.spawn необходимой версией распаковщика. Открываем блокнотом алайф.лтх нужной нам локации и в конце файла создаём секцию вида: [номер, следующий за номером предыдущей секции] ; cse_abstract properties section_name = space_restrictor name = st_pri_b302 position = 135.845,16.680,219.551 ;подставляем нужные координаты direction = 0,0,0 ; cse_alife_object properties game_vertex_id = 3764 ;пишем нужный гейм-вертекс distance = 0 level_vertex_id = 340694 ;пишем нужный левел-вертекс object_flags = 0xffffff3e story_id = 16000 ;присваиваем стори_айди ; cse_shape properties shapes = shape0 shape0:type = sphere shape0:offset = 0,0,0 shape0:radius = 1 ; cse_alife_space_restrictor properties restrictor_type = 3 Стори_айди не должны повторяться, для этого открываем блокнотом файл game_story_ids.ltx – смотрим, каких цифр нет, и дописываем в конец файла все вновь присвоенные стори_айди по типу уже существующих. Очень большие числа не брать, достаточно предела 10000-15000, допустим, хватит для чего угодно.В итоге в конце файла дописываем строки вида: 16000 = "st_pri_b306_name" где число – это айди, в кавычках имя, в принципе можно ставить любое, названия меток у нас будут прямо в скрипте.Далее открываем блокнотом файл level.tasks.script (gamedata/scripts…)Видим там функцию: function add_lchanger_location() local sim = alife() if sim then -- escape local obj = sim:story_object(91) if obj then level.map_add_object_spot(obj.id, "level_changer", "to_garbage") end… -- и.т.д… -- Для каждой нужной нам метки создаём секцию вида: local obj = sim:story_object(91) –- номер стори_айди метки if obj then level.map_add_object_spot(obj.id, "тип метки", "название метки, например Мост им. Преображенского") end… Далее, по типам меток. В принципе, можно использовать стандартные ТЧ-метки.Например:crlc_big – большой белый круг;crlc_mdl – средних размеров круг;crlc_small – маленький кружок.Но можно сделать метки объектов из ЗП. Для этого открываем блокнотом файлик map_spots.xml (config/ui) и дописываем перед финальным </map_spots> секцию вида: <primary_object> <level_map spot="primary_object_spot" pointer="quest_pointer"/> </primary_object> <primary_object_spot x="0" y="0" width="15" height="15" alignment="c" scale="1" scale_min="1" scale_max="6" stretch="1"> <texture x="0" y="585" width="205" height="205">ui\ui_actor_sleep_screen</texture> </primary_object_spot> Теперь можно тип метки указывать ”primary_object”.Закидываем по адресу textures/ui файлик ui_actor_sleep_screen.dds из ЗП, заходим в игру, начинаем НИ и любуемся метками… Метки через данный способ будут отображаться постоянно.Описал вроде всё, текстурку ui_actor_sleep_screen.dds берём из файлов ЗП. Изменено 20 Сентября 2014 пользователем World_Stalker 1 Ссылка на комментарий
Max_Plohih 4 Опубликовано 11 Октября 2011 Поделиться Опубликовано 11 Октября 2011 (изменено) Нам понадобится файл treasure_manager.script.В этом файле находим такие строки:--' Юзание инициатора (возможность выдать тайник) function CTreasure:use(npc) printf("TREASURE USE")После строки printf("TREASURE USE") пишем:if (npc and db.actor) then lootmoney.lootmoney(npc) end У нас должно выйти:--' Юзание инициатора (возможность выдать тайник) function CTreasure:use(npc) printf("TREASURE USE") if (npc and db.actor) then lootmoney.lootmoney(npc) end Теперь создаём файл lootmoney.script и в нём пишем:function lootmoney(npc) if npc ~= nil and not string.find(npc:section(),"arena") and npc:character_community()~="arena_enemy" then local money = npc:money() if money ~= nil and money ~=0 then local deadmoney = money local npc_rank npc_rank = ranks.get_obj_rank_name(npc) if npc_rank ~= nil then if npc_rank == "novice" and deadmoney >=400 then deadmoney=math.random(25,400) elseif npc_rank == "experienced" and deadmoney >=500 then deadmoney=math.random(50,500) elseif npc_rank == "veteran" and deadmoney >=600 then deadmoney=math.random(100,600) elseif npc_rank == "master" and deadmoney >=700 then deadmoney=math.random(200,700) end end local news_texti = "\\n%c[255,255,0,0]Мёртвый сталкер: %c[default]"..npc:character_name().."\\n%c[255,255,0,0]Обнаружено денег: %c[default]"..game.translate_string(tostring(deadmoney).."руб.") db.actor:give_game_news(news_texti, "ui\\ui_iconsTotal", Frect():set(0,0,83,47), 1, 4000) db.actor:give_money(deadmoney) game_stats.money_quest_update(deadmoney) npc:give_money(-money) game_stats.money_quest_update(-money) end end end Итак, первым делом в директории gamedata\scripts создайте файл с названием имя_вашего_файла.script1.Открываем его и пишем: -- названия локаций local level_name = { ["l01_escape"] = "Кордон", ["l02_garbage"] = "Свалка", ["l03_agroprom"] = "НИИ Агропром", ["l03u_agr_undergroun"] = "Подземелье НИИ Агропром", ["l04_darkvalley"] = "Тёмная долина", ["l04u_labx18"] = "Лаборатория X-18", ["l05_bar"] = "Бар", ["l06_rostok"] = "Дикая территория", ["l07_military"] = "Арм.склады", ["l08_yantar"] = "Янтарь", ["l08u_brainlab"] = "Лаборатория X-16", ["l10u_bunker"] = "Лаборатория X-10", ["l10_radar"] = "Радар", ["l11_pripyat"] = "Припять", ["l12_stancia"] = "ЧАЭС", ["l12_stancia_2"] = "ЧАЭС", ["l12u_sarcofag"] = "Саркофаг", ["l12u_control_monolith"] = "Управление Монолитом" } -- названия группировок local community = { ["stalker"] = "Сталкер", ["monolith"] = "Монолит", ["military"] = "Военные", ["bandit"] = "Бандит", ["killer"] = "Наемник", ["ecolog"] = "Эколог", ["dolg"] = "Долг", ["freedom"] = "Свобода", ["zombied"] = "Зомбированный", ["trader"] = "Торговец" } function kill_npc(victim, who) if victim and IsStalker(victim) then -- определяется какая группировка у убитого, его имя, локация local dead_news = "\\n%c[255,160,160,160]Группировка: %c[default]"..community[victim:character_community()].."\\n%c[255,160,160,160]Имя: %c[default]"..victim:character_name().."\\n%c[255,160,160,160]Локация: %c[default]"..level_name[level.name()].."" db.actor:give_game_news(dead_news, "ui\\ui_icons_npc", Frect():set(2,130,124,124), 1, 4000) end end 2. Далее открываем xr_motivator.script, который находится в gamedata\scripts, ищем функцию:function motivator_binder:death_callback(victim, who)и после пишем: имя_вашего_файла.kill_npc(victim, who) в итоге:function motivator_binder:death_callback(victim, who) имя_вашего_файла.kill_npc(victim, who) if who:id() == db.actor:id() then xr_statistic.addKillCount(self.object) endВот собственно и все!Прим. от AntdiabloN. Можно сделать так чтобы при выводе инфы возможно было услышать звук принятого сообщения. В конце файла с сообщениями о смерти пишем --- Звук сообщения function news_sound() local snd_obj snd_obj = xr_sound.get_safe_sound_object([[device\pda\pda_tip]]) -- путь до звукового файла snd_obj:play_no_feedback(db.actor, sound_object.s2d, 1, vector(), 1.0) endи в функции news_of_npc_kill перед первым end пишем - имя_вашего_файла.news_sound()Пример как может быть выглядеть функция:function kill_npc(victim, who) if victim and IsStalker(victim) then local dead_news = "\\n%c[255,160,160,160]Группировка: %c[default]"..community[victim:character_community()].."\\n%c[255,160,160,160]Имя: %c[default]"..victim:character_name().."\\n%c[255,160,160,160]Локация: %c[default]"..level_name[level.name()].."" db.actor:give_game_news(dead_news, "ui\\ui_icons_npc", Frect():set(2,130,124,124), 1, 4000) имя_вашего_файла.news_sound() end end Изменено 20 Сентября 2014 пользователем World_Stalker Поправил 2 Мой мод. Ссылка на комментарий
*Shoker* 322 Опубликовано 16 Октября 2011 Поделиться Опубликовано 16 Октября 2011 Последняя версия скрипта для отлова выстрела из оружия http://dl.dropbox.com/u/23885395/sm_wpns.rar Огромное спасибо Artos-у и KD87 за помощь. Скрипт позволяет отслеживать выстрелы из любого оружия, которое расходует патроны. Работает с любой частью Сталкера. Тестировался на ЧН. Для ЗП скрипт немного изменён. Особенности этой версии: * Скрипт теперь работает без сторонних программ по отлову нажатия клавиш. (не требует кейлогеров) * Существенно поднята точность отлова. * Расширена передаваемая в колбек на выстрел информация. Информация о известных багах внутри скрипта. Все предыдущие обсуждения скрипта в этой теме лучше стереть. А ссылку на этот пост, по усмотрению куратора раздела, добавить в шапку, чтобы он не затерялся. 1 Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О Мастер аномалий на свою заднюю точку. Ссылка на комментарий
Driv3r 9 Опубликовано 27 Октября 2011 Поделиться Опубликовано 27 Октября 2011 (изменено) Еще функции (Для ТЧ). function kill_stalker(actor, npc) npc:kill(npc) end function enemy(actor, npc) npc:set_relation (game_object.enemy, db.actor) end function any_sound() local snd = sound_object([[characters_voice\human_03\stalker\talk\leaves\leaves_42]]) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 2.0) end function НАЗВАНИЕ_create() local x= local y= local z= local level_vertex= local game_vertex_id= alife():create("НАЗВАНИЕ",vector():set(x,y,z),level_vertex,game_vertex_id) end Например: function all_spawn() НАЗВАНИЕ_create() any_sound() end function НАЗВАНИЕ_create() local x= local y= local z= local level_vertex= local game_vertex_id= alife():create("НАЗВАНИЕ",vector():set(x,y,z),level_vertex,game_vertex_id) end function any_sound() local snd = sound_object([[characters_voice\human_03\stalker\talk\leaves\leaves_42]]) snd:play_no_feedback(db.actor,sound_object.s2d, 0, vector():set(0, 0, 0), 2.0) end Изменено 15 Декабря 2017 пользователем Murarius Ссылка на комментарий
Tris 9 Опубликовано 30 Октября 2011 Поделиться Опубликовано 30 Октября 2011 (изменено) На досуге решил поковыряться в файлах "ui" решил покапать файлы: actor_menu\actor_menu_16 (обычные\широкоформатные мониторы)Автор: Trisвот что накопал: <actor_money_static x="501" y="75" width="104" height="22"> <text align="r" font="graffiti22"/> </actor_money_static> <partner_money_static x="55" y="75" width="104" height="22"> <text align="r" font="graffiti22"/> </partner_money_static> ;;;;;;;;;;;;;;;;;;; Место нахождение денег(actor\partner);;;;;;;;;;;;;;;;;;;;;; (Актёр\тот с кем ведёте разговор) <inv_slot2_highlight x="189" y="17" width="65" height="353" stretch="1">;;;;1 оружие <texture>ui_inGame2_weapon_highlighter</texture> </inv_slot2_highlight> <inv_slot3_highlight x="368" y="17" width="65" height="353" stretch="1">;;;;2 оружие <texture>ui_inGame2_weapon_highlighter</texture> </inv_slot3_highlight> <helmet_slot_highlight x="172" y="17" width="76" height="98" stretch="1">;;;; шлем <texture>ui_inGame2_helmet_highlighter</texture> </helmet_slot_highlight> <outfit_slot_highlight x="172" y="142" width="76" height="161" stretch="1">;;;; костюм <texture>ui_inGame2_armor_highlighter</texture> </outfit_slot_highlight> <detector_slot_highlight x="172" y="330" width="76" height="48" stretch="1">;;;; детектор <texture>ui_inGame2_detector_highlighter</texture> </detector_slot_highlight> <quick_slot_highlight x="187" y="398" width="52" height="59" dx="64" stretch="1">;;;; быстрое использование <texture>ui_inGame2_quick_item_highlighter</texture> </quick_slot_highlight> <artefact_slot_highlight x="187" y="476" width="41" height="52" dx="52" stretch="1">;;;; артифакты <texture>ui_inGame2_artefakt_highlighter</texture> </artefact_slot_highlight> ;;;;;;;;;;;;;;;;;Подсветка слотов;;;;;;;;;;;;;;;;;;;;;;; <quick_slot1_text x="386" y="550" width="14" height="13"> <text align="c" font="letterica16">quick_use_str_1</text>;;;;;;;; F1 </quick_slot1_text> <quick_slot2_text x="451" y="550" width="14" height="13"> <text align="c" font="letterica16">quick_use_str_2</text>;;;;;;;; F2 </quick_slot2_text> <quick_slot3_text x="516" y="550" width="14" height="13"> <text align="c" font="letterica16">quick_use_str_3</text>;;;;;;;; F3 </quick_slot3_text> <quick_slot4_text x="580" y="550" width="14" height="13"> <text align="c" font="letterica16">quick_use_str_4</text>;;;;;;;; F4 </quick_slot4_text> ;;;;;;;;;;; Надписи f1 - f2 - f3 - f4;;;;;;;;;;;;;;;;;;;;;;;;;;; <progess_bar_weapon1 x="198" y="378" width="47" height="5" horz="1" min="0" max="1" pos="0">;;;;; 1 оружие <progress stretch="1"> <texture r="142" g="149" b="149">ui_inGame2_inventory_status_bar</texture> </progress> <min_color r="196" g="18" b="18"/> <middle_color r="255" g="255" b="118"/> <max_color r="107" g="207" b="119"/> </progess_bar_weapon1> <progess_bar_weapon2 x="178" y="378" width="47" height="5" horz="1" min="0" max="1" pos="0">;;;;; 2 оружие <progress stretch="1"> <texture r="142" g="149" b="149">ui_inGame2_inventory_status_bar</texture> </progress> <min_color r="196" g="18" b="18"/> <middle_color r="255" g="255" b="118"/> <max_color r="107" g="207" b="119"/> </progess_bar_weapon2> <progess_bar_outfit x="188" y="309" width="47" height="5" horz="1" min="0" max="1" pos="0">;;;;; костюм <progress stretch="1"> <texture r="142" g="149" b="149">ui_inGame2_inventory_status_bar</texture> </progress> <min_color r="196" g="18" b="18"/> <middle_color r="255" g="255" b="118"/> <max_color r="107" g="207" b="119"/> </progess_bar_outfit> <progess_bar_helmet x="188" y="118" width="47" height="5" horz="1" min="0" max="1" pos="0">;;;;; шлем <progress stretch="1"> <texture r="142" g="149" b="149">ui_inGame2_inventory_status_bar</texture> </progress> <min_color r="196" g="18" b="18"/> <middle_color r="255" g="255" b="118"/> <max_color r="107" g="207" b="119"/> </progess_bar_helmet> ;;;;;;;;;;;;;;;;;;;Прогресс бар(состояние:оружие 1\2; костюм; шлем;;;;;;;;;;;;;; <actor_weight_caption x="450" y="736" width="57" height="16"> <text align="r" font="letterica16" color="ui_3">ui_total_weight</text> </actor_weight_caption> <actor_weight x="307" y="736" width="35" height="16"> <text align="c" font="letterica16"/> </actor_weight> <actor_weight_max x="242" y="736" width="68" height="16"> <text align="l" font="letterica16" color="ui_3"/> </actor_weight_max> <partner_weight_caption x="74" y="738" width="68" height="14"> <text align="r" font="letterica16" color="ui_3">ui_total_weight</text> </partner_weight_caption> <partner_weight x="242" y="738" width="36" height="14"> <text align="l" font="letterica16" color="ui_7"/> </partner_weight> ;;;;;;;;;;;актёр: текущий вес рюкзака\максиальный;;;;;; с кем разгованиваеш:общий вес;;;;;;;;;;;;;;;; (actor) (partner) <!-- partner ---------------------------------------------------------------- --> <left_delimiter x="102" y="226" width="273" height="163" stretch="1"> <texture>ui_inGame2_center_trade_devider</texture> <trade_caption x="118" y="74" width="48" height="16"> <text align="l" font="letterica16" color="ui_3">ui_total_price</text> </trade_caption> <trade_price x="166" y="74" width="13" height="16"> <text align="l" font="letterica16"/> </trade_price> <trade_weight_max x="206" y="74" width="40" height="16"> <text align="l" font="letterica16" color="ui_3"/> </trade_weight_max> </left_delimiter> <!-- actor ---------------------------------------------------------------- --> <right_delimiter x="648" y="226" width="273" height="163" stretch="1"> <texture>ui_inGame2_center_trade_devider</texture> <trade_caption x="118" y="74" width="48" height="16"> <text align="r" font="letterica16" color="ui_3">ui_total_price</text> </trade_caption> <trade_price x="166" y="74" width="40" height="16"> <text align="c" font="letterica16"/> </trade_price> <trade_weight_max x="206" y="74" width="40" height="16"> <text align="l" font="letterica16" color="ui_3"/> </trade_weight_max> </right_delimiter> ;;;;;;;;;;;;;;;;Левый разделитель\ правый разделитель;;;;;;;;;;;;;;;;;;;;;; (с кем разговариваеш) (актёр) <belt_list_over x="384" y="472" width="47" height="59" dx="52" stretch="1"> <texture >ui_inGame2_artefact_blocker</texture> </belt_list_over> <helmet_over x="467" y="11" width="89" height="115" stretch="1"> <texture >ui_inGame2_helmet_blocker</texture> </helmet_over> ;;;;;;;;;;;;;;;текстуры закрытия слотов под арты/шлем;;;;;;;;;;;;;;; <dragdrop_bag x="162" y="119" width="250" height="574" cell_width="33" cell_height="41" rows_num="14" cols_num="7" unlimited="1" group_similar="1" always_show_scroll="1" condition_progress_bar="1"/> ;;;;;;;;;;;;;сетка инвентаря(там где распологаются все вещи);;;;;;;;;;;;;; <dragdrop_outfit x="269" y="137" width="85" height="178" cell_width="33" cell_height="41" rows_num="3" cols_num="2" custom_placement="0" a="0" virtual_cells="1" vc_vert_align="c" vc_horiz_align="c"/> <dragdrop_helmet x="269" y="14" width="85" height="110" cell_width="33" cell_height="41" rows_num="2" cols_num="2" custom_placement="0" a="0" virtual_cells="1" vc_vert_align="c" vc_horiz_align="c" /> ;;;;;;;;;;;;;;;;;;;слоты: костюм\шлем;;;;;;;;;;;;;;;;;;;;;;;;; <dragdrop_detector x="469" y="328" width="85" height="55" cell_width="33" cell_height="41" rows_num="1" cols_num="2" custom_placement="0" a="0" virtual_cells="1" vc_vert_align="c" vc_horiz_align="c"/> ;;;;;;;;;;;;;;;;;;;;;;;;слот детектора;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <dragdrop_pistol x="384" y="14" width="74" height="368" cell_width="33" cell_height="41" rows_num="6" cols_num="2" custom_placement="0" vertical_placement="1" a="0" virtual_cells="1" vc_vert_align="c" vc_horiz_align="c"/> ;;;;;;;;;;;;;;;;;;1 слот для оружия;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <dragdrop_automatic x="563" y="14" width="74" height="370" cell_width="33" cell_height="41" rows_num="6" cols_num="2" custom_placement="0" vertical_placement="1" a="0" virtual_cells="1" vc_vert_align="c" vc_horiz_align="c" /> ;;;;;;;;;;;;;;;;2 слот для оружия;;;;;;;;;;;;;;;;;;;;; <dragdrop_quick_slots x="398" y="407" width="227" height="41" cell_width="33" cell_height="41" a="0" rows_num="1" cols_num="4" cell_sp_x="32" cell_sp_y="0" custom_placement="1"/> ;;;;;;;;;; слоты быстрого использования вещей;;;;;;;;;;;;;;; Изменено 20 Сентября 2014 пользователем World_Stalker • Dead Forgetting Zone • Мои работы. Обновление: 24.08.2012 Ссылка на комментарий
Max_Plohih 4 Опубликовано 18 Ноября 2011 Поделиться Опубликовано 18 Ноября 2011 Для создания спального мешка, нам понадобятся эти файлы: В папке scriptsbind_stalker.script пустой файл main_sleep.script В папке config/uiui_movies.xml пустой ui_sleep.xml В папке config/miscdream.ltx items.ltx В папке config/texs/russtring_table_enc_equipment.xml Заходим в gamedata\config\misc, ищем файл items.ltx и в конце пишем: [sleep_bag]:identity_immunities GroupControlSection = spawn_group discovery_dependency = $spawn = "food and drugs\sleep_bag" $prefetch = 32 class = II_ANTIR;класс cform = skeleton visual = physics\decor\bag_01.ogf;модель мешка с песком description = enc_equipment_sleep_bag;описание inv_name = sleep_bag;наименование inv_name_short = sleep_bag;наименование inv_weight = 0.2;вес inv_grid_width = 2;ширина иконки inv_grid_height = 2;высота иконки inv_grid_x = 12;ширина по x inv_grid_y = 0; высота по y cost = 3000;стоимость ; eatable item eat_health = 0 eat_satiety = 0 eat_power = 0 eat_radiation = 0.0 wounds_heal_perc = 0 eat_portions_num = 1 ; food item animation_slot = 4 ;hud item hud = wpn_vodka_hud Работа с созданием спального мешка завершена. Название и описание. Заходим в gamedata\config\text\rus, находим файл string_table_enc_equipment.xml, открываем его и в самом низу, перед </string_table> пишем: <string id="sleep_bag"> <text>Спальный мешок</text> </string> <string id="enc_equipment_sleep_bag"> <text>Отличный спальный мешок. Ткань не рвется, устойчивая к воде. Отличная вещь переночевать в Зоне.</text> </string> Итак с предметом закончили Приступим к главному. Работа со скриптами Заходим в gamedata\scripts, находим файл bind_stalker.script, открываем его, находим функцию function actor_binder:net_destroy() и в колбеках пишем: self.object:set_callback(callback.use_object, nil) Должно получиться так: function actor_binder:net_destroy() if(actor_stats.remove_from_ranking~=nil)then actor_stats.remove_from_ranking(self.object:id()) end -- game_stats.shutdown () db.del_actor(self.object) sr_light.clean_up () self.object:set_callback(callback.inventory_info, nil) self.object:set_callback(callback.article_info, nil) self.object:set_callback(callback.on_item_take, nil) self.object:set_callback(callback.on_item_drop, nil) --self.object:set_callback(callback.actor_sleep, nil) self.object:set_callback(callback.task_state, nil) self.object:set_callback(callback.level_border_enter, nil) self.object:set_callback(callback.level_border_exit, nil) self.object:set_callback(callback.take_item_from_box, nil) self.object:set_callback(callback.use_object, nil) -- вот наш коллбэк if sr_psy_antenna.psy_antenna then sr_psy_antenna.psy_antenna:destroy() sr_psy_antenna.psy_antenna = false end xr_sound.stop_all_sound_object() object_binder.net_destroy(self) end В этом же файле находим функцию function actor_binder:reinit() и так же в коллбэках пишем self.object:set_callback(callback.use_object, self.use_obj, self) Должно получиться так: function actor_binder:reinit() object_binder.reinit(self) local npc_id = self.object:id() db.storage[npc_id] = { } self.st = db.storage[npc_id] self.st.pstor = nil self.next_restrictors_update_time = -10000 self.object:set_callback(callback.inventory_info, self.info_callback, self) self.object:set_callback(callback.article_info, self.article_callback, self) self.object:set_callback(callback.on_item_take, self.on_item_take, self) self.object:set_callback(callback.on_item_drop, self.on_item_drop, self) self.object:set_callback(callback.trade_sell_buy_item, self.on_trade, self) -- for game stats --self.object:set_callback(callback.actor_sleep, self.sleep_callback, self) self.object:set_callback(callback.task_state, self.task_callback, self) --self.object:set_callback(callback.map_location_added, self.map_location_added_callback, self) self.object:set_callback(callback.level_border_enter, self.level_border_enter, self) self.object:set_callback(callback.level_border_exit, self.level_border_exit, self) self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self) self.object:set_callback(callback.use_object, self.use_obj, self) -- вот наш колбек end Так же в этом файле находим функцию function actor_binder:on_item_drop (obj) и после неё пишем: function actor_binder:use_obj(obj) main_sleep.sleep(obj) end Должно получиться так: ---------------------------------------------------------------------------------------------------------------------- function actor_binder:on_item_drop (obj) level_tasks.proceed(self.object) --game_stats.update_drop_item (obj, self.object) end ---------------------------------------------------------------------------------------------------------------------- function actor_binder:use_obj(obj) -- функция на использование предмета main_sleep.sleep(obj) -- наш будущий скрипт и функция в нем. end ---------------------------------------------------------------------------------------------------------------------- Теперь в gamedata\scripts создаем файл c названием main_sleep.script, открываем его и пишем: function sleep(obj) if obj ~= nil then if obj:section() == "sleep_bag" then -- при использовании спального мешка будет открываться выборочное меню local hud = sleep_ui(get_hud()) -- указываем на class "sleep_ui" (CUIScriptWnd) level.start_stop_menu(hud, true) -- открываем меню end end end class "sleep_ui" (CUIScriptWnd) function sleep_ui:__init(owner) super() self.owner = owner self:InitControls() self:InitCallBacks() end function sleep_ui:__finalize() end function sleep_ui:InitControls() self:Init(50,50,550,450) local xml = CScriptXmlInit() xml:ParseFile("ui_sleep.xml") -- настройки будут воспроизводиться в этом xml файле xml:InitStatic("back_video", self) -- видео сзади xml:InitStatic("background", self) -- рамка сзади self:Register(xml:Init3tButton("caption", self),"caption") -- заголовок self:Register(xml:Init3tButton("btn_1", self),"btn_1") -- кнопка на сон одного часа self:Register(xml:Init3tButton("btn_2", self),"btn_2") -- кнопка на сон трех часов self:Register(xml:Init3tButton("btn_3", self),"btn_3") -- кнопка на сон девяти часов if db.actor.health < 0.9 then -- если здоровье упало, то self:Register(xml:Init3tButton("btn_4", self),"btn_4") -- кнопка на выздоровления end self:Register(xml:Init3tButton("btn_quit", self),"btn_quit") -- кнопка выхода end function sleep_ui:InitCallBacks() self:AddCallback("btn_1", ui_events.BUTTON_CLICKED, self.sleep_ui1, self) -- кнопка один идет на функцию sleep_ui1 self:AddCallback("btn_2", ui_events.BUTTON_CLICKED, self.sleep_ui2, self) -- кнопка два идет на функцию sleep_ui2 self:AddCallback("btn_3", ui_events.BUTTON_CLICKED, self.sleep_ui3, self) -- кнопка три идет на функцию sleep_ui3 if db.actor.health < 0.9 then self:AddCallback("btn_4", ui_events.BUTTON_CLICKED, self.sleep_ui4, self) -- кнопка идет на sleep_ui4 end self:AddCallback("btn_quit", ui_events.BUTTON_CLICKED, self.on_quit, self) -- кнопка идет на выход end function sleep_ui:OnKeyboard(dik, keyboard_action) -- функция на отмену сна при нажатии клавиши Esc CUIScriptWnd.OnKeyboard(self,dik,keyboard_action) if keyboard_action == ui_events.WINDOW_KEY_PRESSED then if dik == DIK_keys.DIK_ESCAPE then self:on_quit() end if dik == DIK_keys.DIK_NUMPAD1 then self:sleep_ui1() end if dik == DIK_keys.DIK_NUMPAD2 then self:sleep_ui2() end if dik == DIK_keys.DIK_NUMPAD3 then self:sleep_ui3() end if dik == DIK_keys.DIK_NUMPAD4 then self:sleep_ui4() end end return true end function sleep_ui:sleep_ui1() -- вот функция от кнопки один main_sleep.sleep_one_hour() -- спим один час self:on_quit() -- выход end function sleep_ui:sleep_ui2() -- вот функция от кнопки два main_sleep.sleep_three_hours() -- спим три часа self:on_quit() end function sleep_ui:sleep_ui3() -- вот функция от кнопки три main_sleep.sleep_nine_hours() -- спим девять часов self:on_quit() end function sleep_ui:sleep_ui4() -- функция от кнопкм четыри main_sleep.sleep_health(scale) -- спим до выздоровления self:on_quit() end function sleep_ui:check_game() -- проверка запущена ли игра local check = false if level.present() and (db.actor ~= nil) and db.actor:alive() then check = true end return check end function sleep_ui:on_quit() -- вот кнопка выхода self:GetHolder():start_stop_menu(self, true) alife():create("sleep_bag", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), db.actor:id()) -- спаун мешка обратно end -- ----------------------------- -- DreamMod v0.1 by Ab@dDon --- -- Edited by Weanchester --- -- ----------------------------- function sleep_one_hour() -- сон один час main_sleep.main(1) end function sleep_three_hours() -- сон три часа main_sleep.main(3) end function sleep_nine_hours() -- сон девять часов main_sleep.main(9) end function sleep_health(scale) -- сон до выздоровления local sleep_time = (1 - db.actor.health)*5.00 main_sleep.main(sleep_time) end function main(scale) -- основная функция basic_time_factor = level.get_time_factor () -- вычисление стандартной скорости течения времени db.actor:stop_talk() -- если игрок с кем-нибудь говорит, диалог закрывается. Здесь в ней нет смысла, но вдруг кому пригодится db.actor:hide_weapon() -- ГГ прячет оружие в рюкзак level.disable_input() -- отключение управления main_sleep.starter (scale) -- запуск скрипта, перематывающего время end function starter(scale) -- скрипт перемотки на нужное время local factor = scale * 2650 -- вычисление времени "пробуждения" game.start_tutorial("time_scaling") -- вызов функции перемотки level.set_time_factor(factor) -- собственно сама перемотка end function dreamer() -- отвечает за сны level.set_time_factor(basic_time_factor) --остановка перемотки. basic_time_factor - стандартная скорость течения времени local dream = dream.sleep_video_name_callback () -- позволяет "показать" сон if dream ~= "" then game.start_tutorial(dream) -- показ одного из трёх снов else game.start_tutorial("without_dream") -- "без сна" end end function stopper() level.add_cam_effector("camera_effects\\dream.anm", 1, false, "") -- эффект подъема db.actor:restore_weapon() -- ГГ достаёт оружие level.enable_input() -- включается управление level.add_pp_effector("yantar_underground_psi.ppe", 222, false, "") -- эффект подъема if db.actor.health <= 0.60 then -- если хп упало меньше 60, то запускается функция съедания еды main_sleep.eat_food() end end function eat_food() -- функция съедания еды if db.actor:eat(db.actor:object("conserva")) ~= nil or db.actor:eat(db.actor:object("bread")) ~= nil or db.actor:eat(db.actor:object("kolbasa")) ~= nil then end end С самым главным работа завершена. Переходим к предпоследнему пункту. Работа с XML-описателем Заходим в gamedata\config\ui, создаем файл с названием ui_sleep.xml, открываем его и пишем: <?xml version="1.0" encoding="windows-1251" ?> <main> <back_video x="10" y="10" width="380" height="320" stretch="1"> <texture>ui\credits_back_512_v10</texture> </back_video> <background x="0" y="0" width="400" height="340" stretch="1"> <texture x="0" y="0" width="350" height="460">ui\ui_dg_inventory</texture> </background> <caption x="175" y="30" width="50" height="35"> <text>Сон</text> </caption> <btn_1 x="72" y="80" width="256" height="35"> <texture_e>ui\ui_btn_mm_e</texture_e> <texture_t>ui\ui_btn_mm_t</texture_t> <texture_h>ui\ui_btn_mm_h</texture_h> <text>Спать 1 час</text> </btn_1> <btn_2 x="72" y="130" width="256" height="35"> <texture_e>ui\ui_btn_mm_e</texture_e> <texture_t>ui\ui_btn_mm_t</texture_t> <texture_h>ui\ui_btn_mm_h</texture_h> <text>Спать 3 часа</text> </btn_2> <btn_3 x="72" y="180" width="256" height="35"> <texture_e>ui\ui_btn_mm_e</texture_e> <texture_t>ui\ui_btn_mm_t</texture_t> <texture_h>ui\ui_btn_mm_h</texture_h> <text>Спать 9 часов</text> </btn_3> <btn_4 x="72" y="230" width="256" height="35"> <texture_e>ui\ui_btn_mm_e</texture_e> <texture_t>ui\ui_btn_mm_t</texture_t> <texture_h>ui\ui_btn_mm_h</texture_h> <text>Спать до восстановления здоровья</text> </btn_4> <btn_quit x="270" y="300" width="117" height="29"> <texture_e>ui_button_ordinary_e</texture_e> <texture_t>ui_button_ordinary_t</texture_t> <texture_h>ui_button_ordinary_h</texture_h> <text>Выход</text> </btn_quit> </main> Итак, кнопки описали. Последний пункт. Сны Заходим в gamedata\config\ui, ищем файл ui_movies, открываем и в самом конце пишем: <Movie-003_Rats_OutPut-010> <play_each_item>1</play_each_item> <global_wnd x="0" y="0" width="1024" height="768"> <auto_static x="0" y="0" width="1024" height="768" stretch="1"> <window_name>back</window_name> <texture>intro\intro_back</texture> </auto_static> </global_wnd> <item type="video"> <sound>characters_voice\scenario\video\dream_rats</sound> <pause_state>on</pause_state> <function_on_stop>main_sleep.stopper</function_on_stop> <video_wnd x="0" y="0" width="1024" height="768" stretch="1"> <texture x="0" y="1" width="512" height="245">sleep\movie-003_rats_output-010</texture> </video_wnd> </item> </Movie-003_Rats_OutPut-010> <esc_sky_01> <play_each_item>1</play_each_item> <global_wnd x="0" y="0" width="1024" height="768"> <auto_static x="0" y="0" width="1024" height="768" stretch="1"> <window_name>back</window_name> <texture>intro\intro_back</texture> </auto_static> </global_wnd> <item type="video"> <sound>characters_voice\human_01\dolg\states\sleep\sleep_1.ogg</sound> <pause_state>on</pause_state> <function_on_stop>main_sleep.stopper</function_on_stop> <video_wnd x="0" y="0" width="1024" height="768" stretch="1"> <texture x="0" y="1" width="512" height="245">sleep\esc_sky_01</texture> </video_wnd> </item> </esc_sky_01> <aes_sky_red> <play_each_item>1</play_each_item> <global_wnd x="0" y="0" width="1024" height="768"> <auto_static x="0" y="0" width="1024" height="768" stretch="1"> <window_name>back</window_name> <texture>intro\intro_back</texture> </auto_static> </global_wnd> <item type="video"> <sound>ambient\air_2.ogg</sound> <pause_state>on</pause_state> <function_on_stop>main_sleep.stopper</function_on_stop> <video_wnd x="0" y="0" width="1024" height="768" stretch="1"> <texture x="0" y="1" width="512" height="245">sleep\aes_sky_red</texture> </video_wnd> </item> </aes_sky_red> <without_dream> <play_each_item>1</play_each_item> <global_wnd x="0" y="0" width="1024" height="768"> <auto_static x="0" y="0" width="1024" height="768" stretch="1"> <window_name>back</window_name> <texture>intro\intro_back</texture> </auto_static> </global_wnd> <item type="video"> <sound>characters_voice\human_01\dolg\states\sleep\sleep_1.ogg</sound> <pause_state>on</pause_state> <function_on_stop>main_sleep.stopper</function_on_stop> <video_wnd x="0" y="0" width="1024" height="768" stretch="1"> <texture x="0" y="1" width="1024" height="768">intro\intro_back</texture> </video_wnd> </item> </without_dream> <time_scaling> <play_each_item>1</play_each_item> <global_wnd x="0" y="0" width="1024" height="768"> <auto_static x="0" y="0" width="1024" height="768" stretch="1"> <window_name>back</window_name> <texture>intro\intro_back</texture> </auto_static> </global_wnd> <item type="video"> <sound>characters_voice\human_01\monolith\states\sleep\sleep_6.ogg</sound> <pause_state>off</pause_state> <can_be_stopped>off</can_be_stopped> <function_on_stop>main_sleep.dreamer</function_on_stop> <video_wnd x="0" y="0" width="1024" height="768" stretch="1"> <texture x="0" y="1" width="1024" height="768">intro\intro_back</texture> </video_wnd> </item> </time_scaling> Теперь зайдем в gamedata\config\misc, найдем файл dream.ltx, откроем его. В начале будет такая конструкция: ;-------------------------------------------------------------------------------- ;--- Regular dreams ------------------------------------------------------------- ;-------------------------------------------------------------------------------- [regular_dream1] dream = sleep\aes_sky_red probability = 10 type = nightmare [regular_dream2] dream = sleep\esc_sky_01 probability = 5 type = normal [regular_dream3] dream = sleep\Movie-003_Rats_OutPut-010 probability = 8 type = happy Удаляем sleep\, чтобы получилось так: ;-------------------------------------------------------------------------------- ;--- Regular dreams ------------------------------------------------------------- ;-------------------------------------------------------------------------------- [regular_dream1] dream = aes_sky_red probability = 10 type = nightmare [regular_dream2] dream = esc_sky_01 probability = 5 type = normal [regular_dream3] dream = Movie-003_Rats_OutPut-010 probability = 8 type = happy Сделали мы это, чтоб игра не вылетала во время сна. Со снами закончили. Заключение Осталось добавить мешок в игру. Для этого заходим в gamedata\scripts, ищем файл escape_dialog.script, открываем его, ищем функцию function give_weapon_to_actor (trader, actor) и после dialogs.relocate_item_section(trader, "wpn_knife", "in") пишем: dialogs.relocate_item_section(trader, "sleep_bag", "in") Должно получиться: function give_weapon_to_actor (trader, actor) dialogs.relocate_item_section(trader, "wpn_pm", "in") dialogs.relocate_item_section(trader, "ammo_9x18_fmj", "in") dialogs.relocate_item_section(trader, "ammo_9x18_fmj", "in") dialogs.relocate_item_section(trader, "wpn_knife", "in") dialogs.relocate_item_section(trader, "sleep_bag", "in") end Спальный мешок заспаунится в инвентаре после согласия отбить Шустрого у бандитов. Примечания Иконка у нас не спального мешка, а костюма бандита. Модель - мешок с песком. Вот, собственно, и все! Можете тестировать! Авторы Статья создана: Weanchester, TuMaN Создал скрипт сна: Ab@dDon Отредактировал статью анонимный граммар-наци. 1 Мой мод. Ссылка на комментарий
Whisper 29 Опубликовано 25 Ноября 2011 Поделиться Опубликовано 25 Ноября 2011 (изменено) Пишу в сокращенной форме(без кода) ибо с диалогами давно отлично справляется утилита из состава ЗП sdk и разбирать xml в ручную стало гораздо меньше необходимости. Плюс урок явно не для совсем начинающих.Допустим, у вас по сценарию есть три ветки(фразы), которые может сказать непись в ответ на вашу стартовую.1. Первый разговор на эту тему вообще2. Первый разговор закончился позитивно и может быть продолжен3. Первый разговор закончился негативно и непись готов вам об этом напомнить и (может быть) вы еще что-то можете поменять(но уже на худших условиях).Напрашивающееся решение состоит в том, чтобы проверить dont_has_info "first_time" в ветке 1 и has_info "positive" и "negative" в 2 и 3. После первого разговора и выдачи инфопорции "first_time" выдаем так же один из 2 возможных инфопорций по результату разговора и дело в шляпе - первая ветка отсечена навсегда, так же как и одна из двух других.Но на самом деле в таком случае произойдет вылет - казалось бы без всякой логики, но в действительности игра предостерегает нас от ошибок избыточности. Ибо инфорпорция "first_time" нам совершенно не нужна - достаточно в первой ветке написать dont_has_info "positive" и dont_has_info "negative"(2 и 3 помечены как раньше). Выдача одной из этих инфопорций автоматически отсечет 2 ветки из 3.Допустим, так же, что в другом случае вам надо, чтобы непись четко решал что-то в вашу пользу при определенном условии и, с какой-то вероятностью, обратном случае тоже(да, именно так). Например, какие-то вопросы скидок, уступок, помощи и т.п. То есть, если вы сделали ему что-то хорошее в прошлом - точно поможет, но может помочь и просто так, по доброте душевной, даже если вы не помогали(ведь вы не враги).То есть у нас 2 ветки1. Положительное решение вопроса2. Отрицательное решение вопросаПроще всего сделать так: поставить has_info "neutral" на вторую ветку. Инфопорция эта будет заранее выдаваться вами в том случае, если вы и правда совершенно нейтральны к неписю - тогда выбор автоматически произойдет из двух вариантов случайно - помочь или нет. Если вы помогали ранее, то инфопорция выдана не будет и сработает только первая ветка.Понятно, это можно и легко обратить - чтобы непись чаще отказывал, а не помогал, если вы раньше никак не общались. Изменено 20 Сентября 2014 пользователем World_Stalker Ссылка на комментарий
Black Hunter 3 Опубликовано 18 Января 2012 Поделиться Опубликовано 18 Января 2012 (изменено) Частенько некоторые начинающие модостроители задаются вопросом. Вот я сделал новую модель сталкера, а как сделать к нему иконку? На этот вопрос я постараюсь дать ответ. Итак как я делаю иконки новым визуалам. Что нам понадобится для создания иконки нового нпс. 1. Adobe Photoshop CS 1, 2, 3 (неважно какая версия, я работаю на версии CS 2)2. Плагин DDS для фотошопа.3. FsCapture4. Stalker Icon Editor5. И собственно скриншот нашего нпс. Начинаем.Сначала заходим в игру. Заходим в опции убираем прицел и распознование нпс. Находим нашего нового нпс (или его можно добавить в повелитель зоны и заспаунить там где хочется) прописываем demo_record 1 и с удобной позиции делаем скриншот. Скриншоты сохраняются по такому пути C:\Documents and Settings\All Users\Документы\STALKER-STCS\screenshots (Это у меня так). Итак идем в эту папку, открываем скриншот нашего нпс и включаем FsCapture. Выбираем захват прямоугольной области и захватываем нужную нам часть. Потом когда захватили нужную часть, сохраняем ее в удобную нам папку. Теперь идем в папку в которую сохранили обрезанный скриншот. Открываем его Adobe Photoshop'ом. Теперь идем в папку где содержится файл с иконками. В папке gamedata это textures/ui/ui_npc_unique. Его тоже открываем фотошопом. Открываем вкладку с нашим обрезанным скриншотом. Вверху нажимаем кнопку "Изображение" потом выбираем размер изображения. Далее выходит окно. В графе Разрешение стираем все цифры и пишем туда 72. В графе где написано "бикубическая" выбираем вместо нее "бикубическую четкую". В верхней графе где написано "ширина" стираем все цифры и пишем 165, а вместо "высоты" пишем 108. Наше изображение уменьшилось, теперь слева на панели выбираем инструмент "Прямоугольная область" и захватываем всю нашу картинку. Нажимаем Ctrl+C и переходим на вкладку с нашими иконками. Нажимаем Ctrl+V, затем Ctrl+T и перетаскиваем нашу новую иконку на место той которую хотим заменить. Поставили? Нажимаем Enter и сохраняем в формате dds c параметром NO MIP MAPS. Вот всё и готово, заходим и любуемся новой иконкой. Если же у вас иконка для уникального нпс, то сохраняем нашу иконку в свободную ячейку, сохраняем открываем программой Stalker Icon Editor(SIE) и находим ее координаты. Координаты находятся так: Нажимаем на новую нашу иконку, потом правой кнопкой мыши и выбираем "Информация о выделении для XML". Там смотрим координаты и записываем в ui_npc_unique.xml в папке configs/ui/textures_descr. Копируем любую строчку называем ее как хотим например было ui_npc_u_nebo_2_face_4, а мы вместо него пишем своё название и вместо цифр которые были ставим наши координаты. Потом заходим в профиль нашего нпс и в графе <Icon> вставляем наше название иконки. Изменено 20 Сентября 2014 пользователем World_Stalker Ссылка на комментарий
Painter 3 373 Опубликовано 7 Февраля 2012 Поделиться Опубликовано 7 Февраля 2012 (изменено) 1. Проверка на то, что ГГ находится в укрытии от выброса: function название_функции() if surge_manager.actor_in_cover() then --действие end end 2. Проверка на то, что ГГ НЕ находится в укрытии от выброса: function название_функции() if not surge_manager.actor_in_cover() then --действие end end 3. Проверка на то, что ГГ жив: function название_функции() if db.actor:alive() then --действие end end 4. Проверка на то, что ГГ мёртв: function название_функции() if not db.actor:alive() then --действие end end 5. Проверка на то, что в данный момент идёт выброс: function название_функции() if surge_manager.is_started() then --действие end end 6. Проверка на то, что в данный момент нет выброса: function название_функции() if surge_manager.is_finished() then --действие end end 7. Проверка на наличие заданного кол-а денег у ГГ: function название_функции() local money = 1000 - заданное кол-во денег if db.actor:money() >= money then --действие end end 8. Проверка на отсутствие заданного кол-а денег у ГГ: function название_функции() local money = 1000 - заданное кол-во денег if db.actor:money() < money then --действие end end 9. Проверка на то, что у ГГ совсем нет денег: function название_функции() if db.actor:money() == 0 then --действие end end 10. Проверка на то, что ГГ имеет при себе какой-либо предмет: function название_функции() if db.actor:object("предмет") ~= nil then --действие end end 11. Проверка на то, что ГГ НЕ имеет при себе какой-либо предмет: function название_функции() if db.actor:object("предмет") == nil then --действие end end Изменено 18 Апреля 2020 пользователем Jurok 2 Портфолио Ссылка на комментарий
GEONЕZIS 20 Опубликовано 11 Февраля 2012 Поделиться Опубликовано 11 Февраля 2012 (изменено) Создание квеста с использованием рестрикторов в Зове ПрипятиАвтор: GEONEZIS Предположим нам необходимо реализовать квест следующего типа: ГГ будет выдано задание на извлечение определенного предмета из физического обьекта на локации. Пусть будет такой вариант: Сыч дает Дягтереву задание на изьятие из старой антенны и генератора на ВНЗ Круг различных деталей. Для осуществления подобных заданий необходимо использовать рестрикторы. Данный тип квестов в корне отличается от простых, когда по заданным меткам необходимо было просто подобрать заспавненные ранее предметы.Необходимые для редактирования файлы:1. конфигурационные в (gamedata\configs\gameplay\)-character_desc_zaton.xml-dialogs_zaton.xml-info_zaton.xml2. конфигурационные в (gamedata\configs\misc\)- tm_zaton.ltx- quest_items.ltx- death_generic.ltx3. конфигурационные в (gamedata\configs\text\rus\)- st_dialogs_zaton.xml- st_quests_zaton.xml- ui_st_screen.xml- st_items_quest.xml4. конфигурационные в (gamedata\configs\ui\)- game_tutorials.xml5. логики рескрипторов в (gamedata\configs\scripts\zaton\)- zat_restr_logic_1.ltx- zat_restr_logic_2.ltx6. скриптовый в (gamedata\scripts\)- dialogs_zaton.script- xr_effects.script- ui_si.script7. Спавн в файле all.spawn (gamedata\spawns\)- alife_zaton.ltxДля начала добавим один общий диалог на выдачу и завершения квеста. (В принципе можно было не усложнять и сделать два простых диалога, но рассмотрим более сложный вариант)В файл dialogs_zaton.xmlв самом низу добавим диалог: <dialog id="zat_b106_stalker_sich_test_quest_dialog"> <dont_has_info>zat_b106_sich_quest_complete</dont_has_info> <phrase_list> <phrase id="0"> <text>zat_b106_stalker_sich_test_quest_dialog_0</text> <next>1</next> <next>2</next> </phrase> <phrase id="1"> <dont_has_info>zat_b106_sich_quest_begin</dont_has_info> <text>zat_b106_stalker_sich_test_quest_dialog_1</text> <next>11</next> <next>12</next> </phrase> <phrase id="12"> <text>zat_b106_stalker_sich_test_quest_dialog_12</text> <action>dialogs.break_dialog</action> </phrase> <phrase id="11"> <text>zat_b106_stalker_sich_test_quest_dialog_11</text> <next>111</next> </phrase> <phrase id="111"> <text>zat_b106_stalker_sich_test_quest_dialog_112</text> <action>dialogs_zaton.zat_b106_sich_give_tasks</action> <give_info>zat_b106_sich_quest_begin</give_info> </phrase> <phrase id="2"> <has_info>zat_b106_sich_quest_begin</has_info> <text>zat_b106_stalker_sich_test_quest_dialog_2</text> <next>3</next> <next>4</next> </phrase> <phrase id="4"> <dont_has_info>zat_b106_sich_quest_restr_2</dont_has_info> <text>zat_b106_stalker_sich_test_quest_dialog_4</text> <action>dialogs.break_dialog</action> </phrase> <phrase id="3"> <has_info>zat_b106_sich_quest_restr_2</has_info> <text>zat_b106_stalker_sich_test_quest_dialog_3</text> <give_info>zat_b106_sich_quest_complete</give_info> <next>331</next> </phrase> <phrase id="331"> <text>zat_b106_stalker_sich_test_quest_dialog_331</text> <next>332</next> </phrase> <phrase id="332"> <text>zat_b106_stalker_sich_test_quest_dialog_332</text> <action>dialogs_zaton.zat_b106_sich_quest_relocate_item</action> <next>333</next> </phrase> <phrase id="333"> <text>zat_b106_stalker_sich_test_quest_dialog_333</text> <action>dialogs_zaton.zat_b106_sich_quest_relocate_reward</action> <next>334</next> </phrase> <phrase id="334"> <text>zat_b106_stalker_sich_test_quest_dialog_334</text> </phrase> </phrase_list> </dialog> Ну и чтобы понимать о чем в диалогах идет речь сразу пропишем русскую транскрипцию фраз в файле st_dialogs_zaton.xml <string id="zat_b106_stalker_sich_test_quest_dialog_0"> <text>Я по поводу работы.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_1"> <text>Работы, хм. Ах да забыл. Есть у меня одно поручение. Нужно сходить на ВНЗ Круг и снять показатели нескольких старых приборов. С одной антенны и старого генератора. Ну что, согласен?</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_11"> <text>Да, сделаю.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_12"> <text>Пока есть другие дела.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_112"> <text>Отлично, жду. Награду достойную получишь.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_2"> <text>Ну что, сделал что я просил?</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_4"> <text>Нет, работаю над этим.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_3"> <text>Да. Все сделано.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_331"> <text>Отлично, давай сюда приборы.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_332"> <text>Забирай.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_333"> <text>Вот твоя награда. Успехов сталкер.</text> </string> <string id="zat_b106_stalker_sich_test_quest_dialog_334"> <text>Бывай.</text> </string> Теперь разберем по порядку то что добавили.Диалог на выдачу и завершение квеста имеет следующую структуру:1.Первая часть диалога на выдачу задания. (ветка <next>1</next>)- ГГ предлагают задание и он на выбор может временно отказаться от него, тогда диалог будет доступен во второй раз. Либо же согласиться на исполение.- Соответсвенно при согласии происходит выдача инфопоршня zat_b106_sich_quest_begin(при старте квеста) и выдача самого квеста через актшион <action>dialogs_zaton.zat_b106_sich_give_tasks</action>.- На этом генерация ветки диалога на выдачу задания будет заблокирована, из-за наличия во фразе 1условия <dont_has_info>zat_b106_sich_quest_begin</dont_has_info>2.Вторая часть диалога доступная уже после взятия задания.- Ее генерация происходит путем активации ветки (<next>2</next>), первая фраза которой будет доступна только полсе старта задания то есть наличия условия <has_info>zat_b106_sich_quest_begin</has_info>- Следующие фразы будут доступны также на выбор (<next>3</next>и <next>4</next>) Фраза 4будет доступна сразу же после взятия квеста- она будет являться закрывающей диалог (акшион <action>dialogs.break_dialog</action>). Генерируется она путем наличия условия <dont_has_info>zat_b106_sich_quest_restr_2</dont_has_info>Эта фраза сообщает о том что ГГ еще не выполнил задание.- Фраза 3которая является веткой завершения диалога будет доступна только при наличии условия <has_info>zat_b106_sich_quest_restr_2</has_info>(этот инфопоршень мы получим в процессе выполнения квеста) при этом фраза 4 будет заблокирована.- в треьей фразе будет происходить выдача условия <give_info>zat_b106_sich_quest_complete</give_info>обеспечивающего завершение квеста и полное блокирование диалога.- также отметим наличие акшионов <action>dialogs_zaton.zat_b106_sich_quest_relocate_item</action>и <action>dialogs_zaton.zat_b106_sich_quest_relocate_reward</action>отвечающих за передачу квестовых предметов и выдачу награды.Объявим используемые инфопоршни в info_zaton.xml. Добавим в конце файла код: .... <info_portion id="zat_b106_sich_quest_complete"></info_portion> <info_portion id="zat_b106_sich_quest_begin"></info_portion> <info_portion id="zat_b106_sich_quest_restr_1"></info_portion> <info_portion id="zat_b106_sich_quest_restr_2"></info_portion> .... Добавим наш диалог НПС (В данном случае Сычу) для этого в файл character_desc_zaton.xmlв его профиль <specific_character id="zat_b30_owl_stalker_trader" team_default="1">добавим строку диалога .... <actor_dialog>zat_b106_stalker_sich_test_quest_dialog</actor_dialog> .... С диалогами и инфопоршнями разобрались теперь добавим необходимые для выполнения квеста предметы, а также файлы связанный с ними.В файл quest_items.ltxпропишем две секции предметов zat_b206_sich_quest_item_1и zat_b206_sich_quest_item_2. Оба предмета являются квестовым- невозможна их продажа и выкладывание из инвентаря [zat_b206_sich_quest_item_1]:device_pda $spawn = "quest_items\zat_b206_sich_quest_item_1" visual = dynamics\equipments\quest\materials_textolite.ogf description = st_zat_b206_sich_quest_item_1_descr inv_name = st_zat_b206_sich_quest_item_1_name inv_name_short = st_zat_b206_sich_quest_item_1_name inv_weight = 0.1 can_trade = false quest_item = true inv_grid_width = 1 inv_grid_height = 1 inv_grid_x = 2 inv_grid_y = 19 [zat_b206_sich_quest_item_2]:device_pda $spawn = "quest_items\zat_b206_sich_quest_item_2" visual = dynamics\equipments\quest\materials_wire.ogf description = st_zat_b206_sich_quest_item_2_descr inv_name = st_zat_b206_sich_quest_item_2_name inv_name_short = st_zat_b206_sich_quest_item_2_name inv_weight = 0.1 can_trade = false quest_item = true inv_grid_width = 1 inv_grid_height = 1 inv_grid_x = 14 inv_grid_y = 19 В файл death_generic.ltxпропишем: (в данном случае также необязательно так как генерации в инвентаре НПС нет) .... zat_b206_sich_quest_item_1 = true zat_b206_sich_quest_item_2 = true .... В файл ui_si.scriptтаблица info_tableдобавим (для спавна, в принципе работать будет и без внесения в этот файл): .... "zat_b206_sich_quest_item_1", "zat_b206_sich_quest_item_2", .... В файл st_items_quest.xmlпропишем дескрипцию предметов. <string id="st_zat_b206_sich_quest_item_1_name"> <text>Первая деталь</text> </string> <string id="st_zat_b206_sich_quest_item_1_descr"> <text>Одна из основных деталей общей схемы в исседовательской антенне.</text> </string> <string id="st_zat_b206_sich_quest_item_2_name"> <text>Вторая деталь</text> </string> <string id="st_zat_b206_sich_quest_item_2_descr"> <text>Одна из компановочных составляющих старого генератора.</text> </string> Квестовые предметы прописали, теперь же добавим рестрикторы используемые в квесте.- Прежде всего создадим сами рестрикторы добавив в файл alife_zaton.ltxраспакованного программой ACDC all.spawn [zaton_1865120] ; cse_abstract properties section_name = space_restrictor name = zat_test_quest_restrictor_1 position = -432.537384048828,11.5833719020996,-46.925877601563 direction = 0,0.841602981090546,0 ; cse_alife_object properties game_vertex_id = 51 distance = 0 level_vertex_id = 131423 object_flags = 0xffffff3e custom_data = <<END [story_object] story_id = zat_restr_1_id [logic] cfg = scripts\zaton\zat_restr_logic_1.ltx END ; cse_shape properties shapes = shape0 shape0:type = box shape0:axis_x = 4,0,0 shape0:axis_y = 0,3.13100147247314,0 shape0:axis_z = 0,0,2 shape0:offset = 0,0,0 ; cse_alife_space_restrictor properties restrictor_type = 3 [zaton_1865121] ; cse_abstract properties section_name = space_restrictor name = zat_test_quest_restrictor_2 position = -391.867065048828,10.9986919020996,-15.951530601563 direction = 0,0.841602981090546,0 ; cse_alife_object properties game_vertex_id = 51 distance = 0 level_vertex_id = 190168 object_flags = 0xffffff3e custom_data = <<END [story_object] story_id = zat_restr_2_id [logic] cfg = scripts\zaton\zat_restr_logic_2.ltx END ; cse_shape properties shapes = shape0 shape0:type = box shape0:axis_x = 4,0,0 shape0:axis_y = 0,3.13100147247314,0 shape0:axis_z = 0,0,2 shape0:offset = 0,0,0 ; cse_alife_space_restrictor properties restrictor_type = 3 - Имена секций рестикторов должны быть уникальны (как собственное имя, так и порядковое внутри алл спавна)- Они должны иметь тип 3- Координаты точки спавна рестикторов должны задаваться рядом с тем обектом на локации который мы будем использовать. (position, level_vertex_id, game_vertex_id)- story_id = zat_restr_2_id- уникальный айди номер рестриктора на который будет выставляться квестовая метка.- shape0- общий тип и размер зоны рестриктора- при изменении числовых значений можно как увеличить, так и уменьшить радиус активной зоны вблизи юзаемого предмета.- cfg = scripts\zaton\zat_restr_logic_2.ltx- путь к файлу логики рестриктора.Теперь пропишем логики рестрикторов. Рассмотрим только одну- вторая создается по образу первой.Создадим файл zat_restr_logic_1.ltxИ пропишем в него следующий код: [logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_b106_sich_quest_begin =actor_in_zone(zat_test_quest_restrictor_1)} sr_idle@tutorial %=run_tutorial(zat_sich_quest_1_tutor)% on_info2 = {+zat_b106_sich_quest_restr_1} sr_idle@nil [sr_idle@tutorial] on_info = {+zat_b106_sich_quest_begin !actor_in_zone(zat_test_quest_restrictor_1)} sr_idle@start %=stop_tutorial% on_info2 = {+zat_b106_sich_quest_restr_1} sr_idle@nil on_info3 = {!has_active_tutorial} sr_idle@start [sr_idle@nil] Опишем что означает эта логика и по какому принципу она строиться:- всего логика имеет три секции это sr_idle@start- она же изначально активная, [sr_idle@tutorial]по исполнению гайм туториала, [sr_idle@nil]- нулевое значение логики.- основной принцип работы это проверка наличия двух условий- это старт квеста (zat_b106_sich_quest_begin) и наличия актора в зоне рестиктора =actor_in_zone(zat_test_quest_restrictor_1)при их соблидение подается команда на старт туториала юзания предмета %=run_tutorial(zat_sich_quest_1_tutor)%- если актор находился в зоне рестиктора, но потом вышел из нее !actor_in_zone(zat_test_quest_restrictor_1)происходит выдача команды на остановку туториала %=stop_tutorial% и возвращение логики в исходное стартовое состоянии. Запуск или остановку туториала можно проследить по активации надписи юзания предмета.- соотвестсвенно в независимости от того какая секция логики активна при выдаче инфопоршня zat_b106_sich_quest_restr_1происходит обнуление логики рестиктора. Дальнейшая работа туториалов в ней будет невозможно.Текст активирущийся при юзании рестриктора буде прописан в ui_st_screen.xml <string id="zat_sich_quest_tips"> <text>Извлечь деталь</text> </string> Сам туториал пропишем в файле game_tutorials.xml <zat_sich_quest_1_tutor> <global_wnd/> <item> <disabled_key>quit</disabled_key> <length_sec/> <action id="use" finalize="1">xr_effects.zat_sich_quest_1</action> <guard_key>use</guard_key> <grab_input>0</grab_input> <main_wnd> <auto_static start_time="0" length_sec="5000" x="512" y="660" width="300" height="60" alignment="c" stretch="1"la_cyclic="1" la_texture="1" la_alpha="1"> <text font="graffiti22" r="225" g="225" b="250" a="255" align="c">zat_sich_quest_tips</text> </auto_static> </main_wnd> </item> </zat_sich_quest_1_tutor> Основные параметры это:- <action id="use" finalize="1">xr_effects.zat_sich_quest_1</action>выполняемое действие по скрипту xr_effects.zat_sich_quest_1- zat_sich_quest_tips- текст сообщения перед юзаниемВ файл xr_effects.scriptпропишем скрипты исполняемые при юзании рескриптора. function zat_sich_quest_1(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_1"}) then db.actor:give_info_portion("zat_b106_sich_quest_restr_1") give_actor(db.actor,nil,{"zat_b206_sich_quest_item_1"}) end end function zat_sich_quest_2(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_2"}) then db.actor:give_info_portion("zat_b106_sich_quest_restr_2") give_actor(db.actor,nil,{"zat_b206_sich_quest_item_2"}) end end -Происходит проверка наличия актора в зоне zat_test_quest_restrictor_1и если оно истинно тогда происходит выдача инфопоршня zat_b106_sich_quest_restr_1и спавн в рюкзак ГГ айтема zat_b206_sich_quest_item_1С созданием рестрикторов и туториалов разобрались. Теперь пропишем остальные скриптовые функции:В файле dialogs_zaton.scriptдобавим следующие функции: function zat_b106_sich_give_tasks(first_speaker, second_speaker) task_manager.get_task_manager():give_task("geonezis_zat_b206_sich_example_task") end function zat_b106_sich_quest_relocate_item(first_speaker, second_speaker) local items_table = { "zat_b206_sich_quest_item_1", "zat_b206_sich_quest_item_2", } for k,v in pairs(items_table) do if db.actor:object(v) ~= nil then dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, v) end end end function zat_b106_sich_quest_relocate_reward(first_speaker, second_speaker) dialogs.relocate_money_to_actor(first_speaker, second_speaker, 5000) end Поясним их:- Выдача квеста- Передача квестовых предметов неписю- Выдача ГГ награды за квестТак и собственно в завершении осталось расписать сам квест:В файл tm_zaton.ltxдобавим код: [geonezis_zat_b206_sich_example_task] icon = ui_inGame2_Zamanchiviy_biznes prior = 1 storyline = false title = {+zat_b106_sich_quest_restr_2} zat_b206_sich_example_title2, {+zat_b106_sich_quest_restr_1 -zat_b106_sich_quest_restr_2} zat_b206_sich_example_title1, {-zat_b106_sich_quest_restr_1} zat_b206_sich_example_title0 descr = {+zat_b106_sich_quest_restr_2} zat_b206_sich_example_text2, {+zat_b106_sich_quest_restr_1 -zat_b106_sich_quest_restr_2} zat_b206_sich_example_text1, {-zat_b106_sich_quest_restr_1} zat_b206_sich_example_text0 target = {+zat_b106_sich_quest_restr_2} zat_b30_owl_stalker_trader_id, {+zat_b106_sich_quest_restr_1 -zat_b106_sich_quest_restr_2} zat_restr_2_id, {-zat_b106_sich_quest_restr_1} zat_restr_1_id condlist_0 = {+zat_b106_sich_quest_complete} complete condlist_1 = {+zat_b106_sich_quest_begin =is_squad_enemy_to_actor(zat_b30_owl_stalker_trader_squad)} fail on_complete = %=inc_faction_goodwill_to_actor(stalker:50)% Пояснения:- квест исполняется в три этапа- сначала мы юзаем рестриктор 1, потом после этого второй и в завершении отдаем полученные предметы заказчику. соответсвенно метки перемещаются с zat_restr_1_idна zat_restr_2_idи в завершении на Сыча zat_b30_owl_stalker_trader_id. При этом же обновляются тайтлы и дескрипшины этапов задания. Основные условия их изменения это выдача или же остутсвие двух основных инфопоршней zat_b106_sich_quest_restr_1(получаемого при юзании первого рестриктора) и zat_b106_sich_quest_restr_2(второго)- задание завершается при выдаче инфопоршня zat_b106_sich_quest_complete- квест будет провален если после его старта НПС заказчика стал враждебен по отношению к ГГ =is_squad_enemy_to_actor(zat_b30_owl_stalker_trader_squad)- по завершению квеста происходит повышение репутации у сталкеров %=inc_faction_goodwill_to_actor(stalker:50)%В файле st_quests_zaton.xmlпропишем тайтлы и дескрипшины квеста: <string id="zat_b206_sich_example_title0"> <text>Задание Сыча: извлеките компонент из старой антенны.</text> </string> <string id="zat_b206_sich_example_text0"> <text>Необходимо отправиться на ВНЗ Круг и извлечь деталь обьекта со старой антенны.</text> </string> <string id="zat_b206_sich_example_title1"> <text>Задание Сыча: извлеките вторую деталь со старого генератора</text> </string> <string id="zat_b206_sich_example_text1"> <text>Заберите вторую необходимую заказчику деталь.</text> </string> <string id="zat_b206_sich_example_title2"> <text>Задание Сыча: отдайте заказчику найденные детали.</text> </string> <string id="zat_b206_sich_example_text2"> <text>Передайте все старые детали и компоненты Сычу.</text> </string> На этом урок добавления подобного класса заданий завершен.Файл с отработанным заданием можно скачать тут: http://narod.ru/disk/40325310001/example_q...ezis_2.rar.html Изменено 20 Сентября 2014 пользователем World_Stalker 1 2 - автор модов GA for SGM 1.7, серия "Смерти вопреки".- автор уроков квестостроения на X-Ray 1.6- работал в командах SGM, Spectrum Project (Путь во Мгле). Ссылка на комментарий
MIDERY 0 Опубликовано 20 Февраля 2012 Поделиться Опубликовано 20 Февраля 2012 (изменено) Лёгкий спавн трупа NPC (без функций АМК) Пишем вот такую простенькую функцию: function [имя функции]() local obj= alife():create("имя секции в spawn_sections.ltx",vector():set(x,y,z),level_vertex,game_vertex) obj:on_death() endНа примере - Ученый, близ упавшего вертолета, на армейских складах:function tester() local obj= alife():create("yan_ecolog_respawn_1",vector():set(-38.981,-17.916,355.841),273797,1816) obj:on_death() end Изменено 19 Сентября 2014 пользователем World_Stalker Ссылка на комментарий
Это популярное сообщение. ColR_iT 171 Опубликовано 17 Марта 2012 Это популярное сообщение. Поделиться Опубликовано 17 Марта 2012 (изменено) Переключаем музыку в работающем радио. Как именно, спавнить радио описано в этой же теме несколькими постами выше. Единственное, чтобы я посоветовал, это в принципе для схемы ph_sound использовать объекты с именем секции неphysic_object, а physic_destroyable_object, по одной простои причине - схема on_hit не работает с physic_object. Итак. Самым важным в этом небольшом туторе, как Вы уже сами могли догадаться, будет логика для нашего радио. Логику из секции спавна, лично я, вынес в отдельный файл, а именно logic_switch_radio.ltx. Выглядит она следующим образом: [logic] active = ph_sound@music_1 [ph_sound@music_1] tips = radio_switch snd = radio_music looped = true max_idle = 1000 on_use = ph_sound@music_2 [ph_sound@music_2] tips = radio_switch snd = radio looped = true max_idle = 1000 on_use = ph_sound@music_1 Логика здесь довольно проста. "Изюминка" в том, что мелодии можно переключать, т.е. подойдя к радио и нажав кнопку действия (по умолчанию F), логика перейдёт на следующую схему, тем самым меняя композицию.В том виде в котором данная логика приведена, она естественно работать не будет, поскольку, для схемы ph_sound не предусмотрен колбек на использование (юзание) предмета. Но дело это поправимо... Для этого мы просто напросто добавим его в нашу схему. Изобретать велосипед мы не будем, поэтому колбек мы скопируем из схемы ph_idle (ph_idle.script), там он есть, и впишем в схему ph_sound(ph_sound.script).Открываем файл ph_idle.script и ищем следующую функцию: function action_idle:use_callback(obj, actor) if self.st.on_use then if xr_logic.switch_to_section(self.object, self.st, xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.on_use.condlist)) then return true end end end Это и есть непосредственно сам колбек. Также нас интересует строка в функции set_scheme, а именно (в дополнение к этому, рекомендую также скопировать ещё две строчки, которые обеспечат нас текстовой подсказкой при наведении на радио): st.on_use = xr_logic.cfg_get_condlist(ini, section, "on_use", npc) st.tips = utils.cfg_get_string(ini, section, "tips", npc, false, "", "") npc:set_tip_text(st.tips) Теперь вставляем всё это в аналогичные места в файле ph_sound.script, т.е.: Перед функцией snd_source:update(delta), вставляем колбек, предварительно изменив класс, т.е. буквы action_idle заменяем на snd_source, должно получится так: function snd_source:use_callback(obj, actor) if self.st.on_use then if xr_logic.switch_to_section(self.object, self.st, xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.on_use.condlist)) then return true end end end Затем в функцию set_scheme, в самый её конец, вписываем скопированные строки из аналогичной функции "соседнего" файла. В итоге мы имеем для схемы ph_sound два дополнительных параметра:on_use - колбек на юзание;tips - подсказка при наведении. Кстати, текст для подсказки, можно вписать в файл config\text\rus\string_table_ui.xml по аналогии с имеющимися, в рассматриваемом примере он выгляди так: HTML <string id="radio_switch"><text>Переключить песню ($$ACTION_USE$$)</text></string> Собственно, всё. Кодовый тайник. Как многим известно в ТЧ есть возможность открывать двери при помощи нужного кода, вводя его на клавиатурной панели. Собственно эта самая панель и является ключевым элементом, самый интересный из которых набор кода. Отвечает за это действо схема ph_code (ph_code.script). При вводе пароля выдаётся инфопоршень, а в логике двери есть условие на наличие данного инфопоршня, при котором дверь откроется.Для тайников используется схема ph_idle, а для схемы ph_code как такового, перехода на другую схему нет.Т.е. вся загвоздка состоит в возможности перехода со схемы ph_code на другую.Ну что же давайте добавим эту возможность...Переход будем осуществлять непосредственно в параметре on_code, т.е. при вводе правильного пароля будет происходить переход на другую схему, при которой появится возможность использовать тайник по назначению.За работу параметра on_code отвечает метод OnNumberReceive, а именно вот эта проверка: if self.st.on_code then printf("ph_code <OnNumberReceive>: on_code [%s]", text) xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.on_code.condlist) end Чтобы для данного параметра была возможность перехода на другую схему, эту проверку нужно заменить вот этой: if self.st.on_code ~= nil then printf("ph_code <OnNumberReceive>: on_code [%s]", text) --<# Возможность перехода на другую схему при правильном вводе пароля (on_code). local section = xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.on_code.condlist) xr_logic.switch_to_section(self.object, self.st,section) return true --#> end Вот таким не хитрым способом добавляется возможность использовать схему ph_code для более широкого спектра действий.Теперь приступим непосредственно к тайнику. Для примера я взял синий ящик, который стоит у забора в Деревне новичков.Слегка изменил его секцию спавна: [2297] ; cse_abstract properties section_name = inventory_box name = level_prefix_inventory_box position = -212.106658935547,-20.0091133117676,-141.916839599609 direction = -0.0120084341615438,1.90779304504395,-0.0344137884676456 ; cse_alife_object properties game_vertex_id = 0 distance = 0 level_vertex_id = 594270 object_flags = 0xffffff3b custom_data = <<END [spawn] wpn_pm ammo_9x18_fmj [logic] cfg = scripts\coded_treasure.ltx END story_id = 2000 ; cse_visual properties visual_name = physics\equipment_cache\equipment_box_01_case Изменения коснулись лишь добавлением для него custom_data. (Секция spawn была добавлена для демонстрации). Логика выглядит следующим образом: [logic] active = ph_code@close [ph_code@close] code = 123 on_code = ph_idle@enable [ph_idle@enable] nonscript_usable = true tips = st_search_treasure Собственно всё. При вводе пароля "123" мы получим открытый тайник.Вот небольшое видео для демонстрации: Изменено 24 Сентября 2014 пользователем BFG 2 3 3 Ссылка на комментарий
proper70 74 Опубликовано 3 Мая 2012 Поделиться Опубликовано 3 Мая 2012 (изменено) В файле spawn_sections.ltx пишем конфиг тайника: [s_inventory_box7]:kostya_box -- в квадратных скобках уникальная секция тайника visual = equipments\item_rukzak radius = 1 custom_data = scripts\s_inventory_box7.ltx -- файл с наполнением тайника Файл s_inventory_box7.ltx содержит следующее: [spawn] mutant_gigant_cocoon = 1 mutant_poltergeist_cocoon = 1 af_armor_3 = 3 strelok_taynik_pda30 То есть, в тайнике будут лежать указанные в этом файле предметы: пара эмбрионов монстров, 3 артефакта Панцирь и ПДА. Теперь, если мы после спавна этого тайника хотим туда еще что-то добавить в зависимости от диалога, прохождения и прочего, то мы можем это сделать с помощью следующего скрипта: -- спавним наш тайник local obj = alife():create("s_inventory_box7",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id()) -- в нужном нам месте вызываем функцию спавна дополнительного хабара в тайник: function dospavn(section, obj) alife():create(section,vector():set(0,0,0),0,0,obj.id) end В функцию передается секция предмета и ссылка на тайник, полученная с помощью команды создания тайника alife():create(). Координаты тайника не нужны. Когда в функции alife():create() задан последний параметр, так называемый parent или родитель создаваемого объекта, то координаты игнорируются - новый предмет будет в рюкзаке. local obj = alife():create("esc_stalker_respawn_1",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id()) local tbl = amk.read_stalker_params(obj) tbl.health = 0.1 tbl.updhealth = 0.05 amk.write_stalker_params(tbl, obj) В результате выполнения этого кода рядом с ГГ появится раненый сталкер и будет просить аптечку. Для использования этого кода нужны функции АМК. Изменено 20 Сентября 2014 пользователем World_Stalker 1 1 Ссылка на комментарий
Akella-96 aka SvD 35 Опубликовано 20 Мая 2012 Поделиться Опубликовано 20 Мая 2012 (изменено) Вывод сообщения о малом ХП (рабочая функция)Автор статьи - Akella-96 aka SvDВсем привет, помню на Сталкер - Вики была статья про это, но насколько я знаю, она не рабочая. Сегодня я попробовал разобраться в структуре этой функции, но ни чего не понял. Вскоре я создал рабочую функцию на основе уже существующей - вывод сообщения при большой радиацииИтак, начнем : Сперва находим в gamedata\scripts\bind_stalker.script вот эту функцию --[[ --' Вывод сообщения о большой радиации if self.object.radiation >= 0.7 then local hud = get_hud() local custom_static = hud:GetCustomStatic("cs_radiation_danger") if custom_static == nil then hud:AddCustomStatic("cs_radiation_danger", true) hud:GetCustomStatic("cs_radiation_danger"):wnd():TextControl():SetTextST("st_radiation_danger") end else local hud = get_hud() local custom_static = hud:GetCustomStatic("cs_radiation_danger") if custom_static ~= nil then hud:RemoveCustomStatic("cs_radiation_danger") end end ]]-- И после неё пишем ----------------------------------------------------------------------------------------------------------- --' Вывод сообщения о малом ХП автор - Akella-96 aka SvD if self.object.health <= 0.3 then local hud = get_hud() local custom_static = hud:GetCustomStatic("cs_health_danger") if custom_static == nil then hud:AddCustomStatic("cs_health_danger", true) hud:GetCustomStatic("cs_health_danger"):wnd():TextControl():SetTextST("st_health_danger") end else local hud = get_hud() local custom_static = hud:GetCustomStatic("cs_health_danger") if custom_static ~= nil then hud:RemoveCustomStatic("cs_health_danger") end end ---------------------------------------------------------------------------------------------------------- Потом идем в gamedata\configs\ui\ui_custom_msgs.xml и в самом начале пишем <cs_health_danger x="262" y="50" width="500" height="20" complex_mode="1"> <text font="graffiti22" r="255" g="0" b="0" a="255" align="c"/> </cs_health_danger> Далее идем в gamedata\configs\text\rus\ui_st_screen.xml в самый конец, перед </string_table> добавляем <string id="st_health_danger"> <text>У вас мало здоровья! Примите аптечку!</text> </string> Все. Теперь при состоянии здоровья, меньшего 30% будет выводиться сообщение. Изменено 21 Сентября 2014 пользователем World_Stalker 3 AWRP : Re - Load 0.2 © Ссылка на комментарий
GEONЕZIS 20 Опубликовано 24 Мая 2012 Поделиться Опубликовано 24 Мая 2012 (изменено) Создание многоэтапного квеста на последовательный поиск предметов. Реализация на X-Ray 1.6Автор урока: GEONEZIS Поставленная задача состоит в обучения принципам построения сложных многоходовых заданий на чистой игре Сталкер Зов Припяти. Будет показан процесс построения сложного диалога с ветвлением, последовательный спавн квестовых предметов через скрипт и собственно структура многоуровнего квеста.Задание следующее. Новиков просит ГГ принести для него разбросанные по локации сканеры аномалий. Квест будет построен таким образом что необходим исключительно поэтапный вариант его прохождения, то есть от одной точки к другой, без каких-либо вариантов. Получить один предмет раньше другого не будет предоставляться возможным.Необходимые для редактирования файлы:1. конфигурационные в (gamedata\configs\gameplay\)-character_desc_jupiter.xml-dialogs_jupiter.xml-info_jupiter.xml2. конфигурационные в (gamedata\configs\misc\)- tm_jupiter.ltx- quest_items.ltx- death_generic.ltx3. конфигурационные в (gamedata\configs\text\rus\)- st_dialogs_jupiter.xml- st_quests_jupiter.xml- st_items_quest.xml4. конфигурационные в (gamedata\configs\misc\trade\)- trade_generic.ltx5. скриптовый в (gamedata\scripts\)- dialogs_jupiter.script- ui_si.script- bind_stalker.script- new_tasks.scriptРассмотрим структуру квестовых диалогов. Для этого откроем dialogs_jupiter.xmlи в самом низу добавим два диалога. Один активный при старте задания. Второй на завершение. В принципе можно было объединить их в один, но рассмотрим более легкий вариант. Однока при этом внесем разнообразие в процесс выдачи задания предоставив несколько вариантов его получения внутри диалога. Этот несколько освежит стандартные методы диалогостроения, когда все они делаются последовательными, без каких-либо вариантов.1- ый диалог:<dialog id="jup_b6_scientist_tech_quest_anomalies_scaner"> <dont_has_info>jup_novikov_quest_zaton_scanner_start</dont_has_info> <phrase_list> <phrase id="0"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_0</text> <next>1</next> </phrase> <phrase id="1"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_1</text> <next>2</next> </phrase> <phrase id="2"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_2</text> <action>dialogs_jupiter.jup_b6_create_first_scaner</action> <next>3</next> </phrase> <phrase id="3"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_3</text> <next>4</next> <next>5</next> <next>6</next> </phrase> <phrase id="4"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4</text> <next>41</next> </phrase> <phrase id="41"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_41</text> <next>401</next> <next>402</next> </phrase> <phrase id="401"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_401</text> <next>4011</next> </phrase> <phrase id="4011"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4011</text> <next>4012</next> </phrase> <phrase id="4012"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4012</text> <next>4013</next> <action>dialogs_jupiter.give_novikov_zaton_scaner_quest</action> </phrase> <phrase id="4013"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4013</text> <give_info>jup_novikov_quest_zaton_scanner_start</give_info> </phrase> <phrase id="402"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_402</text> <next>4021</next> </phrase> <phrase id="4021"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4021</text> <next>4022</next> </phrase> <phrase id="4022"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4022</text> <next>4023</next> <action>dialogs_jupiter.give_novikov_zaton_scaner_quest</action> </phrase> <phrase id="4023"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_4023</text> <give_info>jup_novikov_quest_zaton_scanner_start</give_info> </phrase> <phrase id="5"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_5</text> <next>51</next> </phrase> <phrase id="51"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_51</text> <next>52</next> </phrase> <phrase id="52"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_52</text> <next>53</next> </phrase> <phrase id="53"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_53</text> <action>dialogs_jupiter.jup_b6_to_actor_give_spez_outfit</action> <next>531</next> <next>532</next> </phrase> <phrase id="531"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_531</text> <next>5312</next> </phrase> <phrase id="5312"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_5312</text> <next>5313</next> <action>dialogs_jupiter.give_novikov_zaton_scaner_quest</action> </phrase> <phrase id="5313"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_5313</text> <give_info>jup_novikov_quest_zaton_scanner_start</give_info> </phrase> <phrase id="532"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_532</text> <next>5321</next> <action>dialogs_jupiter.give_novikov_zaton_scaner_quest</action> </phrase> <phrase id="5321"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_5321</text> <give_info>jup_novikov_quest_zaton_scanner_start</give_info> </phrase> <phrase id="6"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_6</text> <next>61</next> </phrase> <phrase id="61"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_61</text> <next>611</next> </phrase> <phrase id="611"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_611</text> <action>dialogs_jupiter.give_novikov_zaton_scaner_quest</action> <next>6111</next> </phrase> <phrase id="6111"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_6111</text> <give_info>jup_novikov_quest_zaton_scanner_start</give_info> </phrase> </phrase_list> </dialog> 2-ой диалог:<dialog id="jup_b6_scientist_tech_quest_anomalies_scaner_end"> <has_info>jup_novikov_quest_zaton_scanner_have_6</has_info> <dont_has_info>jup_novikov_quest_zaton_scanner_end</dont_has_info> <precondition>dialogs_jupiter.actot_have_all_zaton_scaner</precondition> <phrase_list> <phrase id="0"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_end_0</text> <action>dialogs_jupiter.actot_to_novikov_give_zaton_scaner</action> <next>1</next> </phrase> <phrase id="1"> <text>jup_b6_scientist_tech_quest_anomalies_scaner_end_1</text> <give_info>jup_novikov_quest_zaton_scanner_end</give_info> </phrase> </phrase_list> </dialog> Сразу же пропишем русскую транскрипцию в st_dialogs_jupiter.xmlдля того чтобы понимать о чем в диалоге идет речь :<string id="jup_b6_scientist_tech_quest_anomalies_scaner_0"> <text>Приветствую, хотел бы оказал вам максимально возможное содействие. Какого рода помощь тебе необходима?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_1"> <text>В принципе есть одно небольшое дело, главное это твое желание работать.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_2"> <text>Я готов.Что нужно делать?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_3"> <text>Прекрасно. Правда придется немного побегать. Мне необходимо получить кое-какие данные.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4"> <text>Замеры? Необходимо будет устанавливать какие-нибудь сканеры?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_41"> <text>Нет, устанавливать не придется. Их уже установили. Тебе же наоборот придется их собрать и доставить сюда, чтобы я смог получить с них результаты замеров.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_401"> <text>Что за сканеры-то? Аномальная активность?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4011"> <text>Обыкновенные сканеры аномалий. Их показатели результатов замеров будут мне необходимы для проведения настройки моего оборудования.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4012"> <text>Все ясно. Придется взять научный комбез. Передавай координаты.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4013"> <text>Уже загрузил. Комбез это хорошая тема. Обязательно возьми. И смотри не сварись в аномалиях.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_402"> <text>Кто их устанавливал и куда мне придется отправиться?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4021"> <text>Тебе то не все-равно, кто их размещал. Пару дней назад, сталкеры из Свободы - сойдет такой ответ? Не о том думаешь. Твоя задача отправиться на Затон, пробежаться по точкам и вернуться назад живым вместе со сканерами. Все ясно?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4022"> <text>Все. Передавай координаты.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_4023"> <text>Уже загрузил. Комбез научный только одень. И смотри не сварись в аномалиях.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5"> <text>А может еще что нужно?</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_51"> <text>Нет, хотя может быть потом я подберу для тебя работку. Но сначала ты должен будешь добыть результаты измерений с установленных на Затоне сканеров аномалий.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_52"> <text>Искать сканеры в аномалиях. Ха, веселая преспектива. Без специального научного костюма мне там долго не пролазить...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_53"> <text>Намек понял. Вот держи ССП-99. Неплохой костюм, хотя и поношенный. Координаты сканеров я тебе загрузил.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_531"> <text>Хотя бы кровь с костюма отмыли? По-любому с трупака какого-нибудь своего ботанического дружка сняли...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5311"> <text>Ой, ну давай мне не заливай..Тоже мне брезгливый нашелся. У самого-то, чай не первой свежести костюмчик..</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5312"> <text>Проехали Кулибин. Все, я отправляюсь за замерами...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5313"> <text>Поосторожнее там...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_532"> <text>Все понял, отправляюсь.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_5321"> <text>Поосторожнее там...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_6"> <text>Хорошо, я сделаю то что нужно. Говори с чего начинать.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_61"> <text>Вот это деловой разговор, делового человека. Вообщем план таков. Сначала ты находишь на Затоне сканеры аномалий, установленные там нашими сподручными сталкерами. Координаты я тебе уже сбросил. Потом, я может быть посмотрю еще что для тебя..</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_611"> <text>Все ясно, Кулибин. Жди, я за твоими сканерами.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_6111"> <text>Поосторожнее там. В аномалиях не сгинь...</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_end_0"> <text>Вот все твои сканеры.</text> </string> <string id="jup_b6_scientist_tech_quest_anomalies_scaner_end_1"> <text>Отличная работа. Немедленно начинаю работу над обработкой результатов замеров. Новую работу получишь позже. А пока гуляй.</text> </string> Теперь разберем структуру представленных диалогов:- Во втором диалоге нет ничего сложного: активен при наличие инфопоршня jup_novikov_quest_zaton_scanner_have_6, исчезает после выдачи jup_novikov_quest_zaton_scanner_end, имеет прекондишн actot_have_all_zaton_scanerкогда в инвенторе ГГ наличие всех квестовых предметов. содержит один акшион actot_to_novikov_give_zaton_scanerна передачу предметов заказчику.- первый диалог сложнее. основная особенность это вложенная тройная разветвленность, когда можно выбрав одну из трех веток получить один и тот же результат.- внутри каждой из веток также имеет место дополнительные ответвления.- старт задания происходит по выдачи акшиона give_novikov_zaton_scaner_questсопровождается также выдачей инфопоршня jup_novikov_quest_zaton_scanner_start- создание первого квестового предмета происходит также внутри диалога- акшионjup_b6_create_first_scaner- чисто для атмосферности происходит выдача ГГ костюма для выполнения задания при выборе одной из трех веток.это акшион jup_b6_to_actor_give_spez_outfitОбъявим используемые инфопоршни в info_jupiter.xml. Добавим в конце файла код:<!--New Quests--> <info_portion id="jup_novikov_quest_zaton_scanner_start"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_end"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_1"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_create_2"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_2"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_create_3"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_3"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_create_4"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_4"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_create_5"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_5"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_create_6"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_6"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_create_7"></info_portion> <info_portion id="jup_novikov_quest_zaton_scanner_have_7"></info_portion> Добавим наши диалоги НПС (В данном случае Новикову) для этого в файл character_desc_jupiter.xmlв его профиль <specific_character id="jup_b6_scientist_tech" team_default="1">добавим строки диалогов..... <actor_dialog>jup_b6_scientist_tech_quest_anomalies_scaner</actor_dialog> <actor_dialog>jup_b6_scientist_tech_quest_anomalies_scaner_end</actor_dialog> ..... С диалогами и инфопоршнями разобрались теперь добавим необходимые для выполнения квеста предметы.В файл quest_items.ltxпропишем семь секций предметов zat_spec_anomaly_scanner_№. Все предметы являются квестовыми- невозможна их продажа и выкладывание из инвентаря ГГ.[zat_spec_anomaly_scanner_1]:device_pda $spawn = "quest_items\zat_spec_anomaly_scanner_1" description = zat_spec_anomaly_scanner_1_descr inv_name = zat_spec_anomaly_scanner_1_name visual = dynamics\equipments\quest\scanner_anomaly.ogf inv_weight = 2 story_id = zat_spec_anomaly_scanner_1 can_trade = false quest_item = true inv_grid_width = 1 inv_grid_height = 2 inv_grid_x = 10 inv_grid_y = 23 В файл death_generic.ltxпропишем: (в данном случае также необязательно так как генерации в инвентаре НПС нет)....... zat_spec_anomaly_scanner_1 = true zat_spec_anomaly_scanner_2 = true zat_spec_anomaly_scanner_3 = true zat_spec_anomaly_scanner_4 = true zat_spec_anomaly_scanner_5 = true zat_spec_anomaly_scanner_6 = true zat_spec_anomaly_scanner_7 = true ..... В файл ui_si.scriptв таблицу info_tableдобавим (для спавна, в принципе работать будет и без внесения в этот файл):........ "zat_spec_anomaly_scanner_1" "zat_spec_anomaly_scanner_2" "zat_spec_anomaly_scanner_3" "zat_spec_anomaly_scanner_4" "zat_spec_anomaly_scanner_5" "zat_spec_anomaly_scanner_6" "zat_spec_anomaly_scanner_7" ........ В файл st_items_quest.xmlпропишем дескрипцию предметов.<string id="zat_spec_anomaly_scanner_1_name"> <text>«Сканер грави-химического симбионта»</text> </string> <string id="zat_spec_anomaly_scanner_1_descr"> <text>«Специализированный сканер аномальной активности из серии 32.1351. Используется учеными для изучения процессов происходящих в грави-химическом симбионте»</text> </string> <string id="zat_spec_anomaly_scanner_2_name"> <text>«Сканер химической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_2_descr"> <text>«Специализированный сканер аномальной активности из серии 27.7724. Используется учеными для изучения процессов происходящих в химической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_3_name"> <text>«Сканер гравитационной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_3_descr"> <text>«Специализированный сканер аномальной активности из серии 78.9835. Используется учеными для изучения процессов происходящих в гравитационной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_4_name"> <text>«Сканер термальной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_4_descr"> <text>«Специализированный сканер аномальной активности из серии 47.3246. Используется учеными для изучения процессов происходящих в термальной аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_5_name"> <text>«Сканер пси-статической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_5_descr"> <text>«Специализированный сканер аномальной активности из серии 06.8912. Используется учеными для изучения процессов происходящих в пси-статической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_6_name"> <text>«Сканер термального симбионта»</text> </string> <string id="zat_spec_anomaly_scanner_6_descr"> <text>«Специализированный сканер аномальной активности из серии 35.0205. Используется учеными для изучения процессов происходящих в термальном симбионте»</text> </string> <string id="zat_spec_anomaly_scanner_7_name"> <text>«Сканер электро-статической аномалии»</text> </string> <string id="zat_spec_anomaly_scanner_7_descr"> <text>«Специализированный сканер аномальной активности из серии 03.1392. Используется учеными для изучения процессов происходящих в электро-статической аномалии»</text> </string> В файле trade_generic.ltxпропишем торговлю. также нужно добавлять индивидуально во все остальные файлы конфигов торговли. (но не обязательно)..... zat_spec_anomaly_scanner_1 ;NO TRADE zat_spec_anomaly_scanner_2 ;NO TRADE zat_spec_anomaly_scanner_3 ;NO TRADE zat_spec_anomaly_scanner_4 ;NO TRADE zat_spec_anomaly_scanner_5 ;NO TRADE zat_spec_anomaly_scanner_6 ;NO TRADE zat_spec_anomaly_scanner_7 ;NO TRADE ...... С квестовыми предметами также разобрались, теперь необходимо разобраться со скриптами квеста. Собственно теперь мы и подходим к основной сути нашего урока, в этом этапе заключен его основной смысл. В файле dialogs_jupiter.scriptдобавим следующие функции:function jup_b6_create_first_scaner(first_speaker, second_speaker) alife():create("zat_spec_anomaly_scanner_1",vector():set(-436.574,-6.527,170.169),116113,16) end function jup_b6_to_actor_give_spez_outfit(first_speaker, second_speaker) dialogs.relocate_item_section_to_actor(first_speaker, second_speaker, "scientific_outfit") end function give_novikov_zaton_scaner_quest() task_manager.get_task_manager():give_task("geonezis_jup_spec_scaner") end function actot_to_novikov_give_zaton_scaner(first_speaker, second_speaker) local items_table = {"zat_spec_anomaly_scanner_1","zat_spec_anomaly_scanner_2","zat_spec_anomaly_scanner_3","zat_spec_anomaly_scanner_4","zat_spec_anomaly_scann er_5","zat_spec_anomaly_scanner_6","zat_spec_anomaly_scanner_7"} for k,v in pairs(items_table) do if db.actor:object(v) ~= nil then dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, v) end end end function actot_have_all_zaton_scaner(first_speaker, second_speaker) return db.actor:object("zat_spec_anomaly_scanner_1")~=nil and db.actor:object("zat_spec_anomaly_scanner_2")~=nil and db.actor:object("zat_spec_anomaly_scanner_3")~=nil and db.actor:object("zat_spec_anomaly_scanner_4")~=nil and db.actor:object("zat_spec_anomaly_scanner_5")~=nil and db.actor:object("zat_spec_anomaly_scanner_6")~=nil and db.actor:object("zat_spec_anomaly_scanner_7")~=nil end коротко их поясним:- спавн первого квестового предмета- передача бронекостюма ГГ- выдача задания- передача всех квестовых предметов НПС- скрипт проверки наличия в инвенторе ГГ всех необходимых предметовТеперь создадим файл new_tasks.scriptи добавим в него следующий код одной основной функции task_spec():--/Квест:Сканеры аномалий function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("jup_novikov_quest_zaton_scanner_start") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_1")) and db.actor:object("zat_spec_anomaly_scanner_1") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_1") end if has_alife_info("jup_novikov_quest_zaton_scanner_have_1") and (not has_alife_info("jup_novikov_quest_zaton_scanner_create_2")) then alife():create("zat_spec_anomaly_scanner_2",vector():set(-304.058,12.450,-159.233),339472,21) db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_create_2") end if has_alife_info("jup_novikov_quest_zaton_scanner_create_2") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_2")) and db.actor:object("zat_spec_anomaly_scanner_2") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_2") end if has_alife_info("jup_novikov_quest_zaton_scanner_have_2") and (not has_alife_info("jup_novikov_quest_zaton_scanner_create_3")) then alife():create("zat_spec_anomaly_scanner_3",vector():set(-68.024,1.398,-164.391),807200,235) db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_create_3") end if has_alife_info("jup_novikov_quest_zaton_scanner_create_3") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_3")) and db.actor:object("zat_spec_anomaly_scanner_3") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_3") end if has_alife_info("jup_novikov_quest_zaton_scanner_have_3") and (not has_alife_info("jup_novikov_quest_zaton_scanner_create_4")) then alife():create("zat_spec_anomaly_scanner_4",vector():set(10.842,8.966,-394.252),964903,8) db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_create_4") end if has_alife_info("jup_novikov_quest_zaton_scanner_create_4") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_4")) and db.actor:object("zat_spec_anomaly_scanner_4") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_4") end if has_alife_info("jup_novikov_quest_zaton_scanner_have_4") and (not has_alife_info("jup_novikov_quest_zaton_scanner_create_5")) then alife():create("zat_spec_anomaly_scanner_5",vector():set(272.490,11.985,-289.525),1431789,43) db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_create_5") end if has_alife_info("jup_novikov_quest_zaton_scanner_create_5") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_5")) and db.actor:object("zat_spec_anomaly_scanner_5") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_5") end if has_alife_info("jup_novikov_quest_zaton_scanner_have_5") and (not has_alife_info("jup_novikov_quest_zaton_scanner_create_6")) then alife():create("zat_spec_anomaly_scanner_6",vector():set(400.209,-0.202,439.740),1630730,242) db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_create_6") end if has_alife_info("jup_novikov_quest_zaton_scanner_create_6") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_6")) and db.actor:object("zat_spec_anomaly_scanner_6") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_6") end if has_alife_info("jup_novikov_quest_zaton_scanner_have_6") and (not has_alife_info("jup_novikov_quest_zaton_scanner_create_7")) then alife():create("zat_spec_anomaly_scanner_7",vector():set(-347.855,40.160,-383.796),259035,29) db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_create_7") end if has_alife_info("jup_novikov_quest_zaton_scanner_create_7") and (not has_alife_info("jup_novikov_quest_zaton_scanner_have_7")) and db.actor:object("zat_spec_anomaly_scanner_7") then db.actor:give_info_portion("jup_novikov_quest_zaton_scanner_have_7") end end end Основная особенность скрипта это последовательный спавн квестовых предметов. Последующий будет создаваться только после того как был найден предыдущий. Также происходит выдача инфопоршней используемых в структуре самого квеста. Еще одна особенность это установка дополнительной проверки в зависимости от локации.Созданный нами скрипт необходимо обьявить в функции апдейта актора actor_binder:update(delta)в файле bind_stalker.script..... new_tasks.task_spec() ..... Теперь собственно перейдем к созданию самого задания.Код секции квеста ([geonezis_jup_spec_scaner]) можно просмотреть в файле tm_jupiter.ltxв архиве с отработанным примером.Основные особенности это наличие двух кондишинов один на завершение задания, второй на его провал (в случае если сквад ученых бункера станет врагами по отношению к ГГ). По завершению задания будет повышена репутация у группировки экологов, а также выдана награда.Структура квеста последовательная. Одна секция тайтлов, дескрипшинов и меток заменаяет другую при получении соответсвующих им инфопоршней. Всего 7 таких этапов. Инфопоршни используемые в задании выдаются также последовательно. Определяемыми являются те которые обновляются при спавне (jup_novikov_quest_zaton_scanner_create_№), а не при взятии предмета.На этом урок завершен.Файл с отработанным заданием можно скачать здесь: http://narod.ru/disk....ar.html Изменено 20 Сентября 2014 пользователем World_Stalker 2 - автор модов GA for SGM 1.7, серия "Смерти вопреки".- автор уроков квестостроения на X-Ray 1.6- работал в командах SGM, Spectrum Project (Путь во Мгле). Ссылка на комментарий
GEONЕZIS 20 Опубликовано 11 Июня 2012 Поделиться Опубликовано 11 Июня 2012 Создание квеста с добавлением дополнительных внутриэтапных подзаданий. Особенности- отсутствие диалогов, использование рестрикторов. Реализация на X-Ray 1.6 Автор урока: GEONEZIS Поставленная задача в данном уроке будет заключаться в обучении основным принципам создания среднего по сложности квеста в игре Сталкер Зов Припяти без использования каких-либо диалогов. Выдача задания будет осуществляться автоматически, в данном случае зададим ее при старте игры. Также будет показан прием добавления во внутреннею структуру основного задания нескольких дополнительных подквестов и объяснение применение рестриторов на всех поставленных этапах. Само задание следующее: При старте ГГ на ПДА придет сообщение о необходимости установки схронов. Осущесвляется выдача квеста. Необходимо забрать утерянные рюкзаки и заложить их в трех указанных точках. После этого задание автоматически завершается. Выдача награды не предусмотрена. Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_jupiter.xml -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_jupiter.ltx - quest_items.ltx - devices.ltx - death_generic.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - st_items_quest.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\misc\trade\) - trade_generic.ltx 5. конфигурационные в (gamedata\configs\ui\) - game_tutorials.xml 6. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов 7. скриптовый в (gamedata\scripts\) - ui_si.script - bind_stalker.script - new_tasks.script - xr_effects.script 8. all.spawn. (gamedata\spawns\) - alife_zaton.ltx На первоначальном этапе определимся с квестовыми предметами. Всего их шесть. Три будут отвечать за айтем рюкзака до его закладки. Они будут являться потомками основного родительского класса device_pda. Другие три будут определены иным классом, им будет соответствовать установленная логика и они отвечают за рюкзаки после установки схрона. Пропишем секции их конфигов в файле quest_items.ltx (Здесь и далее буду приводить конфиг только одной секции, остальные задаются аналогично только с изменением числовых значений в имени). [zat_example_taynik_1_item]:device_pda $spawn = "quest_items\zat_example_taynik_1_item" description = zat_example_taynik_item_descr inv_name = zat_example_taynik_item_name visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf inv_weight = 2 story_id = zat_example_taynik_1_item can_trade = false quest_item = true inv_grid_width = 2 inv_grid_height = 2 inv_grid_x = 0 inv_grid_y = 38 .......... [zat_example_taynik_1]:default_inventory_box custom_data = scripts\zaton\inventory_boxs\zat_example_taynik_1.ltx .......... Первый конфиг не содержит в себе прикрепленного файла в дополнительной секции и определяется как простой квестовый предмет, второй же содержит прикрепленный конфиг с логикой его zat_example_taynik_1.ltx Для определении секции zat_example_taynik_1 необходимо определить родительский класс default_inventory_box в файле devices.ltx [default_inventory_box] GroupControlSection = spawn_group discovery_dependency = $spawn = "devices\default_inventory_box" class = O_INVBOX cform = skeleton visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf script_binding = bind_physic_object.init radius = 3 inv_grid_width = 2 inv_grid_height = 2 inv_grid_x = 0 inv_grid_y = 38 cost = 3500 can_take = true inv_weight = 1.14 description = inv_name = inv_name_short = В этой секции указываются основные параметры такие как основной класс, форма, визуал. Кроме того определим его основную логику в конфигурационном файле zat_example_taynik_1.ltx logic] active = ph_idle@nothing [ph_idle@nothing] nonscript_usable = true tips = st_taynik_check_descr Здесь указывается активная секция это ph_idle@nothing, а также ее содержание. Тайник после установки можно использовать, т.е. возможно его наполнение различными предметами, также при наведении на него будет активна надпись из секции st_taynik_check_descr Зарегистрируем конфиги первой секции предмета тайник zat_example_taynik_..._item. В файле death_generic.ltx пропишем код ..... zat_example_taynik_1_item = true zat_example_taynik_2_item = true zat_example_taynik_3_item = true В файле ui_si.script добавим "zat_example_taynik_1_item", "zat_example_taynik_2_item", "zat_example_taynik_3_item", Обозначим секции, логику и работу рестрикторов необходимых для выполнения внутренних подквестов. В файле alife_zaton.ltx обозначим три секции [zaton_999999011] ; cse_abstract properties section_name = space_restrictor name = zat_test_quest_restrictor_1 position = 210.996811,15.980440,480.381104 direction = 0,0.841602981090546,0 ; cse_alife_object properties game_vertex_id = 6 distance = 0 level_vertex_id = 1323235 object_flags = 0xffffff3e custom_data = <<END [story_object] story_id = zat_restr_1_id [logic] cfg = scripts\zaton\zat_restr_logic_1.ltx END ; cse_shape properties shapes = shape0 shape0:type = box shape0:axis_x = 4,0,0 shape0:axis_y = 0,3.13100147247314,0 shape0:axis_z = 0,0,2 shape0:offset = 0,0,0 В секции указываются координаты и тип рестрикторов, их идентификатор, имя, тип и размер шейпа. В файле логики zat_restr_logic_1.ltx пропишем: [logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_test_quest_rest_main_come =actor_in_zone(zat_test_quest_restrictor_1) =actor_has_item(zat_example_taynik_1_item)} sr_idle@tutorial %=run_tutorial(zat_test_quest_1_tutor)% on_info2 = {+zat_test_quest_restr_1} sr_idle@nil [sr_idle@tutorial] on_info = {+zat_test_quest_rest_main_come !actor_in_zone(zat_test_quest_restrictor_1)} sr_idle@start %=stop_tutorial% on_info2 = {+zat_test_quest_restr_1} sr_idle@nil on_info3 = {!has_active_tutorial} sr_idle@start [sr_idle@nil] Отметим особенности: Активная секция sr_idle@start переход на вторую происходит по достижению трех условий - наличие инфопоршня активности второго этапа основного задания (zat_test_quest_rest_main_come) - актор находиться в зоне действия рестриктора - наличие в его инвентаре zat_example_taynik_1_item При выполнении всех этих условий выполняется работа рестриктора определяемая в туториале zat_test_quest_1_tutor При получении инфопоршня zat_test_quest_restr_1 происходит переход в третью нулевую секцию логики рестриктора sr_idle@nil При выхода актора из зоны рестриктора его работа прекращается и логика переключается во второе состояние sr_idle@tutorial из которого она может снова перейти в первое или в третье. Объявим в файле game_tutorials.xml туторы выполняемые в работе рестрикторов <zat_test_quest_1_tutor> <global_wnd/> <item> <disabled_key>quit</disabled_key> <length_sec/> <action id="use" finalize="1">xr_effects.zat_test_quest_1</action> <guard_key>use</guard_key> <grab_input>0</grab_input> <main_wnd> <auto_static start_time="0" length_sec="5000" x="512" y="660" width="300" height="60" alignment="c" stretch="1"la_cyclic="1" la_texture="1" la_alpha="1"> <text font="graffiti22" r="225" g="225" b="250" a="255" align="c">zat_test_quest_tips</text> </auto_static> </main_wnd> </item> </zat_test_quest_1_tutor> Основные параметры это функция скрипта обработчика действия xr_effects.zat_test_quest_1 и активная надпись из секции zat_test_quest_tips В файле xr_effects.scripts определим функции function zat_test_quest_1(actor, npc) if xr_conditions.actor_in_zone(actor, npc, {"zat_test_quest_restrictor_1"}) then remove_item(actor, npc, {"zat_example_taynik_1_item"}) alife():create("zat_example_taynik_1",vector():set(210.996811,15.980440,480.381104),1323235,6) db.actor:give_info_portion("zat_test_quest_restr_1") end end Опишем ее: - если выполнено условие нахождение актора в зоне рестриктора zat_test_quest_restrictor_1 то происходит удаление из инвентаря ГГ айтема первого конфига тайника zat_example_taynik_1_item, создается по заданным координатам второй zat_example_taynik_1 и выдается инфопоршень zat_test_quest_restr_1 Выдача задания будет происходит при старте ГГ одновременно с квестами основного сюжета. Для этого добавим инфопоршень выдачи и сам квест в секцию логики [sr_idle] оригинального рестриктор zat_b101_logic.ltx =give_task(geonezis_zat_test_example_task) +zat_test_quest_begin Выдача подквестов будет осуществлять в логике другого рестриктора zat_restr_logic_main.ltx Его секция прописывается в all.spawn по аналогии с предыдущими. Сама логика имеет следующий вид: [logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_test_quest_begin -zat_test_quest_rest_main_come =actor_in_zone(zat_test_quest_restrictor_main)} %=give_task(geonezis_zat_test_example_task_1) =give_task(geonezis_zat_test_example_task_2) =give_task(geonezis_zat_test_example_task_3) +zat_test_quest_rest_main_come% on_info2 = {+zat_test_quest_rest_main_come} sr_idle@nil [sr_idle@nil] В активной секции при попадании актора в зону рестриктора происходит выдача внутренних подквестов и переход логики в нулевое состояние. Определим сам квест с подзаданиями: [geonezis_zat_test_example_task] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = {+zat_test_quest_rest_main_come} zat_test_example_title1, {-zat_test_quest_rest_main_come} zat_test_example_title0 descr = {+zat_test_quest_rest_main_come} zat_test_example_text1, {-zat_test_quest_rest_main_come} zat_test_example_text0 target ={+zat_test_quest_rest_main_come} nil, {-zat_test_quest_rest_main_come} zat_restr_main_id condlist_0 = {+zat_test_quest_complete} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)% Подквесты: [geonezis_zat_test_example_task_1] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_1_title descr = zat_test_example_123_text target = zat_restr_1_id condlist_0 = {+zat_test_quest_restr_1} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)% Особенности: - При старте задания необходимо посетить зону основного рестриктора, устанавливается тагет на zat_restr_main_id. В момент посещения активируются подквесты, выдается инфопоршень zat_test_quest_rest_main_come, задание обновляется, его тагет уходит в nill. после взятия всех квестовых айтемов- необходимо завершение всех трех подквестов для получения инфопоршня zat_test_quest_complete Скриптовая функция которая отвечает за создание трех основных квестовых предметов и выдачу завершающего основное задание инфопоршня прописывается в файл new_tasks.script, и объявляется в апдейте актора файла bind_stalker.script new_tasks.task_spec() сама функция --/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_example_taynik_1_item",vector():set(248.498016,14.915686,484.567932),1391296,6) alife():create("zat_example_taynik_2_item",vector():set(247.778076,14.872326,484.085999),1390040,6) alife():create("zat_example_taynik_3_item",vector():set(247.055069,14.796996,483.116058),1388814,6) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо установить все тайники. Подбери рюкзаки оставленные сталкерами", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_restr_1") and has_alife_info("zat_test_quest_restr_2") and has_alife_info("zat_test_quest_restr_3") and not has_alife_info("zat_test_quest_complete") then db.actor:give_info_portion("zat_test_quest_complete") end end end Описание: При нахождении ГГ на локации Затон и наличии инфопоршня zat_test_quest_begin создаются квестовые айтемы и отправляется мессадж на пда ГГ. При завершении всех трех подквестов выдается инфопоршень zat_test_quest_complete завершения основного. Все инфопоршни необходимые нам пропишем в файле info_zaton.xml ..... <info_portion id="zat_test_quest_restr_1"></info_portion> <info_portion id="zat_test_quest_restr_2"></info_portion> <info_portion id="zat_test_quest_restr_3"></info_portion> <info_portion id="zat_test_quest_spawn_items"></info_portion> <info_portion id="zat_test_quest_begin"></info_portion> <info_portion id="zat_test_quest_complete"></info_portion> <info_portion id="zat_test_quest_rest_main_come"></info_portion> ..... Всю текстовую транскрипцию определим в соответствующий xml-файлах. Квестовые айтемы тайников можно занести в файлы торговли. На этом урок завершен. Файл с отработанным задание можно скачать тут: http://narod.ru/disk....ar.html 2 - автор модов GA for SGM 1.7, серия "Смерти вопреки".- автор уроков квестостроения на X-Ray 1.6- работал в командах SGM, Spectrum Project (Путь во Мгле). Ссылка на комментарий
GEONЕZIS 20 Опубликовано 26 Июня 2012 Поделиться Опубликовано 26 Июня 2012 Создание квеста с добавлением дополнительных внутриэтапных заданий. Особенности- отсутствие диалогов, использование физических объектов класса physic_destroyable_object в качестве квестовых предметов. Реализация на X-Ray 1.6 В данном уроке речь пойдет о реализации задания подобного тому что было рассмотрено в предыдущем уроке. В отличие от него теперь добавление внутриэтапных заданий будет завязано не на применение рестрикторов, а на использование физических объектов специального класса. Задание секций этих объектов будет осуществлено также как и в моде SGM (автор GeJorge) Еще одной особенностью будет добавление класса метки объекта (также по аналогии с SGM) что позволит отказаться от применения рестрикторов в определенных моментах. Выдача задания осуществляется при старте игры. Диалогов нет. Само задание: ГГ на ПДА приходит сообщение о необходимости обыска трех точек с установленными там объектами. Необходимо выяснить что это за объекты и вернуться в стартовую точку. После этого задание автоматически завершается. Выдача награды не предусмотрена. Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\models\) - dynamic_objects.ltx 5. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов и объектов 6. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 7. all.spawn. (gamedata\spawns\) - alife_zaton.ltx 8. физическая модель в (gamedata\meshes\dynamics\box\) - konteyner.ogf Некоторые этапы добавления изменений будут приведены с сокращением, ввиду их схожести с аналогичными в других уроках. Акцент будет сделан на впервые вносимые изменения и аспекты. Изначально создадим новые классы квестовых предметов. Класс родительского предмета метка будет соответствовать стандартному квестовому device_pda, но будет иметь визуал "нулевого значения". поэтому при написания квестов и установки тагета в них можно будет воспользоваться именно этим приемом, а не добавлением цели на индивидуальном айди отдельного рестриктора. пропишем в quest_items.ltx секцию [quest_spot]:device_pda $spawn = "devices\quest_spot" visual = dynamics\scene_objects\part\part_none.ogf can_take = false сами добавленные метки имеют следующие секции. как видим они являются потомками родительского класса quest_spot. также указывается айди метки по которому будет прописываться таргет story_id. [zat_test_stalker_container_1_spot]:quest_spot story_id = zat_test_stalker_container_1_spot [zat_test_stalker_container_2_spot]:quest_spot story_id = zat_test_stalker_container_2_spot [zat_test_stalker_container_3_spot]:quest_spot story_id = zat_test_stalker_container_3_spot Новый физический объект используемый нами в квесте объявим в файле dynamic_objects.ltx . Он будет иметь свой уникальный класс наследуемый от основного physic_destroyable_object Секции конфигов будут следующими: [box_quest_item]:physic_destroyable_object $spawn = "dynamic_objects\box\box_quest_item" visual = dynamics\box\konteyner.ogf [zat_test_stalker_container_1]:box_quest_item custom_data = scripts\zaton\inventory_boxs\zat_test_stalker_container_1.ltx [zat_test_stalker_container_2]:box_quest_item custom_data = scripts\zaton\inventory_boxs\zat_test_stalker_container_2.ltx [zat_test_stalker_container_3]:box_quest_item custom_data = scripts\zaton\inventory_boxs\zat_test_stalker_container_3.ltx В основной секции указывается физическая модель предмета visual. В уникальных секциях указываются секции конфигов custom_data Логика добавленных предметов будет задаваться в файлах zat_test_stalker_container_....ltx следующим образом: [logic] active = ph_idle@retranslator_take [ph_idle@retranslator_take] nonscript_usable = false tips = st_take_the_quest_item on_use = ph_idle@retranslator_heavy %+zat_test_quest_item_1_used% on_info = {+zat_test_quest_complete} sr_idle@nil [ph_idle@retranslator_heavy] nonscript_usable = false tips = st_quest_item_is_used on_info = {+zat_test_quest_complete} sr_idle@nil [sr_idle@nil] - активная секция логики ph_idle@retranslator_take - первоначальная активная надпись считывается из секции st_take_the_quest_item - при юзании предмета произойдет выдача инфопорции zat_test_quest_item_1_used и переход во вторую секцию логики ph_idle@retranslator_heavy - при этом изменяется активная надпись на st_quest_item_is_used - при получении инфопорции zat_test_quest_complete логика обнуляется. Теперь необходимо создать основной рестриктор на обход которого будет завязана основа квеста. Сам рестриктор создаем в all.spawn по аналоги с предыдущими уроками. Логика рестриктора из файла zat_restr_logic_main.ltx имеет следующий вид: [logic] active = sr_idle@start [sr_idle@start] on_info = {+zat_test_quest_begin -zat_test_quest_rest_main_come =actor_in_zone(zat_test_quest_restrictor_main)} %=give_task(geonezis_zat_test_example_task_1) =give_task(geonezis_zat_test_example_task_2) =give_task(geonezis_zat_test_example_task_3) +zat_test_quest_rest_main_come% on_info2 = {+zat_test_quest_rest_main_come} sr_idle@wait [sr_idle@wait] on_info = {+zat_test_quest_all_item_used -zat_test_quest_complete =actor_in_zone(zat_test_quest_restrictor_main)} %+zat_test_quest_complete% on_info2 = {+zat_test_quest_complete} sr_idle@nil [sr_idle@nil] разберем ее: - имеет три секции первая активная, во вторую переходит по совокупности полученных условий при обновлении квеста. - при этом происходит выдача трех подзаданий. - для перехода в нулевую секцию необходимо завершение задания. Выдача задания будет происходит при старте ГГ одновременно с квестами основного сюжета. Для этого добавим инфопоршень выдачи и сам квест в секцию логики [sr_idle] оригинального рестриктор zat_b101_logic.ltx =give_task(geonezis_zat_test_example_task) +zat_test_quest_begin Определим сам квест с подзаданиями: основной квест: [geonezis_zat_test_example_task] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = {+zat_test_quest_all_item_used} zat_test_example_title2, {+zat_test_quest_rest_main_come -zat_test_quest_all_item_used} zat_test_example_title1, {-zat_test_quest_rest_main_come} zat_test_example_title0 descr = {+zat_test_quest_all_item_used} zat_test_example_text2, {+zat_test_quest_rest_main_come -zat_test_quest_all_item_used} zat_test_example_text1, {-zat_test_quest_rest_main_come} zat_test_example_text0 target = {+zat_test_quest_all_item_used} zat_restr_main_id, {+zat_test_quest_rest_main_come -zat_test_quest_all_item_used} nil, {-zat_test_quest_rest_main_come} zat_restr_main_id condlist_0 = {+zat_test_quest_complete} complete on_complete = %=inc_faction_goodwill_to_actor(stalker:50)% внутренние подквесты (приведен только первый, два других по аналогии): [geonezis_zat_test_example_task_1] icon = ui_inGame2_Osobiy_zakaz prior = 1 storyline = false title = zat_test_example_1_title0 descr = zat_test_example_1_text0 target = zat_test_stalker_container_1_spot condlist_0 = {+zat_test_quest_item_1_used} complete Особенности: - При старте задания необходимо посетить зону основного рестриктора, устанавливается тагет на zat_restr_main_id. В момент посещения активируются подквесты, выдается инфопоршень zat_test_quest_rest_main_come, задание обновляется, его тагет уходит в nil. после юзания всех квестовых айтемов созданных в начале объектов проиходит завершение всех трех подквестов, основной квест обновляется снова. чтобы завершить его необходимо снова посетить точку основного рестриктора. Скриптовая функция которая отвечает за создание трех основных квестовых предметов и выдачу завершающего основное задание инфопоршня прописывается в файл new_tasks.script, и объявляется в апдейте актора файла bind_stalker.script new_tasks.task_spec() сама функция --/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_test_stalker_container_1_spot",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2_spot",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3_spot",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Для начала займи указанную точку", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_rest_main_come") and not has_alife_info("zat_test_quest_spawn_items_2") then alife():create("zat_test_stalker_container_1",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо исследовать все контейнеры.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items_2") end if has_alife_info("zat_test_quest_item_1_used") and has_alife_info("zat_test_quest_item_2_used") and has_alife_info("zat_test_quest_item_3_used") and not has_alife_info("zat_test_quest_all_item_used") then db.actor:give_info_portion("zat_test_quest_all_item_used") end end end описание: - первоначально по выдаче задания происходит создания меток дополнительных подквестов. - при выдачи самих подквестов происходит создание самих предметов необходимых для их выполнения. - при наличии трех инфопорций полученных от юзания всех предметов выдается общий инфопоршень на обновление основного задания. Все инфопоршни необходимые нам пропишем в файле info_zaton.xml Всю текстовую транскрипцию определим в xml-файлах. На этом урок завершен. Файл с отработанным задание можно скачать тут: http://narod.ru/disk....ar.html Создание квеста с добавлением дополнительных внутриэтапных заданий. Особенности- отсутствие диалогов, добавление тайников в качестве квестовых предметов. Реализация на X-Ray 1.6 Основной отличительной особенностью этого урока от предыдущего является только то, что выполнение внутренних подквестов будет завязано на исследовании тайников (взятие квестовых предметов из них). Будет показан принцип добавление в игру тайников определенных отдельным классом и их заполнение различными предметами. Поэтому урок будет приведен по максимуму сокращенно, с указанием только основных особенностей и списком всех используемых файлов. Полностью просмотреть вносимые изменения вы сможете скачав пример с отработанным заданием или же изучив материал из предыдущего урока. Необходимые для изменения файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml 4. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов и объектов 6. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 7. all.spawn. (gamedata\spawns\) - alife_zaton.ltx Определим в файле quest_items.ltx две родительские секции для создания предмета нового класса "квестовый рюкзак". [default_inventory_box] GroupControlSection = spawn_group discovery_dependency = $spawn = "devices\default_inventory_box" class = O_INVBOX cform = skeleton visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf script_binding = bind_physic_object.init radius = 3 inv_grid_width = 2 inv_grid_height = 2 inv_grid_x = 0 inv_grid_y = 38 cost = 3500 can_take = true inv_weight = 1.14 description = inv_name = inv_name_short = [quest_rukzak]:default_inventory_box $spawn = "devices\quest_rukzak" visual = dynamics\devices\dev_rukzak\dev_rukzak.ogf В дальнейшем нами будет использоваться переопределенный класс quest_rukzak с заданным нами визуалом dynamics\devices\dev_rukzak\dev_rukzak.ogf. В классе default_inventory_box определяются другие основные параметры. Вся остальная структура добавляемых изменений аналогично указанным ранее. По другом задается только основной квестовый скрипт в файле new_tasks.script --/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_begin") and not has_alife_info("zat_test_quest_spawn_items") then alife():create("zat_test_stalker_container_1_spot",vector():set(210.996811,15.980440,480.381104),1323235,6) alife():create("zat_test_stalker_container_2_spot",vector():set(267.914307,17.374102,483.001709),1424536,6) alife():create("zat_test_stalker_container_3_spot",vector():set(305.260254,18.979174,532.515625),1484018,287) news_manager.send_tip(db.actor, "Для начала займи указанную точку", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end if has_alife_info("zat_test_quest_rest_main_come") and not has_alife_info("zat_test_quest_spawn_items_2") then local x1_cell=alife():create("quest_rukzak",vector():set(210.996811,15.980440,480.381104),1323235,6) parse_table=utils.parse_spawns("zat_test_quest_item_info_1,af_medusa,wpn_ak74,stalker_outfit,wpn_pm") for k,v in pairs(parse_table) do for i=1,v.prob do alife():create(v.section,vector(),0,0,x1_cell.id) end end local x2_cell=alife():create("quest_rukzak",vector():set(267.914307,17.374102,483.001709),1424536,6) parse_table=utils.parse_spawns("zat_test_quest_item_info_2,af_ice,wpn_abakan,dolg_outfit,wpn_pm") for k,v in pairs(parse_table) do for i=1,v.prob do alife():create(v.section,vector(),0,0,x2_cell.id) end end local x3_cell=alife():create("quest_rukzak",vector():set(305.260254,18.979174,532.515625),1484018,287) parse_table=utils.parse_spawns("zat_test_quest_item_info_3,af_fire,wpn_lr300,svoboda_light_outfit,wpn_pm") for k,v in pairs(parse_table) do for i=1,v.prob do alife():create(v.section,vector(),0,0,x3_cell.id) end end news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо исследовать все тайники.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items_2") end if (not has_alife_info("zat_test_quest_item_1_used")) and has_alife_info("zat_test_quest_spawn_items_2") and db.actor:object("zat_test_quest_item_info_1") then db.actor:give_info_portion("zat_test_quest_item_1_used") end if (not has_alife_info("zat_test_quest_item_2_used")) and has_alife_info("zat_test_quest_spawn_items_2") and db.actor:object("zat_test_quest_item_info_2") then db.actor:give_info_portion("zat_test_quest_item_2_used") end if (not has_alife_info("zat_test_quest_item_3_used")) and has_alife_info("zat_test_quest_spawn_items_2") and db.actor:object("zat_test_quest_item_info_3") then db.actor:give_info_portion("zat_test_quest_item_3_used") end if has_alife_info("zat_test_quest_item_1_used") and has_alife_info("zat_test_quest_item_2_used") and has_alife_info("zat_test_quest_item_3_used") and not has_alife_info("zat_test_quest_all_item_used") then db.actor:give_info_portion("zat_test_quest_all_item_used") end end end Особенности: - при старте задания создаются квестовые метки - при достижении позиции актора внутри основного рестриктора происходит создание трех квестовых тайников quest_rukzak по заданным координатам и их заполнение различными предметами. - при обыски тайника и взятии ГГ квестового предмета из него происходит выдача инфопоршеней на завершение внутренних подзаданий. - после обыска всех трех тайников выдается основной инфопоршень на обновление основного задания. Файл с отработанным заданием можно скачать тут: http://narod.ru/disk....ar.html Автор уроков: Geonezis 1 - автор модов GA for SGM 1.7, серия "Смерти вопреки".- автор уроков квестостроения на X-Ray 1.6- работал в командах SGM, Spectrum Project (Путь во Мгле). Ссылка на комментарий
GEONЕZIS 20 Опубликовано 27 Июня 2012 Поделиться Опубликовано 27 Июня 2012 Создание однотипного квеста на одновременный поиск двух разных предметов. Особенности- использование элементарных скриптовых функций actor_has_item() Реализация на X-Ray 1.6 Итак, предположим нам необходимо создать простой квест для Зова Припяти на одновременный поиск двух различных предметов. Пусть идея квеста будет такой: Сыч дает ГГ поручение найти два артефакта Снежинка и Пламя. Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -character_desc_zaton.xml -dialogs_zaton.xml -info_zaton.xml -character_desc_general.xml (необязательно) 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_dialogs_zaton.xml - st_quests_zaton.xml 4. скриптовый в (gamedata\scripts\) - dialogs_zaton.script Для начала создадим два простеньких диалога для выдачи и завершения квеста. В файл dialogs_zaton.xml в самом низу добавим два диалога: На выдачу квеста: <dialog id="zat_b30_owl_stalker_trader_small_quests_begin"> <dont_has_info>zat_b30_owl_stalker_trader_quest_init</dont_has_info> <dont_has_info>zat_b30_owl_stalker_trader_quest_no_quest</dont_has_info> <precondition>dialogs_zaton.zat_b30_owl_stalker_trader_not_have_arts</precondition> <phrase_list> <phrase id="0"> <text>zat_b30_owl_stalker_trader_small_quests_0</text> <next>1</next> </phrase> <phrase id="1"> <text>zat_b30_owl_stalker_trader_small_quests_1</text> <next>2</next> <next>3</next> </phrase> <phrase id="2"> <text>zat_b30_owl_stalker_trader_small_quests_2</text> <give_info>zat_b30_owl_stalker_trader_quest_no_quest</give_info> </phrase> <phrase id="3"> <text>zat_b30_owl_stalker_trader_small_quests_3</text> <action>dialogs_zaton.zat_b30_owl_stalker_trader_give_quest</action> <next>4</next> </phrase> <phrase id="4"> <text>zat_b30_owl_stalker_trader_small_quests_4</text> <give_info>zat_b30_owl_stalker_trader_quest_init</give_info> </phrase> </phrase_list> </dialog> На завершение квеста: <dialog id="zat_b30_owl_stalker_trader_small_quests_end"> <has_info>zat_b30_owl_stalker_trader_quest_init</has_info> <dont_has_info>zat_b30_owl_stalker_trader_quest_end</dont_has_info> <precondition>dialogs_zaton.zat_b30_owl_stalker_trader_have_arts</precondition> <phrase_list> <phrase id="0"> <text>zat_b30_owl_stalker_trader_small_quests_5</text> <give_info>zat_b30_owl_stalker_trader_quest_end</give_info> <next>1</next> </phrase> <phrase id="1"> <text>zat_b30_owl_stalker_trader_small_quests_6</text> <next>2</next> </phrase> <phrase id="2"> <text>zat_b30_owl_stalker_trader_small_quests_7</text> <action>dialogs_zaton.zat_b30_owl_stalker_trader_relocates_arts</action> <next>3</next> </phrase> <phrase id="3"> <text>zat_b30_owl_stalker_trader_small_quests_8</text> <action>dialogs_zaton.zat_b30_owl_stalker_trader_relocates_money_to_actor</action> <next>4</next> </phrase> <phrase id="4"> <text>zat_b30_owl_stalker_trader_small_quests_9</text> <action>dialogs.break_dialog</action> </phrase> </phrase_list> </dialog> Пропишем их русскую транскрипцию в файле st_dialogs_zaton.xml Теперь разберем по порядку то что добавили. Диалог на выдачу квеста имеет следующую элементарную структуру: - ГГ предлагают задание и он на выбор может отказаться от него, тогда второй раз диалог уже не будет доступен. Либо же согласиться на исполение. - Соответсвенно происходит выдача инфопоршней zat_b30_owl_stalker_trader_quest_init (при старте квеста) и zat_b30_owl_stalker_trader_quest_no_quest (при отказе от выполнения). - Наличие в диалоге тегов <dont_has_info>имя поршня</dont_has_info> обеспечивает его блокировку при выборе одной из веток. - Наличие прекондишина <precondition>dialogs_zaton.zat_b30_owl_stalker_trader_have_arts</precondition> также блокирует стартовый диалог при наличии квестовых предметов (в данном случае это артефакты) в рюкзаке ГГ. - акшион <action>dialogs_zaton.zat_b30_owl_stalker_trader_give_quest</action> обеспечивает выдачу квеста. поясню особенности второго диалога: - наличие тега <has_info>zat_b30_owl_stalker_trader_quest_init</has_info> обеспечивает возможность инициализации диалога после выдачи квеста. - наличие <dont_has_info>zat_b30_owl_stalker_trader_quest_end</dont_has_info> обеспечивает блокировку диалога после завершение квеста. - прекондишн <precondition>dialogs_zaton.zat_b30_owl_stalker_trader_have_arts</precondition> обеспечивает блокирование диалога до момента наличия в инвентаре ГГ нужных квестовых предметов. - акшионы <action>dialogs_zaton.zat_b30_owl_stalker_trader_relocates_arts</action> и <action>dialogs_zaton.zat_b30_owl_stalker_trader_relocates_money_to_actor</action> обеспечивают передачу квестовых предметов от ГГ к НПС, и последующего денежного вознаграждения для ГГ от него. Объявим используемые инфопоршни в info_zaton.xml Добавим в конце файла код: <!-- New quest --> <info_portion id="zat_b30_owl_stalker_trader_quest_no_quest"></info_portion> <info_portion id="zat_b30_owl_stalker_trader_quest_init"></info_portion> <info_portion id="zat_b30_owl_stalker_trader_quest_end"></info_portion> Добавим наши диалоги НПС (В данном случае Сычу) для этого в файл character_desc_zaton.xml в его профиль <specific_character id="zat_b30_owl_stalker_trader" team_default="1"> добавим две строки диалогов ..... <actor_dialog>zat_b30_owl_stalker_trader_small_quests_begin</actor_dialog> <actor_dialog>zat_b30_owl_stalker_trader_small_quests_end</actor_dialog> ..... С диалогами и инфопоршнями разобрались теперь раccмотрим необходимые скриптовые функции: В файл dialogs_zaton.script добавим код function zat_b30_owl_stalker_trader_give_quest() task_manager.get_task_manager():give_task("geonezis_zat_b30_owl_quest") end function zat_b30_owl_stalker_trader_have_arts(first_speaker, second_speaker) return ((db.actor:object("af_ice") ~= nil) and (db.actor:object("af_fire") ~= nil)) end function zat_b30_owl_stalker_trader_not_have_arts(first_speaker, second_speaker) return ((db.actor:object("af_ice") == nil) and (db.actor:object("af_fire") == nil)) end function zat_b30_owl_stalker_trader_relocates_arts(first_speaker, second_speaker) dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, "af_ice") dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, "af_fire") end function zat_b30_owl_stalker_trader_relocates_money_to_actor(first_speaker, second_speaker) dialogs.relocate_money_to_actor(first_speaker, second_speaker, 30000) end Теперь по порядку разберем эти функции: - zat_b30_owl_stalker_trader_give_quest - выдача квеста - zat_b30_owl_stalker_trader_have_arts - возвращает true при проверки на наличие в инвентаре ГГ двух необходимвх предметов (в данном случае артефактов af_ice и af_fire) - zat_b30_owl_stalker_trader_not_have_arts- возвращает false при аналогичной проверке. - zat_b30_owl_stalker_trader_relocates_arts- передача НПС артефактов - zat_b30_owl_stalker_trader_relocates_money_to_actor- выдача денежной награды ГГ. Ну и самое основное это квест. В файле tm_zaton.ltx прописываем [geonezis_zat_b30_owl_quest] icon = ui_inGame2_Kontrakt_s_uchenimi prior = 2 storyline = false title = {=actor_has_item(af_ice) =actor_has_item(af_fire)} zat_b30_owl_stalker_trader_small_quest_title_3, {=actor_has_item(af_ice) !actor_has_item(af_fire)} zat_b30_owl_stalker_trader_small_quest_title_2, {!actor_has_item(af_ice) =actor_has_item(af_fire)} zat_b30_owl_stalker_trader_small_quest_title_1, zat_b30_owl_stalker_trader_small_quest_title_0 descr = {=actor_has_item(af_ice) =actor_has_item(af_fire)} zat_b30_owl_stalker_trader_small_quest_text_3, {=actor_has_item(af_ice) !actor_has_item(af_fire)} zat_b30_owl_stalker_trader_small_quest_text_2, {!actor_has_item(af_ice) =actor_has_item(af_fire)} zat_b30_owl_stalker_trader_small_quest_text_1, zat_b30_owl_stalker_trader_small_quest_text_0 target = {=actor_has_item(af_ice) =actor_has_item(af_fire)} zat_b30_owl_stalker_trader_id, nil condlist_0 = {+zat_b30_owl_stalker_trader_quest_end} complete Разберем то что происходит в процессе выполнения квеста и собственно его структуру. - [geonezis_zat_b30_owl_quest] - название задение в таск менеджере - icon = ui_inGame2_Kontrakt_s_uchenimi - иконка квеста (в данном случае от задания Контракт с Учеными) - prior = 2 - приоретет задания - storyline = false - сюжеткный ли квест или нет - title = - заголовки при обновлении задания - descr = - дескрипшины при обновлении задания - target = - цели, метки квеста при его обьнавлении. - condlist_0 =- кондишн (спец. условия) в квесте (в данном случае один на завершение) Основная особенность задания это последовательная проверка структурных условий посредством функции actor_has_item(...). Это вызываемая из xr_conditions.script функция на проверку наличия у актора того или иного предмета. Соответсвенно в структуре этого квеста используют два варианта когда значениее функции false (!actor_has_item(...)) и true (=actor_has_item(...)) В квесте рассматриваются все возможные сочетания вариантов наличия или отсутсвия найденного того или иного предмета. 1. когда нет ни одного. 2. первый (арт снежинка) есть, второго (арт пламя) нет. 3. первого нет, второй есть 4. оба есть. Соответсвенно в независимости от того какой арт был найден первым- произойдет точное обновление дескрипшина и титла задания с указанием текущего состояния. Также если игрок выложит из инвентаря уже найденный арт, то задание будет обновляться снова. Метка на цели в квесте (Сыч) появиться только при наличии обоих предметов. По выдачи инфопоршня zat_b30_owl_stalker_trader_quest_end квест будет завершен. Пропишим рускую транскрипцию дескрипшинов и тайтлов квеста в st_quests_zaton.xml По желанию для проверки в character_desc_general.xml при старте ГГ пропишем нужный арты. На этом урок завершен. Файл с отработанным заданием можно скачать здесь- http://narod.ru/disk....ar.html Создание примитивного квеста на поиск двух различных предметов, с выдачей ачивмента. Особенности- способ написания задание с его обновлением по инфопорциям, добавление по завершении простого достижения (ачивмента). Реализация на X-Ray 1.6 Поставленная в данном уроке задача схожа с той что была в предыдущем. Основным отличием от него будет являться способ реализации заданий такого типа. Если ранее основным обработчиком на обновление этапов квеста служило использование функций actor_has_item(...), то сейчас последовательное обновление будет осуществляться через выдачу соответствующих инфопорций. Будет подробно рассмотрена структура диалога в котором будет происходить их выдача. Также среди особенностей отметим добавление по завершении задания специального достижения. Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay) -character_desc_zaton.xml -dialogs_zaton.xml -info_zaton.xml -character_desc_general.xml (необязательно) 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - achievements.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_dialogs_zaton.xml - st_quests_zaton.xml - st_achievement.xml - ui_st_screen.xml 4. скриптовые в (gamedata\scripts\) - dialogs_zaton.script - xr_statistic.script Начнем с разбора процесса создания ачивмента, выдаваемого по завершении задания. Остальные этапы по написанию квеста будут сокращаны, ибо по большей части они уже были рассмотрены в предыдущем уроке. В файле achievements.ltx в самом низу добавим следующую секцию: [sich_helper] icon = ui_inGame2_Iskatel hint = st_sp_achievement_22_hint name = st_sp_achievement_22_name desc = st_sp_achievement_22_descr functor = xr_statistic.sich_helper_functor -[sich_helper]- уникальное имя секции ачивмента. его же необходимо зарегистрировать в начале файла в списке всех достижений. -icon- имя секции иконки достижения. берется из файла ui_actor_achivments.xml (\configs\ui\textures_descr\) в свою очередь сама иконка прописывается в ui_actor_achivments.dds (\textures\ui\) В данном случае возьмем стандартную иконку из другого достижения. - hint- описание в ПДА при наведении на ачивку. - name- название (имя) достижения. - desc- описание самого достижения. - functor- имя функции из xr_statistic.script отвечающей за срабатывания условий на получение достижения и собственно его выдача. Описание русской транскрипции добавим в файл st_achievement.xml <string id="st_sp_achievement_22_name"> <text>Помошник торговца</text> </string> <string id="st_sp_achievement_22_hint"> <text>Бандиты стали лучше к Вам относится.</text> </string> <string id="st_sp_achievement_22_descr"> <text>Вы нашли и принесли артефакты скряге Сычу. Тем самым Вы заслужили уважение бандитов.</text> </string> и в ui_st_screen.xml <string id="st_ach_sich_helper"> <text>Получено достижение «Помошник торговца».</text> </string> В xr_statistic.script добавляем исполняемую функцию: function sich_helper_functor() if not has_alife_info("sich_helper_achievement_gained") then if has_alife_info("zat_geonezis_example_quest_complete") then news_manager.send_tip(db.actor, "st_ach_sich_helper", nil, "seeker", nil, nil) xr_effects.inc_faction_goodwill_to_actor(db.actor, nil, {"bandit", 100}) db.actor:give_info_portion("sich_helper_achievement_gained") end end return has_alife_info("sich_helper_achievement_gained") end более подробно разберем работу данной функции: - происходит проверка, а не было ли уже получено данное достижение (отсутствие инфопоршня sich_helper_achievement_gained) - срабатывание условия выдачи достижения в данном случае условие только одно- это получение инфопоршня zat_geonezis_example_quest_complete (который будет выдаваться по завершению квеста) - далее происходит отправка на пда ГГ сообщения с текстом что достижение было получено. - вызывается обработчик функций на выполнение "бонуса" или "антибонуса" достижения. (в данном случае это только увеличение репутации у сталкеров) - выдается инфопоршень получения достижения (в рассматриваемом примере это sich_helper_achievement_gained) Так, теперь приступим к процессу формирования задания. Опишем подробно только второй диалог, который будет активен после взятия задания. Первый, на получения квеста можно будет посмотреть в файле dialogs_zaton.xml имя диалога- jup_azot_sborkiquest_init_dialog Соответственно русскую транскрипцию диалогов и квестов также не будем приводить. Ее можно будет увидеть в файлах st_quests_zaton.xml и st_dialogs_zaton.xml Код второго диалога следующий: <dialog id="jup_azot_sborkiquest_find_dialog"> <has_info>jup_azot_quest_sborki_give</has_info> <precondition>dialogs_zaton.actor_has_first_or_second_grenader_item</precondition> <phrase_list> <phrase id="0"> <text>jup_azot_quest_sborki_find_begin</text> <next>1</next> </phrase> <phrase id="1"> <text>jup_azot_quest_sborki_find_what</text> <next>11</next> <next>12</next> <next>13</next> <next>14</next> </phrase> <phrase id="11"> <text>jup_azot_quest_sborki_find_first_item</text> <precondition>dialogs_zaton.if_actor_has_zat_grenader_stalker_flash</precondition> <action>dialogs_zaton.transfer_zat_grenader_stalker_flash</action> <action>dialogs_jupiter.jup_b43_reward_for_first_artefact</action> <give_info>jup_azot_quest_sborki1_done</give_info> <next>111</next> <next>112</next> </phrase> <phrase id="111"> <text>jup_azot_quest_sborki_find_item_flash</text> <dont_has_info>jup_azot_quest_sborki2_done</dont_has_info> </phrase> <phrase id="112"> <text>jup_azot_quest_sborki_find_item_all</text> <has_info>jup_azot_quest_sborki2_done</has_info> <has_info>jup_azot_quest_sborki1_done</has_info> </phrase> <phrase id="12"> <text>jup_azot_quest_sborki_find_second_item</text> <precondition>dialogs_zaton.if_actor_has_zat_grenader_stalker_gran_instrument</precondition> <action>dialogs_zaton.transfer_zat_grenader_stalker_gran_instrument</action> <action>dialogs_jupiter.jup_b43_reward_for_second_artefact</action> <give_info>jup_azot_quest_sborki2_done</give_info> <next>121</next> <next>122</next> </phrase> <phrase id="121"> <text>jup_azot_quest_sborki_find_item_instr</text> <dont_has_info>jup_azot_quest_sborki1_done</dont_has_info> </phrase> <phrase id="122"> <text>jup_azot_quest_sborki_find_item_all</text> <has_info>jup_azot_quest_sborki2_done</has_info> <has_info>jup_azot_quest_sborki1_done</has_info> </phrase> <phrase id="13"> <text>jup_azot_quest_sborki_find_first_or_second_item</text> <precondition>dialogs_zaton.actor_has_first_and_second_grenader_item</precondition> <action>dialogs_zaton.transfer_zat_grenader_stalker_flash</action> <action>dialogs_zaton.transfer_zat_grenader_stalker_gran_instrument</action> <action>dialogs_jupiter.jup_b43_reward_for_both_artefacts</action> <give_info>jup_azot_quest_sborki1_done</give_info> <give_info>jup_azot_quest_sborki2_done</give_info> <next>131</next> </phrase> <phrase id="131"> <text>jup_azot_quest_sborki_find_end</text> </phrase> <phrase id="14"> <text>jup_azot_quest_sborki_find_nothing</text> <action>dialogs.break_dialog</action> </phrase> </phrase_list> </dialog> начнем по-порядку разбирать особенности этого диалога: - обязательными условиями его активации будет наличие инфопоршня выдачи задания jup_azot_quest_sborki_give, а также функции прекондишина actor_has_first_or_second_grenader_item - будет происходить выбор четырех последующих фраз для генерации в зависимости от наличия у ГГ квестовых предметов. - четвертая, имеющая нулевое значение отрицания- будет активна при любых условиях. - первая и вторая- когда у ГГ есть один из двух необходимых предметов активны при наличии выполнения соответствующих прекондишинов if_actor_has_zat_grenader_stalker_flash и if_actor_has_zat_grenader_stalker_gran_instrument. при этом проиходит передача этого предмета НПС функции (transfer_....),получении от НПС награды на каждом этапе и выдача инфопорции на обновление задания. первый и второй этапы- взаимоисключающие. одновременно они не могут быть активны. - третья- когда у ГГ есть оба необходимых предмета. происходит их передача и завершение квеста. добавим все скриптовые функции в файл dialogs_zaton.script function jup_azot_quest_sborki_give() task_manager.get_task_manager():give_task("geonezis_azot_quest_sborki_give") end function zat_b33_relocate_money_to_azot(first_speaker, second_speaker) dialogs.relocate_money_from_actor(first_speaker, second_speaker, 500) end function actor_has_first_or_second_grenader_item(first_speaker, second_speaker) return first_speaker:object("af_baloon") ~= nil or first_speaker:object("af_gold_fish") ~= nil end function actor_has_first_and_second_grenader_item(first_speaker, second_speaker) return first_speaker:object("af_baloon") ~= nil and first_speaker:object("af_gold_fish") ~= nil end function if_actor_has_zat_grenader_stalker_flash(first_speaker, second_speaker) return first_speaker:object("af_baloon") ~= nil and first_speaker:object("af_gold_fish") == nil end function if_actor_has_zat_grenader_stalker_gran_instrument(first_speaker, second_speaker) return first_speaker:object("af_gold_fish") ~= nil and first_speaker:object("af_baloon") == nil end function transfer_zat_grenader_stalker_flash(first_speaker, second_speaker) dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, "af_baloon") end function transfer_zat_grenader_stalker_gran_instrument(first_speaker, second_speaker) dialogs.relocate_item_section_from_actor(first_speaker, second_speaker, "af_gold_fish") end Описывать их нет смысла- они все элементарные. Аналогично не будем расписывать процесс добавления диалогов нпс и регистрацию инфопоршней. Все это приведено в предыдущем уроке. Отметим особенности квеста. В файле tm_zaton.ltx добавим код задания --|> [geonezis_azot_quest_sborki_give] icon = ui_inGame2_Kontrakt_s_uchenimi prior = 1 storyline = false title = {+jup_azot_quest_sborki2_done -jup_azot_quest_sborki1_done} zat_sich_bring_1_name, {+jup_azot_quest_sborki1_done -jup_azot_quest_sborki2_done} zat_sich_bring_2_name, {+jup_azot_quest_sborki1_done +jup_azot_quest_sborki2_done} zat_sich_thanks_for_2_items_name, {-jup_azot_quest_sborki1_done -jup_azot_quest_sborki2_done} zat_sich_sborki_started_name descr = {+jup_azot_quest_sborki2_done -jup_azot_quest_sborki1_done} zat_sich_bring_1_text, {+jup_azot_quest_sborki1_done -jup_azot_quest_sborki2_done} zat_sich_bring_2_text, {+jup_azot_quest_sborki1_done +jup_azot_quest_sborki2_done} zat_sich_thanks_for_2_items_text, {-jup_azot_quest_sborki1_done -jup_azot_quest_sborki2_done} zat_sich_sborki_started_text target = zat_b30_owl_stalker_trader_id condlist_0 = {+jup_azot_quest_sborki1_done +jup_azot_quest_sborki2_done} complete condlist_1 = {+jup_azot_quest_sborki_give =is_squad_enemy_to_actor(zat_b30_owl_stalker_trader_squad)} fail on_complete = %+zat_geonezis_example_quest_complete% reward_money = 10000 Тайтлы и дескрипшины задания будут обновляться после второго разговора с НПС, при получении соответствующих инфопоршней. То есть основное отличие от задания из урока № 33 это его обновление после передачи предметов, а не при их получении и наличии в инвентаре ГГ. По завершении задания будет выдаваться инфопоршень zat_geonezis_example_quest_complete необходимый для выдачи ачивмента, который в свою очередь будет теперь необходим для разблокировки следующего смыслового диалога zat_b30_owl_stalker_trader_buy_info На этом урок завершен. Скачать пример можно тут: http://narod.ru/disk....ar.html Автор уроков: Geonezis Добавлено через 9 мин.: Создание сложного квеста с использованием объекта класса inventory_box. Особенности- отсутствие диалогов, использование рестрикторов, выдача тайника в качестве награды. Реализация на X-Ray 1.6 Поставленная задача в данном уроке будет заключаться в обучении основным принципам создания сложного квеста в игре Сталкер Зов Припяти с добавление объекта класса inventory_box. Выдача задания будет осуществляться автоматически, в данном случае зададим ее при старте игры. Также будет показан пример задания сложной логики добавленного объекта и ее возможная привязка в процессе реализации квестов. Само задание будет следующим. При старте ГГ будет получено сообщение о необходимости поиска схрона на территории Земснаряда. Чтобы открыть этот схрон необходимо использоваться два специальных ключа. Нужно будет найти эти отмычки и использовать их для получения доступа к содержимому объекта. После этого квест автоматически завершается. Вместо получения денежной награды происходит выдача координат тайника, также дополнительно добавленного нами. Необходимые для редактирования файлы: 1. конфигурационные в (gamedata\configs\gameplay\) -info_zaton.xml 2. конфигурационные в (gamedata\configs\misc\) - tm_zaton.ltx - quest_items.ltx - secret_zaton.ltx 3. конфигурационные в (gamedata\configs\text\rus\) - st_quests_zaton.xml - st_items_quest.xml - ui_st_screen.xml 4. конфигурационные в (gamedata\configs\scripts\zaton\) - файлы логик рестрикторов 5. скриптовый в (gamedata\scripts\) - bind_stalker.script - new_tasks.script 6. all.spawn. (gamedata\spawns\) - alife_zaton.ltx Полный процесс регистрации квестовых предметов во всех файлах и некоторые повторяющиеся моменты не будет описаны, они аналогичны предыдущим урокам. Также текстовая транскрипция будет приведена только в файле с отработанным заданием. Первоначально создадим новый тайник который будет выдан нам в качестве награды по завершению квеста. - в файле secret_zaton.ltx добавим тайник в общий список zat_hiding_place_56 и объявим его секцию [zat_hiding_place_56] wpn_vintorez = 1, 1 в нем будет находиться один предмет- винторез. - создадим секцию рестриктора тайника и сам предмет через all.spawn [zaton_1867] ; cse_abstract properties section_name = space_restrictor name = zat_hiding_place_56 position = -443.072845458984,11.5764598846436,-51.894603729248 direction = 0.000881000014487654,-0.242430001497269,-0.0560249984264374 ; cse_alife_object properties game_vertex_id = 253 distance = 0 level_vertex_id = 118142 object_flags = 0xffffef3e custom_data = <<END [secret] cfg = misc\secret_zaton.ltx END ; cse_shape properties shapes = shape0 shape0:type = sphere shape0:offset = 0,0,0 shape0:radius = 1 ; cse_alife_space_restrictor properties restrictor_type = 3 указывается уникальное имя, координаты спанва и файл конфига. [zaton_1868] ; cse_abstract properties section_name = wpn_vintorez name = zaton_hiding_wpn_vintorez_1 position = -443.072845458984,11.5764598846436,-51.894603729248 direction = -0.0467090010643005,0.650978982448578,1.5079699754715 ; cse_alife_object properties game_vertex_id = 253 distance = 0 level_vertex_id = 118142 object_flags = 0xffffff0f custom_data = <<END [secret] name = zat_hiding_place_56 END ; cse_visual properties visual_name = dynamics\weapons\wpn_vintorez\wpn_vintorez ; cse_alife_item properties condition = 1 upgrades = ; cse_alife_item_weapon properties ammo_current = 90 upd:condition = 255 upd:weapon_flags = 0 upd:ammo_elapsed = 0 upd:addon_flags = 0 upd:ammo_type = 0 upd:weapon_state = 0 upd:weapon_zoom = 0 upd:current_fire_mode = 0 upd:grenade_mode = 0 указывается визуал модели предмета и принадлежность к тайнику. Теперь создадим квестовый объект класса inventory_box В файле алл спавна alife_zaton.ltx добавим секцию [zaton_1866] ; cse_abstract properties section_name = inventory_box name = zat_test_container position = 415.890075683594,-3.38021898269653,231.797317504883 direction = 0.000230999998166226,-0.715035021305084,-0.000265999988187104 ; cse_alife_object properties game_vertex_id = 7 distance = 0 level_vertex_id = 1647866 object_flags = 0xffffff3f custom_data = <<END [story_object] story_id = zat_test_cont_id [logic] cfg = scripts\zaton\zat_test_conteiner.ltx END ; cse_visual properties visual_name = dynamics\equipments\quest\safe_container ; cse_alife_inventory_box properties tip = inventory_box_use указывается: - класс объекта section_name - уникальное имя секции name - координаты точки спавна - прикрепленный файл логики cfg - идентификатор для установления метки таргета квеста story_id - визуал модели объекта - тип объекта зададим логику нашего объекта в файле zat_test_conteiner.ltx следующим образом: [logic] active = ph_idle@full_locked [ph_idle@full_locked] nonscript_usable = false tips = zat_test_conteiner_full_locked on_info = {=actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2)} ph_idle@has_two_key, {=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)} ph_idle@has_one_key, {=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@has_one_key on_info2 = {+zat_test_conteiner_open} ph_idle@open, {+zat_test_one_lock_open} ph_idle@locked on_use = {!actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} %+zat_test_quest_find_to_open =spawn_object_in(zat_test_container_item:zat_test_cont_id)% [ph_idle@has_one_key] nonscript_usable = false tips = zat_test_conteiner_has_one_key on_use = {=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)} ph_idle@locked %=remove_item(zat_test_key_1) =play_sound(power_switch) +zat_test_one_lock_open%, {=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@locked %=remove_item(zat_test_key_2) =play_sound(power_switch) +zat_test_one_lock_open% on_info = {=actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2)} ph_idle@has_two_key, {!actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@full_locked on_info2 = {+zat_test_conteiner_open} ph_idle@open, {+zat_test_one_lock_open} ph_idle@locked [ph_idle@locked] nonscript_usable = false tips = zat_test_conteiner_locked on_info = {=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)} ph_idle@locked_has_second_key, {=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@locked_has_second_key on_info2 = {+zat_test_conteiner_open} ph_idle@open [ph_idle@locked_has_second_key] nonscript_usable = false tips = zat_test_conteiner_has_one_key on_use = {=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)} ph_idle@open %=remove_item(zat_test_key_1) =play_sound(power_switch) +zat_test_conteiner_open%, {=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@open %=remove_item(zat_test_key_2) =play_sound(power_switch) +zat_test_conteiner_open% on_info = {!actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@locked on_info2 = {+zat_test_conteiner_open} ph_idle@open [ph_idle@has_two_key] nonscript_usable = false tips = zat_test_conteiner_has_two_key on_use = {=actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2)} ph_idle@open %=play_sound(power_switch) =remove_item(zat_test_key_1) =remove_item(zat_test_key_2) +zat_test_conteiner_open% on_info = {=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)} ph_idle@has_one_key, {=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@has_one_key, {!actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)} ph_idle@full_locked on_info2 = {+zat_test_conteiner_open} ph_idle@open [ph_idle@open] nonscript_usable = true tips = zat_test_conteiner_open on_info = {-zat_test_conteiner_open} %+zat_test_conteiner_open% Теперь более подробно ее разберем. имеющийся у нас схрон (предмет с данной логикой) будет иметь 6 секций возможного состояния. Нам необходимо открыть его используя два ключа. Поэтому возможны следующие варианты: - ящик закрыт. ph_idle@full_locked - использован один из ключей ph_idle@locked - у актора есть один из ключей ph_idle@has_one_key - у актора есть второй ключ при условии что был уже использован любой из первых. ph_idle@locked_has_second_key - у актора сразу есть два ключаph_idle@has_two_key - ящик вскрыт.ph_idle@open Общая конструкция секций логики: - состоянии запрета использования обработчика nonscript_usable будет true только в одном случае когда ящик открыт. - строка с используемой секции надписи указывается в tips сама транскрипция задается в ui_st_screen.xml - вызываемое действие определяется в on_use- происходит переход в одно из последующих состояний и удаление предметов. - активное состояние определяется из условий on_info Теперь по порядку разберем каждую из секций. В принципе сложного в построении такой логике ничего нет, решается обыкновенная комбинаторная задача сочетания двух объектов, когда первый ключ есть, второго нет: наоборот второй есть, первого нет; обо есть; ни одного нет. - активное состояние ph_idle@full_locked- ящик закрыт. изначально необходимо его использовать чтобы произошло обновление квеста (выдача инфопорции +zat_test_quest_find_to_open) и спавн внутрь него необходимого нам предмета (=spawn_object_in(zat_test_container_item:zat_test_cont_id)). это действие возможно только когда ключей у актора нет (!actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)). если мы сразу нашли оба ключа (=actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2)) то происходит переход в секцию ph_idle@has_two_key если у гг есть один ключ, но нет другого (не важно какого) то активируется секция ph_idle@has_one_key вторые условия on_info2 следующие: при получении инфопорции zat_test_conteiner_open происходит переход в ph_idle@open, соответственно при получении zat_test_one_lock_open становиться активной ph_idle@locked - у актора есть один из ключей ph_idle@has_one_key вне зависимости от того какой из ключей был найден при юзании ящика происходит вскрытие одного замка, переход в секцию ph_idle@locked и выполняются следующие действия %=remove_item(zat_test_key_....) =play_sound(power_switch) +zat_test_one_lock_open% удаляется один из ключей из инвентаря ГГ, проигрывается звук вскрытия замка, выдается соответствующий инфопоршень вскрытия. - один из ключей уже использован, второй нет. ph_idle@locked это переходная секция юзание ящика при этом невозможно. вне зависимости от того какой ключ есть у ГГ (=actor_has_item(zat_test_key_1) !actor_has_item(zat_test_key_2)) или (=actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)) будет осуществлен переход в секцию ph_idle@locked_has_second_key дополнительное условие наличие инфопорции zat_test_conteiner_open переход в ph_idle@open - один из ключей использован, второй в наличии. ph_idle@locked_has_second_key при наличии одного из двух ключей =actor_has_item(zat_test_key_...) !actor_has_item(zat_test_key_...) во время юзания происходит переход в секцию ph_idle@open,удаляется один из ключей, проигрывается звук вскрытия, выдается соответствующий инфопоршень. основное условие нет ни одного ключа- !actor_has_item(zat_test_key_2) !actor_has_item(zat_test_key_1)происходит переход в состояние ожидания ph_idle@locked дополнительное условие аналогично. - есть оба ключа. ph_idle@has_two_key при наличии обоих ключей =actor_has_item(zat_test_key_1) =actor_has_item(zat_test_key_2) оба они удаляются. происходит переход в ph_idle@open условия при этом- возвращения в необходимые секции когда либо ключей нет, либо есть по одному. - ключи заюзаны. ph_idle@open ящик вскрыт- можно забирать инвентарное содержимое. Квестовые предметы- ключи (zat_test_key_1, zat_test_key_2) и необходимый для получения из схрона предмет zat_test_container_item добавим в quest_items.ltx [zat_test_key_1]:dev_flash_1 $spawn = "quest_items\zat_test_key_1" visual = dynamics\equipments\quest\key.ogf description = st_zat_test_key_1_descr inv_name = st_zat_test_key_1 inv_name_short = st_zat_test_key_1 can_trade = false quest_item = true cost = 0 inv_grid_width = 1 inv_grid_height = 1 inv_grid_x = 4 inv_grid_y = 15 [zat_test_key_2]:dev_flash_2 $spawn = "quest_items\zat_test_key_2" visual = dynamics\equipments\quest\key.ogf description = st_zat_test_key_2_descr inv_name = st_zat_test_key_2 inv_name_short = st_zat_test_key_2 can_trade = false quest_item = true cost = 0 inv_grid_width = 1 inv_grid_height = 1 inv_grid_x = 4 inv_grid_y = 15 [zat_test_container_item]:device_pda $spawn = "quest_items\zat_test_container_item" visual = dynamics\equipments\quest\notes_document_case_3.ogf inv_weight = 0.05 inv_grid_width = 2 inv_grid_height = 1 inv_grid_x = 18 inv_grid_y = 20 $prefetch = 16 description = st_zat_test_container_item_descr inv_name = st_zat_test_container_item inv_name_short = st_zat_test_container_item can_trade = false quest_item = true cost = 0 Сам квест имеет следующий вид: --|> [geonezis_test_quest] icon = ui_inGame2_Karti_mestnosti prior = 1 storyline = false title = {+zat_test_quest_find_to_open} zat_test_quest_title1, {-zat_test_quest_find_to_open} zat_test_quest_title0 descr = {+zat_test_quest_find_to_open} zat_test_quest_text1, {-zat_test_quest_find_to_open} zat_test_quest_text0 target = {+zat_test_quest_find_to_open} zat_test_cont_id, {-zat_test_quest_find_to_open} zat_test_cont_id condlist_0 = {=actor_has_item(zat_test_container_item)} complete on_complete = %+zat_test_quest_complete% ;=give_treasure(zat_hiding_place_31:zat_hiding_place_49 В принципе он элементарный. До первого юзания ящика активна первая секция, после активна секция на поиск ключей. Квест завершается при наличии у ГГ необходимого и взятого из ящика предмета =actor_has_item(zat_test_container_item) Скрипт на спавн ключей будет иметь следующий вид: --/Квест Example function task_spec() local level_name=level.name() if level_name=="zaton" then if has_alife_info("zat_test_quest_find_to_open") and not has_alife_info("zat_test_quest_spawn_items") then local rnd_quest_items_1=math.random(1,2) if rnd_quest_items_1==1 then alife():create("zat_test_key_1",vector():set(369.470,-5.291,281.921),1579200,67) alife():create("zat_test_key_2",vector():set(368.114,-5.228,281.887),1577301,67) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо вскрыть заблокированный модуль. Для этого необходимо найти два ключа оставленные в тайниках сталкерами.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") elseif rnd_quest_items_1==2 then alife():create("zat_test_key_1",vector():set(366.925,-5.202,281.718),1575412,67) alife():create("zat_test_key_2",vector():set(365.569,-5.450,281.175),1573410,67) news_manager.send_tip(db.actor, "Чтобы выполнить тестовое задание необходимо вскрыть заблокированный модуль. Для этого необходимо найти два ключа оставленные в тайниках сталкерами.", nil, nil, 14000) db.actor:give_info_portion("zat_test_quest_spawn_items") end end if has_alife_info("zat_test_quest_complete") and not has_alife_info("zat_test_quest_tainik_give") then treasure_manager.get_treasure_manager():give_treasure("zat_hiding_place_56") db.actor:give_info_portion("zat_test_quest_tainik_give") end end end ключи спавняться рандомно в двух точках, после первого юзания ящика (получении инфопоршня zat_test_quest_find_to_open) Выдача тайника происходит по завершении квеста. Может быть сделано это двумя способами или внутри скрипта, или внутри задания. Включение квестового скрипта в обработку аналогично как и в других уроках. Выдача самого квеста на старте игры также по аналогии. Скачать файл с уроком можно по ссылке http://narod.ru/disk....ar.html Автор уроков: Geonezis 1 - автор модов GA for SGM 1.7, серия "Смерти вопреки".- автор уроков квестостроения на X-Ray 1.6- работал в командах SGM, Spectrum Project (Путь во Мгле). Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти